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