]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/FfsInfStatement.py
BaseTools: Various typo
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / FfsInfStatement.py
1 ## @file
2 # process FFS generation from INF statement
3 #
4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2014-2016 Hewlett-Packard Development Company, L.P.<BR>
6 #
7 # This program and the accompanying materials
8 # are licensed and made available under the terms and conditions of the BSD License
9 # which accompanies this distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
11 #
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 #
15
16 ##
17 # Import Modules
18 #
19 from __future__ import absolute_import
20 from . import Rule
21 import Common.LongFilePathOs as os
22 from io import BytesIO
23 from struct import *
24 from .GenFdsGlobalVariable import GenFdsGlobalVariable
25 from .Ffs import SectionSuffix,FdfFvFileTypeToFileType
26 import subprocess
27 import sys
28 from . import Section
29 from . import RuleSimpleFile
30 from . import RuleComplexFile
31 from CommonDataClass.FdfClass import FfsInfStatementClassObject
32 from Common.MultipleWorkspace import MultipleWorkspace as mws
33 from Common.DataType import SUP_MODULE_USER_DEFINED
34 from Common.StringUtils import *
35 from Common.Misc import PathClass
36 from Common.Misc import GuidStructureByteArrayToGuidString
37 from Common.Misc import ProcessDuplicatedInf
38 from Common.Misc import GetVariableOffset
39 from Common import EdkLogger
40 from Common.BuildToolError import *
41 from .GuidSection import GuidSection
42 from .FvImageSection import FvImageSection
43 from Common.Misc import PeImageClass
44 from AutoGen.GenDepex import DependencyExpression
45 from PatchPcdValue.PatchPcdValue import PatchBinaryFile
46 from Common.LongFilePathSupport import CopyLongFilePath
47 from Common.LongFilePathSupport import OpenLongFilePath as open
48 import Common.GlobalData as GlobalData
49 from .DepexSection import DepexSection
50 from Common.Misc import SaveFileOnChange
51 from Common.Expression import *
52 from Common.DataType import *
53
54 ## generate FFS from INF
55 #
56 #
57 class FfsInfStatement(FfsInfStatementClassObject):
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 != SUP_MODULE_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 != 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, ModuleGuid, 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 == SUP_MODULE_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 == SUP_MODULE_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 != TAB_PCDS_PATCHABLE_IN_MODULE:
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 == TAB_VOID:
302 if Pcd.InfDefaultValue == DefaultValue or not DefaultValue:
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 not Pcd.MaxDatumSize:
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 == TAB_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 > MAX_VAL_TYPE[Pcd.DatumType] \
337 or PcdValueInImg > MAX_VAL_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 if len(Inf.Depex.data) > 0 and len(Inf.DepexExpression.data) > 0:
346 self.Depex = True
347
348 GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName)
349 GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid)
350 GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType)
351 GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString)
352 GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName)
353
354 #
355 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${ModuleName}\
356 #
357
358 self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \
359 self.ModuleGuid + self.BaseName)
360 if not os.path.exists(self.OutputPath) :
361 os.makedirs(self.OutputPath)
362
363 self.EfiOutputPath, self.EfiDebugPath = self.__GetEFIOutPutPath__()
364 GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)
365
366 ## PatchEfiFile
367 #
368 # Patch EFI file with patch PCD
369 #
370 # @param EfiFile: EFI file needs to be patched.
371 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
372 # If passed in file does not end with efi, return as is
373 #
374 def PatchEfiFile(self, EfiFile, FileType):
375 #
376 # If the module does not have any patches, then return path to input file
377 #
378 if not self.PatchPcds:
379 return EfiFile
380
381 #
382 # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED
383 #
384 if FileType != BINARY_FILE_TYPE_PE32 and self.ModuleType != SUP_MODULE_USER_DEFINED:
385 return EfiFile
386
387 #
388 # Generate path to patched output file
389 #
390 Basename = os.path.basename(EfiFile)
391 Output = os.path.normpath (os.path.join(self.OutputPath, Basename))
392
393 #
394 # If this file has already been patched, then return the path to the patched file
395 #
396 if self.PatchedBinFile == Output:
397 return Output
398
399 #
400 # If a different file from the same module has already been patched, then generate an error
401 #
402 if self.PatchedBinFile:
403 EdkLogger.error("GenFds", GENFDS_ERROR,
404 'Only one binary file can be patched:\n'
405 ' a binary file has been patched: %s\n'
406 ' current file: %s' % (self.PatchedBinFile, EfiFile),
407 File=self.InfFileName)
408
409 #
410 # Copy unpatched file contents to output file location to perform patching
411 #
412 CopyLongFilePath(EfiFile, Output)
413
414 #
415 # Apply patches to patched output file
416 #
417 for Pcd, Value in self.PatchPcds:
418 RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)
419 if RetVal:
420 EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName)
421
422 #
423 # Save the path of the patched output file
424 #
425 self.PatchedBinFile = Output
426
427 #
428 # Return path to patched output file
429 #
430 return Output
431
432 ## GenFfs() method
433 #
434 # Generate FFS
435 #
436 # @param self The object pointer
437 # @param Dict dictionary contains macro and value pair
438 # @param FvChildAddr Array of the inside FvImage base address
439 # @param FvParentAddr Parent Fv base address
440 # @retval string Generated FFS file name
441 #
442 def GenFfs(self, Dict = {}, FvChildAddr = [], FvParentAddr=None, IsMakefile=False, FvName=None):
443 #
444 # Parse Inf file get Module related information
445 #
446
447 self.__InfParse__(Dict)
448 Arch = self.GetCurrentArch()
449 SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName);
450 DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
451
452 SrcFileDir = "."
453 SrcPath = os.path.dirname(SrcFile)
454 SrcFileName = os.path.basename(SrcFile)
455 SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName)
456 DestPath = os.path.dirname(DestFile)
457 DestFileName = os.path.basename(DestFile)
458 DestFileBase, DestFileExt = os.path.splitext(DestFileName)
459 self.MacroDict = {
460 # source file
461 "${src}" : SrcFile,
462 "${s_path}" : SrcPath,
463 "${s_dir}" : SrcFileDir,
464 "${s_name}" : SrcFileName,
465 "${s_base}" : SrcFileBase,
466 "${s_ext}" : SrcFileExt,
467 # destination file
468 "${dst}" : DestFile,
469 "${d_path}" : DestPath,
470 "${d_name}" : DestFileName,
471 "${d_base}" : DestFileBase,
472 "${d_ext}" : DestFileExt
473 }
474 #
475 # Allow binary type module not specify override rule in FDF file.
476 #
477 if len(self.BinFileList) > 0:
478 if self.Rule is None or self.Rule == "":
479 self.Rule = "BINARY"
480
481 if not IsMakefile and GenFdsGlobalVariable.EnableGenfdsMultiThread and self.Rule != 'BINARY':
482 IsMakefile = True
483 #
484 # Get the rule of how to generate Ffs file
485 #
486 Rule = self.__GetRule__()
487 GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)
488 #
489 # Convert Fv File Type for PI1.1 SMM driver.
490 #
491 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A:
492 if Rule.FvFileType == 'DRIVER':
493 Rule.FvFileType = 'SMM'
494 #
495 # Framework SMM Driver has no SMM FV file type
496 #
497 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A:
498 if Rule.FvFileType == 'SMM' or Rule.FvFileType == SUP_MODULE_SMM_CORE:
499 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File=self.InfFileName)
500 #
501 # For the rule only has simpleFile
502 #
503 MakefilePath = None
504 if self.IsBinaryModule:
505 IsMakefile = False
506 if IsMakefile:
507 MakefilePath = self.InfFileName, Arch
508 if isinstance (Rule, RuleSimpleFile.RuleSimpleFile):
509 SectionOutputList = self.__GenSimpleFileSection__(Rule, IsMakefile=IsMakefile)
510 FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList, MakefilePath=MakefilePath)
511 return FfsOutput
512 #
513 # For Rule has ComplexFile
514 #
515 elif isinstance(Rule, RuleComplexFile.RuleComplexFile):
516 InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr, IsMakefile=IsMakefile)
517 FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments, MakefilePath=MakefilePath)
518 return FfsOutput
519
520 ## __ExtendMacro__() method
521 #
522 # Replace macro with its value
523 #
524 # @param self The object pointer
525 # @param String The string to be replaced
526 # @retval string Macro replaced string
527 #
528 def __ExtendMacro__ (self, String):
529 MacroDict = {
530 '$(INF_OUTPUT)' : self.EfiOutputPath,
531 '$(MODULE_NAME)' : self.BaseName,
532 '$(BUILD_NUMBER)': self.BuildNum,
533 '$(INF_VERSION)' : self.VersionString,
534 '$(NAMED_GUID)' : self.ModuleGuid
535 }
536 String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)
537 String = GenFdsGlobalVariable.MacroExtend(String, self.MacroDict)
538 return String
539
540 ## __GetRule__() method
541 #
542 # Get correct rule for generating FFS for this INF
543 #
544 # @param self The object pointer
545 # @retval Rule Rule object
546 #
547 def __GetRule__ (self) :
548 CurrentArchList = []
549 if self.CurrentArch is None:
550 CurrentArchList = ['common']
551 else:
552 CurrentArchList.append(self.CurrentArch)
553
554 for CurrentArch in CurrentArchList:
555 RuleName = 'RULE' + \
556 '.' + \
557 CurrentArch.upper() + \
558 '.' + \
559 self.ModuleType.upper()
560 if self.Rule is not None:
561 RuleName = RuleName + \
562 '.' + \
563 self.Rule.upper()
564
565 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
566 if Rule is not None:
567 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
568 return Rule
569
570 RuleName = 'RULE' + \
571 '.' + \
572 TAB_COMMON + \
573 '.' + \
574 self.ModuleType.upper()
575
576 if self.Rule is not None:
577 RuleName = RuleName + \
578 '.' + \
579 self.Rule.upper()
580
581 GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))
582
583 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
584 if Rule is not None:
585 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
586 return Rule
587
588 if Rule is None :
589 EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \
590 % (RuleName, self.InfFileName))
591
592 ## __GetPlatformArchList__() method
593 #
594 # Get Arch list this INF built under
595 #
596 # @param self The object pointer
597 # @retval list Arch list
598 #
599 def __GetPlatformArchList__(self):
600
601 InfFileKey = os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))
602 DscArchList = []
603 for Arch in GenFdsGlobalVariable.ArchList :
604 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
605 if PlatformDataBase is not None:
606 if InfFileKey in PlatformDataBase.Modules:
607 DscArchList.append (Arch)
608 else:
609 #
610 # BaseTools support build same module more than once, the module path with FILE_GUID overridden has
611 # the file name FILE_GUIDmodule.inf, then PlatformDataBase.Modules use FILE_GUIDmodule.inf as key,
612 # but the path (self.MetaFile.Path) is the real path
613 #
614 for key in PlatformDataBase.Modules:
615 if InfFileKey == str((PlatformDataBase.Modules[key]).MetaFile.Path):
616 DscArchList.append (Arch)
617 break
618
619 return DscArchList
620
621 ## GetCurrentArch() method
622 #
623 # Get Arch list of the module from this INF is to be placed into flash
624 #
625 # @param self The object pointer
626 # @retval list Arch list
627 #
628 def GetCurrentArch(self) :
629
630 TargetArchList = GenFdsGlobalVariable.ArchList
631
632 PlatformArchList = self.__GetPlatformArchList__()
633
634 CurArchList = TargetArchList
635 if PlatformArchList != []:
636 CurArchList = list(set (TargetArchList) & set (PlatformArchList))
637 GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))
638
639 ArchList = []
640 if self.KeyStringList != []:
641 for Key in self.KeyStringList:
642 Key = GenFdsGlobalVariable.MacroExtend(Key)
643 Target, Tag, Arch = Key.split('_')
644 if Arch in CurArchList:
645 ArchList.append(Arch)
646 if Target not in self.TargetOverrideList:
647 self.TargetOverrideList.append(Target)
648 else:
649 ArchList = CurArchList
650
651 UseArchList = TargetArchList
652 if self.UseArch is not None:
653 UseArchList = []
654 UseArchList.append(self.UseArch)
655 ArchList = list(set (UseArchList) & set (ArchList))
656
657 self.InfFileName = NormPath(self.InfFileName)
658 if len(PlatformArchList) == 0:
659 self.InDsc = False
660 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
661 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
662 if ErrorCode != 0:
663 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
664 if len(ArchList) == 1:
665 Arch = ArchList[0]
666 return Arch
667 elif len(ArchList) > 1:
668 if len(PlatformArchList) == 0:
669 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))
670 else:
671 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))
672 else:
673 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." \
674 % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))
675
676 ## __GetEFIOutPutPath__() method
677 #
678 # Get the output path for generated files
679 #
680 # @param self The object pointer
681 # @retval string Path that output files from this INF go to
682 #
683 def __GetEFIOutPutPath__(self):
684 Arch = ''
685 OutputPath = ''
686 DebugPath = ''
687 (ModulePath, FileName) = os.path.split(self.InfFileName)
688 Index = FileName.rfind('.')
689 FileName = FileName[0:Index]
690 if self.OverrideGuid:
691 FileName = self.OverrideGuid
692 Arch = "NoneArch"
693 if self.CurrentArch is not None:
694 Arch = self.CurrentArch
695
696 OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
697 Arch,
698 ModulePath,
699 FileName,
700 'OUTPUT'
701 )
702 DebugPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
703 Arch,
704 ModulePath,
705 FileName,
706 'DEBUG'
707 )
708 OutputPath = os.path.realpath(OutputPath)
709 DebugPath = os.path.realpath(DebugPath)
710 return OutputPath, DebugPath
711
712 ## __GenSimpleFileSection__() method
713 #
714 # Generate section by specified file name or a list of files with file extension
715 #
716 # @param self The object pointer
717 # @param Rule The rule object used to generate section
718 # @retval string File name of the generated section file
719 #
720 def __GenSimpleFileSection__(self, Rule, IsMakefile = False):
721 #
722 # Prepare the parameter of GenSection
723 #
724 FileList = []
725 OutputFileList = []
726 GenSecInputFile = None
727 if Rule.FileName is not None:
728 GenSecInputFile = self.__ExtendMacro__(Rule.FileName)
729 if os.path.isabs(GenSecInputFile):
730 GenSecInputFile = os.path.normpath(GenSecInputFile)
731 else:
732 GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))
733 else:
734 FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)
735
736 Index = 1
737 SectionType = Rule.SectionType
738 #
739 # Convert Fv Section Type for PI1.1 SMM driver.
740 #
741 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A:
742 if SectionType == BINARY_FILE_TYPE_DXE_DEPEX:
743 SectionType = BINARY_FILE_TYPE_SMM_DEPEX
744 #
745 # Framework SMM Driver has no SMM_DEPEX section type
746 #
747 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A:
748 if SectionType == BINARY_FILE_TYPE_SMM_DEPEX:
749 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
750 NoStrip = True
751 if self.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM):
752 if self.KeepReloc is not None:
753 NoStrip = self.KeepReloc
754 elif Rule.KeepReloc is not None:
755 NoStrip = Rule.KeepReloc
756 elif self.ShadowFromInfFile is not None:
757 NoStrip = self.ShadowFromInfFile
758
759 if FileList != [] :
760 for File in FileList:
761
762 SecNum = '%d' %Index
763 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
764 SectionSuffix[SectionType] + SUP_MODULE_SEC + SecNum
765 Index = Index + 1
766 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
767 File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)
768
769 #Get PE Section alignment when align is set to AUTO
770 if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):
771 ImageObj = PeImageClass (File)
772 if ImageObj.SectionAlignment < 0x400:
773 self.Alignment = str (ImageObj.SectionAlignment)
774 elif ImageObj.SectionAlignment < 0x100000:
775 self.Alignment = str (ImageObj.SectionAlignment // 0x400) + 'K'
776 else:
777 self.Alignment = str (ImageObj.SectionAlignment // 0x100000) + 'M'
778
779 if not NoStrip:
780 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
781 if not os.path.exists(FileBeforeStrip) or \
782 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):
783 CopyLongFilePath(File, FileBeforeStrip)
784 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
785 GenFdsGlobalVariable.GenerateFirmwareImage(
786 StrippedFile,
787 [File],
788 Strip=True,
789 IsMakefile=IsMakefile
790 )
791 File = StrippedFile
792
793 if SectionType == BINARY_FILE_TYPE_TE:
794 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
795 GenFdsGlobalVariable.GenerateFirmwareImage(
796 TeFile,
797 [File],
798 Type='te',
799 IsMakefile=IsMakefile
800 )
801 File = TeFile
802 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)
803 OutputFileList.append(OutputFile)
804 else:
805 SecNum = '%d' %Index
806 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
807 SectionSuffix[SectionType] + SUP_MODULE_SEC + SecNum
808 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
809 GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)
810
811 #Get PE Section alignment when align is set to AUTO
812 if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):
813 ImageObj = PeImageClass (GenSecInputFile)
814 if ImageObj.SectionAlignment < 0x400:
815 self.Alignment = str (ImageObj.SectionAlignment)
816 elif ImageObj.SectionAlignment < 0x100000:
817 self.Alignment = str (ImageObj.SectionAlignment // 0x400) + 'K'
818 else:
819 self.Alignment = str (ImageObj.SectionAlignment // 0x100000) + 'M'
820
821 if not NoStrip:
822 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
823 if not os.path.exists(FileBeforeStrip) or \
824 (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):
825 CopyLongFilePath(GenSecInputFile, FileBeforeStrip)
826
827 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
828 GenFdsGlobalVariable.GenerateFirmwareImage(
829 StrippedFile,
830 [GenSecInputFile],
831 Strip=True,
832 IsMakefile=IsMakefile
833 )
834 GenSecInputFile = StrippedFile
835
836 if SectionType == BINARY_FILE_TYPE_TE:
837 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
838 GenFdsGlobalVariable.GenerateFirmwareImage(
839 TeFile,
840 [GenSecInputFile],
841 Type='te',
842 IsMakefile=IsMakefile
843 )
844 GenSecInputFile = TeFile
845 GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)
846 OutputFileList.append(OutputFile)
847
848 return OutputFileList
849
850 ## __GenSimpleFileFfs__() method
851 #
852 # Generate FFS
853 #
854 # @param self The object pointer
855 # @param Rule The rule object used to generate section
856 # @param InputFileList The output file list from GenSection
857 # @retval string Generated FFS file name
858 #
859 def __GenSimpleFileFfs__(self, Rule, InputFileList, MakefilePath = None):
860 FfsOutput = self.OutputPath + \
861 os.sep + \
862 self.__ExtendMacro__(Rule.NameGuid) + \
863 '.ffs'
864
865 GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))
866 InputSection = []
867 SectionAlignments = []
868 for InputFile in InputFileList:
869 InputSection.append(InputFile)
870 SectionAlignments.append(Rule.SectAlignment)
871
872 if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('):
873 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
874 if len(PcdValue) == 0:
875 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
876 % (Rule.NameGuid))
877 if PcdValue.startswith('{'):
878 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
879 RegistryGuidStr = PcdValue
880 if len(RegistryGuidStr) == 0:
881 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
882 % (Rule.NameGuid))
883 self.ModuleGuid = RegistryGuidStr
884
885 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,
886 FdfFvFileTypeToFileType[Rule.FvFileType],
887 self.ModuleGuid, Fixed=Rule.Fixed,
888 CheckSum=Rule.CheckSum, Align=Rule.Alignment,
889 SectionAlign=SectionAlignments,
890 MakefilePath=MakefilePath
891 )
892 return FfsOutput
893
894 ## __GenComplexFileSection__() method
895 #
896 # Generate section by sections in Rule
897 #
898 # @param self The object pointer
899 # @param Rule The rule object used to generate section
900 # @param FvChildAddr Array of the inside FvImage base address
901 # @param FvParentAddr Parent Fv base address
902 # @retval string File name of the generated section file
903 #
904 def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr, IsMakefile = False):
905 if self.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE):
906 if Rule.KeepReloc is not None:
907 self.KeepRelocFromRule = Rule.KeepReloc
908 SectFiles = []
909 SectAlignments = []
910 Index = 1
911 HasGeneratedFlag = False
912 if self.PcdIsDriver == 'PEI_PCD_DRIVER':
913 if self.IsBinaryModule:
914 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "PEIPcdDataBase.raw")
915 else:
916 PcdExDbFileName = os.path.join(self.EfiOutputPath, "PEIPcdDataBase.raw")
917 PcdExDbSecName = os.path.join(self.OutputPath, "PEIPcdDataBaseSec.raw")
918 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,
919 [PcdExDbFileName],
920 "EFI_SECTION_RAW",
921 IsMakefile = IsMakefile
922 )
923 SectFiles.append(PcdExDbSecName)
924 SectAlignments.append(None)
925 elif self.PcdIsDriver == 'DXE_PCD_DRIVER':
926 if self.IsBinaryModule:
927 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "DXEPcdDataBase.raw")
928 else:
929 PcdExDbFileName = os.path.join(self.EfiOutputPath, "DXEPcdDataBase.raw")
930 PcdExDbSecName = os.path.join(self.OutputPath, "DXEPcdDataBaseSec.raw")
931 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,
932 [PcdExDbFileName],
933 "EFI_SECTION_RAW",
934 IsMakefile = IsMakefile
935 )
936 SectFiles.append(PcdExDbSecName)
937 SectAlignments.append(None)
938 for Sect in Rule.SectionList:
939 SecIndex = '%d' %Index
940 SectList = []
941 #
942 # Convert Fv Section Type for PI1.1 SMM driver.
943 #
944 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A:
945 if Sect.SectionType == BINARY_FILE_TYPE_DXE_DEPEX:
946 Sect.SectionType = BINARY_FILE_TYPE_SMM_DEPEX
947 #
948 # Framework SMM Driver has no SMM_DEPEX section type
949 #
950 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A:
951 if Sect.SectionType == BINARY_FILE_TYPE_SMM_DEPEX:
952 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
953 #
954 # process the inside FvImage from FvSection or GuidSection
955 #
956 if FvChildAddr != []:
957 if isinstance(Sect, FvImageSection):
958 Sect.FvAddr = FvChildAddr.pop(0)
959 elif isinstance(Sect, GuidSection):
960 Sect.FvAddr = FvChildAddr
961 if FvParentAddr is not None and isinstance(Sect, GuidSection):
962 Sect.FvParentAddr = FvParentAddr
963
964 if Rule.KeyStringList != []:
965 SectList, Align = Sect.GenSection(self.OutputPath, self.ModuleGuid, SecIndex, Rule.KeyStringList, self, IsMakefile = IsMakefile)
966 else :
967 SectList, Align = Sect.GenSection(self.OutputPath, self.ModuleGuid, SecIndex, self.KeyStringList, self, IsMakefile = IsMakefile)
968
969 if not HasGeneratedFlag:
970 UniVfrOffsetFileSection = ""
971 ModuleFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)
972 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]
973 #
974 # Search the source list in InfData to find if there are .vfr file exist.
975 #
976 VfrUniBaseName = {}
977 VfrUniOffsetList = []
978 for SourceFile in InfData.Sources:
979 if SourceFile.Type.upper() == ".VFR" :
980 #
981 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
982 #
983 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
984 if SourceFile.Type.upper() == ".UNI" :
985 #
986 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
987 #
988 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")
989
990
991 if len(VfrUniBaseName) > 0:
992 if IsMakefile:
993 if InfData.BuildType != 'UEFI_HII':
994 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')
995 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')
996 UniVfrOffsetFileNameList = []
997 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
998 TrimCmd = "Trim --Vfr-Uni-Offset -o %s --ModuleName=%s --DebugDir=%s " % (UniVfrOffsetFileName, self.BaseName, self.EfiDebugPath)
999 GenFdsGlobalVariable.SecCmdList.append(TrimCmd)
1000 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
1001 [UniVfrOffsetFileName],
1002 "EFI_SECTION_RAW",
1003 IsMakefile = True
1004 )
1005 else:
1006 VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)
1007 #
1008 # Generate the Raw data of raw section
1009 #
1010 if VfrUniOffsetList:
1011 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')
1012 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')
1013 FfsInfStatement.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)
1014 UniVfrOffsetFileNameList = []
1015 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
1016 """Call GenSection"""
1017
1018 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
1019 UniVfrOffsetFileNameList,
1020 "EFI_SECTION_RAW"
1021 )
1022 #os.remove(UniVfrOffsetFileName)
1023 if UniVfrOffsetFileSection:
1024 SectList.append(UniVfrOffsetFileSection)
1025 HasGeneratedFlag = True
1026
1027 for SecName in SectList :
1028 SectFiles.append(SecName)
1029 SectAlignments.append(Align)
1030 Index = Index + 1
1031 return SectFiles, SectAlignments
1032
1033 ## __GenComplexFileFfs__() method
1034 #
1035 # Generate FFS
1036 #
1037 # @param self The object pointer
1038 # @param Rule The rule object used to generate section
1039 # @param InputFileList The output file list from GenSection
1040 # @retval string Generated FFS file name
1041 #
1042 def __GenComplexFileFfs__(self, Rule, InputFile, Alignments, MakefilePath = None):
1043
1044 if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('):
1045 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
1046 if len(PcdValue) == 0:
1047 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
1048 % (Rule.NameGuid))
1049 if PcdValue.startswith('{'):
1050 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
1051 RegistryGuidStr = PcdValue
1052 if len(RegistryGuidStr) == 0:
1053 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
1054 % (Rule.NameGuid))
1055 self.ModuleGuid = RegistryGuidStr
1056
1057 FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
1058 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,
1059 FdfFvFileTypeToFileType[Rule.FvFileType],
1060 self.ModuleGuid, Fixed=Rule.Fixed,
1061 CheckSum=Rule.CheckSum, Align=Rule.Alignment,
1062 SectionAlign=Alignments,
1063 MakefilePath=MakefilePath
1064 )
1065 return FfsOutput
1066
1067 ## __GetBuildOutputMapFileVfrUniInfo() method
1068 #
1069 # Find the offset of UNI/INF object offset in the EFI image file.
1070 #
1071 # @param self The object pointer
1072 # @param VfrUniBaseName A name list contain the UNI/INF object name.
1073 # @retval RetValue A list contain offset of UNI/INF object.
1074 #
1075 def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):
1076 MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")
1077 EfiFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".efi")
1078 return GetVariableOffset(MapFileName, EfiFileName, list(VfrUniBaseName.values()))
1079
1080 ## __GenUniVfrOffsetFile() method
1081 #
1082 # Generate the offset file for the module which contain VFR or UNI file.
1083 #
1084 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
1085 # @param UniVfrOffsetFileName The output offset file name.
1086 #
1087 @staticmethod
1088 def __GenUniVfrOffsetFile(VfrUniOffsetList, UniVfrOffsetFileName):
1089
1090 # Use a instance of StringIO to cache data
1091 fStringIO = BytesIO()
1092
1093 for Item in VfrUniOffsetList:
1094 if (Item[0].find("Strings") != -1):
1095 #
1096 # UNI offset in image.
1097 # GUID + Offset
1098 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1099 #
1100 UniGuid = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
1101 fStringIO.write(UniGuid)
1102 UniValue = pack ('Q', int (Item[1], 16))
1103 fStringIO.write (UniValue)
1104 else:
1105 #
1106 # VFR binary offset in image.
1107 # GUID + Offset
1108 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1109 #
1110 VfrGuid = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
1111 fStringIO.write(VfrGuid)
1112 type (Item[1])
1113 VfrValue = pack ('Q', int (Item[1], 16))
1114 fStringIO.write (VfrValue)
1115
1116 #
1117 # write data into file.
1118 #
1119 try :
1120 SaveFileOnChange(UniVfrOffsetFileName, fStringIO.getvalue())
1121 except:
1122 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)
1123
1124 fStringIO.close ()
1125
1126