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