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