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