]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/FfsInfStatement.py
BaseTools: use predefined constants instead of local strings
[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 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 from Common.Expression import *
50 from Common.DataType import TAB_COMMON
51
52 ## generate FFS from INF
53 #
54 #
55 class FfsInfStatement(FfsInfStatementClassObject):
56 ## The mapping dictionary from datum type to its maximum number.
57 _MAX_SIZE_TYPE = {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}
58 ## The constructor
59 #
60 # @param self The object pointer
61 #
62 def __init__(self):
63 FfsInfStatementClassObject.__init__(self)
64 self.TargetOverrideList = []
65 self.ShadowFromInfFile = None
66 self.KeepRelocFromRule = None
67 self.InDsc = True
68 self.OptRomDefs = {}
69 self.PiSpecVersion = '0x00000000'
70 self.InfModule = None
71 self.FinalTargetSuffixMap = {}
72 self.CurrentLineNum = None
73 self.CurrentLineContent = None
74 self.FileName = None
75 self.InfFileName = None
76 self.OverrideGuid = None
77 self.PatchedBinFile = ''
78 self.MacroDict = {}
79 self.Depex = False
80
81 ## GetFinalTargetSuffixMap() method
82 #
83 # Get final build target list
84 def GetFinalTargetSuffixMap(self):
85 if not self.InfModule or not self.CurrentArch:
86 return []
87 if not self.FinalTargetSuffixMap:
88 FinalBuildTargetList = GenFdsGlobalVariable.GetModuleCodaTargetList(self.InfModule, self.CurrentArch)
89 for File in FinalBuildTargetList:
90 self.FinalTargetSuffixMap.setdefault(os.path.splitext(File)[1], []).append(File)
91
92 # Check if current INF module has DEPEX
93 if '.depex' not in self.FinalTargetSuffixMap and self.InfModule.ModuleType != "USER_DEFINED" \
94 and not self.InfModule.DxsFile and not self.InfModule.LibraryClass:
95 ModuleType = self.InfModule.ModuleType
96 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
97
98 if ModuleType != DataType.SUP_MODULE_USER_DEFINED:
99 for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys():
100 if LibraryClass.startswith("NULL") and PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]:
101 self.InfModule.LibraryClasses[LibraryClass] = PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]
102
103 StrModule = str(self.InfModule)
104 PlatformModule = None
105 if StrModule in PlatformDataBase.Modules:
106 PlatformModule = PlatformDataBase.Modules[StrModule]
107 for LibraryClass in PlatformModule.LibraryClasses:
108 if LibraryClass.startswith("NULL"):
109 self.InfModule.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
110
111 DependencyList = [self.InfModule]
112 LibraryInstance = {}
113 DepexList = []
114 while len(DependencyList) > 0:
115 Module = DependencyList.pop(0)
116 if not Module:
117 continue
118 for Dep in Module.Depex[self.CurrentArch, ModuleType]:
119 if DepexList != []:
120 DepexList.append('AND')
121 DepexList.append('(')
122 DepexList.extend(Dep)
123 if DepexList[-1] == 'END': # no need of a END at this time
124 DepexList.pop()
125 DepexList.append(')')
126 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
127 break
128 for LibName in Module.LibraryClasses:
129 if LibName in LibraryInstance:
130 continue
131 if PlatformModule and LibName in PlatformModule.LibraryClasses:
132 LibraryPath = PlatformModule.LibraryClasses[LibName]
133 else:
134 LibraryPath = PlatformDataBase.LibraryClasses[LibName, ModuleType]
135 if not LibraryPath:
136 LibraryPath = Module.LibraryClasses[LibName]
137 if not LibraryPath:
138 continue
139 LibraryModule = GenFdsGlobalVariable.WorkSpace.BuildObject[LibraryPath, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
140 LibraryInstance[LibName] = LibraryModule
141 DependencyList.append(LibraryModule)
142 if DepexList:
143 Dpx = DependencyExpression(DepexList, ModuleType, True)
144 if len(Dpx.PostfixNotation) != 0:
145 # It means this module has DEPEX
146 self.FinalTargetSuffixMap['.depex'] = [os.path.join(self.EfiOutputPath, self.BaseName) + '.depex']
147 return self.FinalTargetSuffixMap
148
149 ## __InfParse() method
150 #
151 # Parse inf file to get module information
152 #
153 # @param self The object pointer
154 # @param Dict dictionary contains macro and value pair
155 #
156 def __InfParse__(self, Dict = {}):
157
158 GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)
159
160 self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')
161 if len(self.InfFileName) > 1 and self.InfFileName[0] == '\\' and self.InfFileName[1] == '\\':
162 pass
163 elif self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :
164 self.InfFileName = self.InfFileName[1:]
165
166 if self.InfFileName.find('$') == -1:
167 InfPath = NormPath(self.InfFileName)
168 if not os.path.exists(InfPath):
169 InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath)
170 if not os.path.exists(InfPath):
171 EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName))
172
173 self.CurrentArch = self.GetCurrentArch()
174 #
175 # Get the InfClass object
176 #
177
178 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
179 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
180 if ErrorCode != 0:
181 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
182
183 #
184 # Cache lower case version of INF path before processing FILE_GUID override
185 #
186 InfLowerPath = str(PathClassObj).lower()
187 if self.OverrideGuid:
188 PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)
189 if self.CurrentArch is not None:
190
191 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
192 #
193 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
194 #
195 self.BaseName = Inf.BaseName
196 self.ModuleGuid = Inf.Guid
197 self.ModuleType = Inf.ModuleType
198 if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
199 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']
200 if Inf.AutoGenVersion < 0x00010005:
201 self.ModuleType = Inf.ComponentType
202 self.VersionString = Inf.Version
203 self.BinFileList = Inf.Binaries
204 self.SourceFileList = Inf.Sources
205 if self.KeepReloc is None and Inf.Shadow:
206 self.ShadowFromInfFile = Inf.Shadow
207
208 else:
209 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
210 self.BaseName = Inf.BaseName
211 self.ModuleGuid = Inf.Guid
212 self.ModuleType = Inf.ModuleType
213 if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
214 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']
215 self.VersionString = Inf.Version
216 self.BinFileList = Inf.Binaries
217 self.SourceFileList = Inf.Sources
218 if self.BinFileList == []:
219 EdkLogger.error("GenFds", GENFDS_ERROR,
220 "INF %s specified in FDF could not be found in build ARCH %s!" \
221 % (self.InfFileName, GenFdsGlobalVariable.ArchList))
222
223 if self.OverrideGuid:
224 self.ModuleGuid = self.OverrideGuid
225
226 if len(self.SourceFileList) != 0 and not self.InDsc:
227 EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))
228
229 if self.ModuleType == 'SMM_CORE' and int(self.PiSpecVersion, 16) < 0x0001000A:
230 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)
231
232 if self.ModuleType == 'MM_CORE_STANDALONE' and int(self.PiSpecVersion, 16) < 0x00010032:
233 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)
234
235 if Inf._Defs is not None and len(Inf._Defs) > 0:
236 self.OptRomDefs.update(Inf._Defs)
237
238 self.PatchPcds = []
239 InfPcds = Inf.Pcds
240 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
241 FdfPcdDict = GenFdsGlobalVariable.FdfParser.Profile.PcdDict
242 PlatformPcds = Platform.Pcds
243
244 # Workaround here: both build and GenFds tool convert the workspace path to lower case
245 # But INF file path in FDF and DSC file may have real case characters.
246 # Try to convert the path to lower case to see if PCDs value are override by DSC.
247 DscModules = {}
248 for DscModule in Platform.Modules:
249 DscModules[str(DscModule).lower()] = Platform.Modules[DscModule]
250 for PcdKey in InfPcds:
251 Pcd = InfPcds[PcdKey]
252 if not hasattr(Pcd, 'Offset'):
253 continue
254 if Pcd.Type != 'PatchableInModule':
255 continue
256 # Override Patchable PCD value by the value from DSC
257 PatchPcd = None
258 if InfLowerPath in DscModules and PcdKey in DscModules[InfLowerPath].Pcds:
259 PatchPcd = DscModules[InfLowerPath].Pcds[PcdKey]
260 elif PcdKey in Platform.Pcds:
261 PatchPcd = Platform.Pcds[PcdKey]
262 DscOverride = False
263 if PatchPcd and Pcd.Type == PatchPcd.Type:
264 DefaultValue = PatchPcd.DefaultValue
265 DscOverride = True
266
267 # Override Patchable PCD value by the value from FDF
268 FdfOverride = False
269 if PcdKey in FdfPcdDict:
270 DefaultValue = FdfPcdDict[PcdKey]
271 FdfOverride = True
272
273 # Override Patchable PCD value by the value from Build Option
274 BuildOptionOverride = False
275 if GlobalData.BuildOptionPcd:
276 for pcd in GlobalData.BuildOptionPcd:
277 if PcdKey == (pcd[1], pcd[0]):
278 if pcd[2]:
279 continue
280 DefaultValue = pcd[3]
281 BuildOptionOverride = True
282 break
283
284 if not DscOverride and not FdfOverride and not BuildOptionOverride:
285 continue
286
287 # Support Flexible PCD format
288 if DefaultValue:
289 try:
290 DefaultValue = ValueExpressionEx(DefaultValue, Pcd.DatumType, Platform._GuidDict)(True)
291 except BadExpression:
292 EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValue), File=self.InfFileName)
293
294 if Pcd.InfDefaultValue:
295 try:
296 Pcd.InfDefaultValue = ValueExpressionEx(Pcd.InfDefaultValue, Pcd.DatumType, Platform._GuidDict)(True)
297 except BadExpression:
298 EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DefaultValue),File=self.InfFileName)
299
300 # Check value, if value are equal, no need to patch
301 if Pcd.DatumType == "VOID*":
302 if Pcd.InfDefaultValue == DefaultValue or DefaultValue in [None, '']:
303 continue
304 # Get the string size from FDF or DSC
305 if DefaultValue[0] == 'L':
306 # Remove L"", but the '\0' must be appended
307 MaxDatumSize = str((len(DefaultValue) - 2) * 2)
308 elif DefaultValue[0] == '{':
309 MaxDatumSize = str(len(DefaultValue.split(',')))
310 else:
311 MaxDatumSize = str(len(DefaultValue) - 1)
312 if DscOverride:
313 Pcd.MaxDatumSize = PatchPcd.MaxDatumSize
314 # If no defined the maximum size in DSC, try to get current size from INF
315 if Pcd.MaxDatumSize in ['', None]:
316 Pcd.MaxDatumSize = str(len(Pcd.InfDefaultValue.split(',')))
317 else:
318 Base1 = Base2 = 10
319 if Pcd.InfDefaultValue.upper().startswith('0X'):
320 Base1 = 16
321 if DefaultValue.upper().startswith('0X'):
322 Base2 = 16
323 try:
324 PcdValueInImg = int(Pcd.InfDefaultValue, Base1)
325 PcdValueInDscOrFdf = int(DefaultValue, Base2)
326 if PcdValueInImg == PcdValueInDscOrFdf:
327 continue
328 except:
329 continue
330 # Check the Pcd size and data type
331 if Pcd.DatumType == "VOID*":
332 if int(MaxDatumSize) > int(Pcd.MaxDatumSize):
333 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
334 % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, int(MaxDatumSize) - int(Pcd.MaxDatumSize)))
335 else:
336 if PcdValueInDscOrFdf > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType] \
337 or PcdValueInImg > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType]:
338 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of %s type PCD '%s.%s' doesn't match its data type." \
339 % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
340 self.PatchPcds.append((Pcd, DefaultValue))
341
342 self.InfModule = Inf
343 self.PcdIsDriver = Inf.PcdIsDriver
344 self.IsBinaryModule = Inf.IsBinaryModule
345 Inf._GetDepex()
346 Inf._GetDepexExpression()
347 if len(Inf._Depex.data) > 0 and len(Inf._DepexExpression.data) > 0:
348 self.Depex = True
349
350 GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName)
351 GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid)
352 GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType)
353 GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString)
354 GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName)
355
356 #
357 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
358 #
359
360 self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \
361 self.ModuleGuid + self.BaseName)
362 if not os.path.exists(self.OutputPath) :
363 os.makedirs(self.OutputPath)
364
365 self.EfiOutputPath, self.EfiDebugPath = self.__GetEFIOutPutPath__()
366 GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)
367
368 ## PatchEfiFile
369 #
370 # Patch EFI file with patch PCD
371 #
372 # @param EfiFile: EFI file needs to be patched.
373 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
374 # If passed in file does not end with efi, return as is
375 #
376 def PatchEfiFile(self, EfiFile, FileType):
377 #
378 # If the module does not have any patches, then return path to input file
379 #
380 if not self.PatchPcds:
381 return EfiFile
382
383 #
384 # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED
385 #
386 if FileType != 'PE32' and self.ModuleType != "USER_DEFINED":
387 return EfiFile
388
389 #
390 # Generate path to patched output file
391 #
392 Basename = os.path.basename(EfiFile)
393 Output = os.path.normpath (os.path.join(self.OutputPath, Basename))
394
395 #
396 # If this file has already been patched, then return the path to the patched file
397 #
398 if self.PatchedBinFile == Output:
399 return Output
400
401 #
402 # If a different file from the same module has already been patched, then generate an error
403 #
404 if self.PatchedBinFile:
405 EdkLogger.error("GenFds", GENFDS_ERROR,
406 'Only one binary file can be patched:\n'
407 ' a binary file has been patched: %s\n'
408 ' current file: %s' % (self.PatchedBinFile, EfiFile),
409 File=self.InfFileName)
410
411 #
412 # Copy unpatched file contents to output file location to perform patching
413 #
414 CopyLongFilePath(EfiFile, Output)
415
416 #
417 # Apply patches to patched output file
418 #
419 for Pcd, Value in self.PatchPcds:
420 RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)
421 if RetVal:
422 EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName)
423
424 #
425 # Save the path of the patched output file
426 #
427 self.PatchedBinFile = Output
428
429 #
430 # Return path to patched output file
431 #
432 return Output
433
434 ## GenFfs() method
435 #
436 # Generate FFS
437 #
438 # @param self The object pointer
439 # @param Dict dictionary contains macro and value pair
440 # @param FvChildAddr Array of the inside FvImage base address
441 # @param FvParentAddr Parent Fv base address
442 # @retval string Generated FFS file name
443 #
444 def GenFfs(self, Dict = {}, FvChildAddr = [], FvParentAddr=None, IsMakefile=False, FvName=None):
445 #
446 # Parse Inf file get Module related information
447 #
448
449 self.__InfParse__(Dict)
450 Arch = self.GetCurrentArch()
451 SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir , self.InfFileName);
452 DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
453
454 SrcFileDir = "."
455 SrcPath = os.path.dirname(SrcFile)
456 SrcFileName = os.path.basename(SrcFile)
457 SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName)
458 DestPath = os.path.dirname(DestFile)
459 DestFileName = os.path.basename(DestFile)
460 DestFileBase, DestFileExt = os.path.splitext(DestFileName)
461 self.MacroDict = {
462 # source file
463 "${src}" : SrcFile,
464 "${s_path}" : SrcPath,
465 "${s_dir}" : SrcFileDir,
466 "${s_name}" : SrcFileName,
467 "${s_base}" : SrcFileBase,
468 "${s_ext}" : SrcFileExt,
469 # destination file
470 "${dst}" : DestFile,
471 "${d_path}" : DestPath,
472 "${d_name}" : DestFileName,
473 "${d_base}" : DestFileBase,
474 "${d_ext}" : DestFileExt
475 }
476 #
477 # Allow binary type module not specify override rule in FDF file.
478 #
479 if len(self.BinFileList) > 0:
480 if self.Rule is None or self.Rule == "":
481 self.Rule = "BINARY"
482
483 if not IsMakefile and GenFdsGlobalVariable.EnableGenfdsMultiThread and self.Rule != 'BINARY':
484 IsMakefile = True
485 #
486 # Get the rule of how to generate Ffs file
487 #
488 Rule = self.__GetRule__()
489 GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)
490 #
491 # Convert Fv File Type for PI1.1 SMM driver.
492 #
493 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
494 if Rule.FvFileType == 'DRIVER':
495 Rule.FvFileType = 'SMM'
496 #
497 # Framework SMM Driver has no SMM FV file type
498 #
499 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
500 if Rule.FvFileType == 'SMM' or Rule.FvFileType == 'SMM_CORE':
501 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File=self.InfFileName)
502 #
503 # For the rule only has simpleFile
504 #
505 MakefilePath = None
506 if self.IsBinaryModule:
507 IsMakefile = False
508 if IsMakefile:
509 MakefilePath = self.InfFileName, 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.keys():
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 == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
744 if SectionType == 'DXE_DEPEX':
745 SectionType = 'SMM_DEPEX'
746 #
747 # Framework SMM Driver has no SMM_DEPEX section type
748 #
749 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
750 if SectionType == '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 ('SEC', 'PEI_CORE', '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 Ffs.Ffs.SectionSuffix[SectionType] + '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 == 'PE32' or SectionType == '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 == '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 Ffs.Ffs.SectionSuffix[SectionType] + '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 == 'PE32' or SectionType == '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 == '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 Ffs.Ffs.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 ('SEC', 'PEI_CORE', 'PEIM'):
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 == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
947 if Sect.SectionType == 'DXE_DEPEX':
948 Sect.SectionType = 'SMM_DEPEX'
949 #
950 # Framework SMM Driver has no SMM_DEPEX section type
951 #
952 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
953 if Sect.SectionType == '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 Ffs.Ffs.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, 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 = 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