]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/FfsInfStatement.py
BaseTools: Fixed the bug of multi-thread genffs for override inf
[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 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
506 if self.OverrideGuid:
507 PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)
508 MakefilePath = PathClassObj.Path, Arch
509 if isinstance (Rule, RuleSimpleFile.RuleSimpleFile):
510 SectionOutputList = self.__GenSimpleFileSection__(Rule, IsMakefile=IsMakefile)
511 FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList, MakefilePath=MakefilePath)
512 return FfsOutput
513 #
514 # For Rule has ComplexFile
515 #
516 elif isinstance(Rule, RuleComplexFile.RuleComplexFile):
517 InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr, IsMakefile=IsMakefile)
518 FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments, MakefilePath=MakefilePath)
519 return FfsOutput
520
521 ## __ExtendMacro__() method
522 #
523 # Replace macro with its value
524 #
525 # @param self The object pointer
526 # @param String The string to be replaced
527 # @retval string Macro replaced string
528 #
529 def __ExtendMacro__ (self, String):
530 MacroDict = {
531 '$(INF_OUTPUT)' : self.EfiOutputPath,
532 '$(MODULE_NAME)' : self.BaseName,
533 '$(BUILD_NUMBER)': self.BuildNum,
534 '$(INF_VERSION)' : self.VersionString,
535 '$(NAMED_GUID)' : self.ModuleGuid
536 }
537 String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)
538 String = GenFdsGlobalVariable.MacroExtend(String, self.MacroDict)
539 return String
540
541 ## __GetRule__() method
542 #
543 # Get correct rule for generating FFS for this INF
544 #
545 # @param self The object pointer
546 # @retval Rule Rule object
547 #
548 def __GetRule__ (self) :
549 CurrentArchList = []
550 if self.CurrentArch is None:
551 CurrentArchList = ['common']
552 else:
553 CurrentArchList.append(self.CurrentArch)
554
555 for CurrentArch in CurrentArchList:
556 RuleName = 'RULE' + \
557 '.' + \
558 CurrentArch.upper() + \
559 '.' + \
560 self.ModuleType.upper()
561 if self.Rule is not None:
562 RuleName = RuleName + \
563 '.' + \
564 self.Rule.upper()
565
566 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
567 if Rule is not None:
568 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
569 return Rule
570
571 RuleName = 'RULE' + \
572 '.' + \
573 TAB_COMMON + \
574 '.' + \
575 self.ModuleType.upper()
576
577 if self.Rule is not None:
578 RuleName = RuleName + \
579 '.' + \
580 self.Rule.upper()
581
582 GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))
583
584 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
585 if Rule is not None:
586 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
587 return Rule
588
589 if Rule is None :
590 EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \
591 % (RuleName, self.InfFileName))
592
593 ## __GetPlatformArchList__() method
594 #
595 # Get Arch list this INF built under
596 #
597 # @param self The object pointer
598 # @retval list Arch list
599 #
600 def __GetPlatformArchList__(self):
601
602 InfFileKey = os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))
603 DscArchList = []
604 for Arch in GenFdsGlobalVariable.ArchList :
605 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
606 if PlatformDataBase is not None:
607 if InfFileKey in PlatformDataBase.Modules:
608 DscArchList.append (Arch)
609 else:
610 #
611 # BaseTools support build same module more than once, the module path with FILE_GUID overridden has
612 # the file name FILE_GUIDmodule.inf, then PlatformDataBase.Modules use FILE_GUIDmodule.inf as key,
613 # but the path (self.MetaFile.Path) is the real path
614 #
615 for key in PlatformDataBase.Modules:
616 if InfFileKey == str((PlatformDataBase.Modules[key]).MetaFile.Path):
617 DscArchList.append (Arch)
618 break
619
620 return DscArchList
621
622 ## GetCurrentArch() method
623 #
624 # Get Arch list of the module from this INF is to be placed into flash
625 #
626 # @param self The object pointer
627 # @retval list Arch list
628 #
629 def GetCurrentArch(self) :
630
631 TargetArchList = GenFdsGlobalVariable.ArchList
632
633 PlatformArchList = self.__GetPlatformArchList__()
634
635 CurArchList = TargetArchList
636 if PlatformArchList != []:
637 CurArchList = list(set (TargetArchList) & set (PlatformArchList))
638 GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))
639
640 ArchList = []
641 if self.KeyStringList != []:
642 for Key in self.KeyStringList:
643 Key = GenFdsGlobalVariable.MacroExtend(Key)
644 Target, Tag, Arch = Key.split('_')
645 if Arch in CurArchList:
646 ArchList.append(Arch)
647 if Target not in self.TargetOverrideList:
648 self.TargetOverrideList.append(Target)
649 else:
650 ArchList = CurArchList
651
652 UseArchList = TargetArchList
653 if self.UseArch is not None:
654 UseArchList = []
655 UseArchList.append(self.UseArch)
656 ArchList = list(set (UseArchList) & set (ArchList))
657
658 self.InfFileName = NormPath(self.InfFileName)
659 if len(PlatformArchList) == 0:
660 self.InDsc = False
661 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
662 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
663 if ErrorCode != 0:
664 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
665 if len(ArchList) == 1:
666 Arch = ArchList[0]
667 return Arch
668 elif len(ArchList) > 1:
669 if len(PlatformArchList) == 0:
670 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))
671 else:
672 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))
673 else:
674 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." \
675 % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))
676
677 ## __GetEFIOutPutPath__() method
678 #
679 # Get the output path for generated files
680 #
681 # @param self The object pointer
682 # @retval string Path that output files from this INF go to
683 #
684 def __GetEFIOutPutPath__(self):
685 Arch = ''
686 OutputPath = ''
687 DebugPath = ''
688 (ModulePath, FileName) = os.path.split(self.InfFileName)
689 Index = FileName.rfind('.')
690 FileName = FileName[0:Index]
691 if self.OverrideGuid:
692 FileName = self.OverrideGuid
693 Arch = "NoneArch"
694 if self.CurrentArch is not None:
695 Arch = self.CurrentArch
696
697 OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
698 Arch,
699 ModulePath,
700 FileName,
701 'OUTPUT'
702 )
703 DebugPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
704 Arch,
705 ModulePath,
706 FileName,
707 'DEBUG'
708 )
709 OutputPath = os.path.realpath(OutputPath)
710 DebugPath = os.path.realpath(DebugPath)
711 return OutputPath, DebugPath
712
713 ## __GenSimpleFileSection__() method
714 #
715 # Generate section by specified file name or a list of files with file extension
716 #
717 # @param self The object pointer
718 # @param Rule The rule object used to generate section
719 # @retval string File name of the generated section file
720 #
721 def __GenSimpleFileSection__(self, Rule, IsMakefile = False):
722 #
723 # Prepare the parameter of GenSection
724 #
725 FileList = []
726 OutputFileList = []
727 GenSecInputFile = None
728 if Rule.FileName is not None:
729 GenSecInputFile = self.__ExtendMacro__(Rule.FileName)
730 if os.path.isabs(GenSecInputFile):
731 GenSecInputFile = os.path.normpath(GenSecInputFile)
732 else:
733 GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))
734 else:
735 FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)
736
737 Index = 1
738 SectionType = Rule.SectionType
739 #
740 # Convert Fv Section Type for PI1.1 SMM driver.
741 #
742 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A:
743 if SectionType == BINARY_FILE_TYPE_DXE_DEPEX:
744 SectionType = BINARY_FILE_TYPE_SMM_DEPEX
745 #
746 # Framework SMM Driver has no SMM_DEPEX section type
747 #
748 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A:
749 if SectionType == BINARY_FILE_TYPE_SMM_DEPEX:
750 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
751 NoStrip = True
752 if self.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM):
753 if self.KeepReloc is not None:
754 NoStrip = self.KeepReloc
755 elif Rule.KeepReloc is not None:
756 NoStrip = Rule.KeepReloc
757 elif self.ShadowFromInfFile is not None:
758 NoStrip = self.ShadowFromInfFile
759
760 if FileList != [] :
761 for File in FileList:
762
763 SecNum = '%d' %Index
764 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
765 SectionSuffix[SectionType] + SUP_MODULE_SEC + SecNum
766 Index = Index + 1
767 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
768 File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)
769
770 #Get PE Section alignment when align is set to AUTO
771 if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):
772 ImageObj = PeImageClass (File)
773 if ImageObj.SectionAlignment < 0x400:
774 self.Alignment = str (ImageObj.SectionAlignment)
775 elif ImageObj.SectionAlignment < 0x100000:
776 self.Alignment = str (ImageObj.SectionAlignment // 0x400) + 'K'
777 else:
778 self.Alignment = str (ImageObj.SectionAlignment // 0x100000) + 'M'
779
780 if not NoStrip:
781 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
782 if not os.path.exists(FileBeforeStrip) or \
783 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):
784 CopyLongFilePath(File, FileBeforeStrip)
785 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
786 GenFdsGlobalVariable.GenerateFirmwareImage(
787 StrippedFile,
788 [File],
789 Strip=True,
790 IsMakefile=IsMakefile
791 )
792 File = StrippedFile
793
794 if SectionType == BINARY_FILE_TYPE_TE:
795 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
796 GenFdsGlobalVariable.GenerateFirmwareImage(
797 TeFile,
798 [File],
799 Type='te',
800 IsMakefile=IsMakefile
801 )
802 File = TeFile
803 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)
804 OutputFileList.append(OutputFile)
805 else:
806 SecNum = '%d' %Index
807 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
808 SectionSuffix[SectionType] + SUP_MODULE_SEC + SecNum
809 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
810 GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)
811
812 #Get PE Section alignment when align is set to AUTO
813 if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):
814 ImageObj = PeImageClass (GenSecInputFile)
815 if ImageObj.SectionAlignment < 0x400:
816 self.Alignment = str (ImageObj.SectionAlignment)
817 elif ImageObj.SectionAlignment < 0x100000:
818 self.Alignment = str (ImageObj.SectionAlignment // 0x400) + 'K'
819 else:
820 self.Alignment = str (ImageObj.SectionAlignment // 0x100000) + 'M'
821
822 if not NoStrip:
823 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
824 if not os.path.exists(FileBeforeStrip) or \
825 (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):
826 CopyLongFilePath(GenSecInputFile, FileBeforeStrip)
827
828 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
829 GenFdsGlobalVariable.GenerateFirmwareImage(
830 StrippedFile,
831 [GenSecInputFile],
832 Strip=True,
833 IsMakefile=IsMakefile
834 )
835 GenSecInputFile = StrippedFile
836
837 if SectionType == BINARY_FILE_TYPE_TE:
838 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
839 GenFdsGlobalVariable.GenerateFirmwareImage(
840 TeFile,
841 [GenSecInputFile],
842 Type='te',
843 IsMakefile=IsMakefile
844 )
845 GenSecInputFile = TeFile
846 GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)
847 OutputFileList.append(OutputFile)
848
849 return OutputFileList
850
851 ## __GenSimpleFileFfs__() method
852 #
853 # Generate FFS
854 #
855 # @param self The object pointer
856 # @param Rule The rule object used to generate section
857 # @param InputFileList The output file list from GenSection
858 # @retval string Generated FFS file name
859 #
860 def __GenSimpleFileFfs__(self, Rule, InputFileList, MakefilePath = None):
861 FfsOutput = self.OutputPath + \
862 os.sep + \
863 self.__ExtendMacro__(Rule.NameGuid) + \
864 '.ffs'
865
866 GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))
867 InputSection = []
868 SectionAlignments = []
869 for InputFile in InputFileList:
870 InputSection.append(InputFile)
871 SectionAlignments.append(Rule.SectAlignment)
872
873 if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('):
874 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
875 if len(PcdValue) == 0:
876 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
877 % (Rule.NameGuid))
878 if PcdValue.startswith('{'):
879 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
880 RegistryGuidStr = PcdValue
881 if len(RegistryGuidStr) == 0:
882 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
883 % (Rule.NameGuid))
884 self.ModuleGuid = RegistryGuidStr
885
886 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,
887 FdfFvFileTypeToFileType[Rule.FvFileType],
888 self.ModuleGuid, Fixed=Rule.Fixed,
889 CheckSum=Rule.CheckSum, Align=Rule.Alignment,
890 SectionAlign=SectionAlignments,
891 MakefilePath=MakefilePath
892 )
893 return FfsOutput
894
895 ## __GenComplexFileSection__() method
896 #
897 # Generate section by sections in Rule
898 #
899 # @param self The object pointer
900 # @param Rule The rule object used to generate section
901 # @param FvChildAddr Array of the inside FvImage base address
902 # @param FvParentAddr Parent Fv base address
903 # @retval string File name of the generated section file
904 #
905 def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr, IsMakefile = False):
906 if self.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE):
907 if Rule.KeepReloc is not None:
908 self.KeepRelocFromRule = Rule.KeepReloc
909 SectFiles = []
910 SectAlignments = []
911 Index = 1
912 HasGeneratedFlag = False
913 if self.PcdIsDriver == 'PEI_PCD_DRIVER':
914 if self.IsBinaryModule:
915 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "PEIPcdDataBase.raw")
916 else:
917 PcdExDbFileName = os.path.join(self.EfiOutputPath, "PEIPcdDataBase.raw")
918 PcdExDbSecName = os.path.join(self.OutputPath, "PEIPcdDataBaseSec.raw")
919 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,
920 [PcdExDbFileName],
921 "EFI_SECTION_RAW",
922 IsMakefile = IsMakefile
923 )
924 SectFiles.append(PcdExDbSecName)
925 SectAlignments.append(None)
926 elif self.PcdIsDriver == 'DXE_PCD_DRIVER':
927 if self.IsBinaryModule:
928 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "DXEPcdDataBase.raw")
929 else:
930 PcdExDbFileName = os.path.join(self.EfiOutputPath, "DXEPcdDataBase.raw")
931 PcdExDbSecName = os.path.join(self.OutputPath, "DXEPcdDataBaseSec.raw")
932 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,
933 [PcdExDbFileName],
934 "EFI_SECTION_RAW",
935 IsMakefile = IsMakefile
936 )
937 SectFiles.append(PcdExDbSecName)
938 SectAlignments.append(None)
939 for Sect in Rule.SectionList:
940 SecIndex = '%d' %Index
941 SectList = []
942 #
943 # Convert Fv Section Type for PI1.1 SMM driver.
944 #
945 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A:
946 if Sect.SectionType == BINARY_FILE_TYPE_DXE_DEPEX:
947 Sect.SectionType = BINARY_FILE_TYPE_SMM_DEPEX
948 #
949 # Framework SMM Driver has no SMM_DEPEX section type
950 #
951 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A:
952 if Sect.SectionType == BINARY_FILE_TYPE_SMM_DEPEX:
953 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
954 #
955 # process the inside FvImage from FvSection or GuidSection
956 #
957 if FvChildAddr != []:
958 if isinstance(Sect, FvImageSection):
959 Sect.FvAddr = FvChildAddr.pop(0)
960 elif isinstance(Sect, GuidSection):
961 Sect.FvAddr = FvChildAddr
962 if FvParentAddr is not None and isinstance(Sect, GuidSection):
963 Sect.FvParentAddr = FvParentAddr
964
965 if Rule.KeyStringList != []:
966 SectList, Align = Sect.GenSection(self.OutputPath, self.ModuleGuid, SecIndex, Rule.KeyStringList, self, IsMakefile = IsMakefile)
967 else :
968 SectList, Align = Sect.GenSection(self.OutputPath, self.ModuleGuid, SecIndex, self.KeyStringList, self, IsMakefile = IsMakefile)
969
970 if not HasGeneratedFlag:
971 UniVfrOffsetFileSection = ""
972 ModuleFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)
973 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]
974 #
975 # Search the source list in InfData to find if there are .vfr file exist.
976 #
977 VfrUniBaseName = {}
978 VfrUniOffsetList = []
979 for SourceFile in InfData.Sources:
980 if SourceFile.Type.upper() == ".VFR" :
981 #
982 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
983 #
984 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
985 if SourceFile.Type.upper() == ".UNI" :
986 #
987 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
988 #
989 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")
990
991
992 if len(VfrUniBaseName) > 0:
993 if IsMakefile:
994 if InfData.BuildType != 'UEFI_HII':
995 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')
996 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')
997 UniVfrOffsetFileNameList = []
998 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
999 TrimCmd = "Trim --Vfr-Uni-Offset -o %s --ModuleName=%s --DebugDir=%s " % (UniVfrOffsetFileName, self.BaseName, self.EfiDebugPath)
1000 GenFdsGlobalVariable.SecCmdList.append(TrimCmd)
1001 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
1002 [UniVfrOffsetFileName],
1003 "EFI_SECTION_RAW",
1004 IsMakefile = True
1005 )
1006 else:
1007 VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)
1008 #
1009 # Generate the Raw data of raw section
1010 #
1011 if VfrUniOffsetList:
1012 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')
1013 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')
1014 FfsInfStatement.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)
1015 UniVfrOffsetFileNameList = []
1016 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
1017 """Call GenSection"""
1018
1019 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
1020 UniVfrOffsetFileNameList,
1021 "EFI_SECTION_RAW"
1022 )
1023 #os.remove(UniVfrOffsetFileName)
1024 if UniVfrOffsetFileSection:
1025 SectList.append(UniVfrOffsetFileSection)
1026 HasGeneratedFlag = True
1027
1028 for SecName in SectList :
1029 SectFiles.append(SecName)
1030 SectAlignments.append(Align)
1031 Index = Index + 1
1032 return SectFiles, SectAlignments
1033
1034 ## __GenComplexFileFfs__() method
1035 #
1036 # Generate FFS
1037 #
1038 # @param self The object pointer
1039 # @param Rule The rule object used to generate section
1040 # @param InputFileList The output file list from GenSection
1041 # @retval string Generated FFS file name
1042 #
1043 def __GenComplexFileFfs__(self, Rule, InputFile, Alignments, MakefilePath = None):
1044
1045 if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('):
1046 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
1047 if len(PcdValue) == 0:
1048 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
1049 % (Rule.NameGuid))
1050 if PcdValue.startswith('{'):
1051 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
1052 RegistryGuidStr = PcdValue
1053 if len(RegistryGuidStr) == 0:
1054 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
1055 % (Rule.NameGuid))
1056 self.ModuleGuid = RegistryGuidStr
1057
1058 FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
1059 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,
1060 FdfFvFileTypeToFileType[Rule.FvFileType],
1061 self.ModuleGuid, Fixed=Rule.Fixed,
1062 CheckSum=Rule.CheckSum, Align=Rule.Alignment,
1063 SectionAlign=Alignments,
1064 MakefilePath=MakefilePath
1065 )
1066 return FfsOutput
1067
1068 ## __GetBuildOutputMapFileVfrUniInfo() method
1069 #
1070 # Find the offset of UNI/INF object offset in the EFI image file.
1071 #
1072 # @param self The object pointer
1073 # @param VfrUniBaseName A name list contain the UNI/INF object name.
1074 # @retval RetValue A list contain offset of UNI/INF object.
1075 #
1076 def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):
1077 MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")
1078 EfiFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".efi")
1079 return GetVariableOffset(MapFileName, EfiFileName, list(VfrUniBaseName.values()))
1080
1081 ## __GenUniVfrOffsetFile() method
1082 #
1083 # Generate the offset file for the module which contain VFR or UNI file.
1084 #
1085 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
1086 # @param UniVfrOffsetFileName The output offset file name.
1087 #
1088 @staticmethod
1089 def __GenUniVfrOffsetFile(VfrUniOffsetList, UniVfrOffsetFileName):
1090
1091 # Use a instance of StringIO to cache data
1092 fStringIO = BytesIO()
1093
1094 for Item in VfrUniOffsetList:
1095 if (Item[0].find("Strings") != -1):
1096 #
1097 # UNI offset in image.
1098 # GUID + Offset
1099 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1100 #
1101 UniGuid = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
1102 fStringIO.write(UniGuid)
1103 UniValue = pack ('Q', int (Item[1], 16))
1104 fStringIO.write (UniValue)
1105 else:
1106 #
1107 # VFR binary offset in image.
1108 # GUID + Offset
1109 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1110 #
1111 VfrGuid = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
1112 fStringIO.write(VfrGuid)
1113 type (Item[1])
1114 VfrValue = pack ('Q', int (Item[1], 16))
1115 fStringIO.write (VfrValue)
1116
1117 #
1118 # write data into file.
1119 #
1120 try :
1121 SaveFileOnChange(UniVfrOffsetFileName, fStringIO.getvalue())
1122 except:
1123 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)
1124
1125 fStringIO.close ()
1126
1127