]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/FfsInfStatement.py
96e212cae7aa7d892ea06b1f2e4af7b21dbb5f04
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / FfsInfStatement.py
1 ## @file
2 # process FFS generation from INF statement
3 #
4 # Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
5 #
6 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
10 #
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 #
14
15 ##
16 # Import Modules
17 #
18 import Rule
19 import os
20 import shutil
21 import StringIO
22 from struct import *
23 from GenFdsGlobalVariable import GenFdsGlobalVariable
24 import Ffs
25 import subprocess
26 import sys
27 import Section
28 import RuleSimpleFile
29 import RuleComplexFile
30 from CommonDataClass.FdfClass import FfsInfStatementClassObject
31 from Common.String import *
32 from Common.Misc import PathClass
33 from Common.Misc import GuidStructureByteArrayToGuidString
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
41 ## generate FFS from INF
42 #
43 #
44 class FfsInfStatement(FfsInfStatementClassObject):
45 ## The constructor
46 #
47 # @param self The object pointer
48 #
49 def __init__(self):
50 FfsInfStatementClassObject.__init__(self)
51 self.TargetOverrideList = []
52 self.ShadowFromInfFile = None
53 self.KeepRelocFromRule = None
54 self.InDsc = True
55 self.OptRomDefs = {}
56 self.PiSpecVersion = '0x00000000'
57 self.InfModule = None
58 self.FinalTargetSuffixMap = {}
59 self.CurrentLineNum = None
60 self.CurrentLineContent = None
61 self.FileName = None
62 self.InfFileName = None
63
64 ## GetFinalTargetSuffixMap() method
65 #
66 # Get final build target list
67 def GetFinalTargetSuffixMap(self):
68 if not self.InfModule or not self.CurrentArch:
69 return []
70 if not self.FinalTargetSuffixMap:
71 FinalBuildTargetList = GenFdsGlobalVariable.GetModuleCodaTargetList(self.InfModule, self.CurrentArch)
72 for File in FinalBuildTargetList:
73 self.FinalTargetSuffixMap.setdefault(os.path.splitext(File)[1], []).append(File)
74
75 # Check if current INF module has DEPEX
76 if '.depex' not in self.FinalTargetSuffixMap and self.InfModule.ModuleType != "USER_DEFINED" \
77 and not self.InfModule.DxsFile and not self.InfModule.LibraryClass:
78 ModuleType = self.InfModule.ModuleType
79 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
80
81 if ModuleType != DataType.SUP_MODULE_USER_DEFINED:
82 for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys():
83 if LibraryClass.startswith("NULL") and PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]:
84 self.InfModule.LibraryClasses[LibraryClass] = PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]
85
86 StrModule = str(self.InfModule)
87 PlatformModule = None
88 if StrModule in PlatformDataBase.Modules:
89 PlatformModule = PlatformDataBase.Modules[StrModule]
90 for LibraryClass in PlatformModule.LibraryClasses:
91 if LibraryClass.startswith("NULL"):
92 self.InfModule.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
93
94 DependencyList = [self.InfModule]
95 LibraryInstance = {}
96 DepexList = []
97 while len(DependencyList) > 0:
98 Module = DependencyList.pop(0)
99 if not Module:
100 continue
101 for Dep in Module.Depex[self.CurrentArch, ModuleType]:
102 if DepexList != []:
103 DepexList.append('AND')
104 DepexList.append('(')
105 DepexList.extend(Dep)
106 if DepexList[-1] == 'END': # no need of a END at this time
107 DepexList.pop()
108 DepexList.append(')')
109 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
110 break
111 for LibName in Module.LibraryClasses:
112 if LibName in LibraryInstance:
113 continue
114 if PlatformModule and LibName in PlatformModule.LibraryClasses:
115 LibraryPath = PlatformModule.LibraryClasses[LibName]
116 else:
117 LibraryPath = PlatformDataBase.LibraryClasses[LibName, ModuleType]
118 if not LibraryPath:
119 LibraryPath = Module.LibraryClasses[LibName]
120 if not LibraryPath:
121 continue
122 LibraryModule = GenFdsGlobalVariable.WorkSpace.BuildObject[LibraryPath, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
123 LibraryInstance[LibName] = LibraryModule
124 DependencyList.append(LibraryModule)
125 if DepexList:
126 Dpx = DependencyExpression(DepexList, ModuleType, True)
127 if len(Dpx.PostfixNotation) != 0:
128 # It means this module has DEPEX
129 self.FinalTargetSuffixMap['.depex'] = [os.path.join(self.EfiOutputPath, self.BaseName) + '.depex']
130 return self.FinalTargetSuffixMap
131
132 ## __InfParse() method
133 #
134 # Parse inf file to get module information
135 #
136 # @param self The object pointer
137 # @param Dict dictionary contains macro and value pair
138 #
139 def __InfParse__(self, Dict = {}):
140
141 GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)
142
143 self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')
144 if self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :
145 self.InfFileName = self.InfFileName[1:]
146
147 if self.InfFileName.find('$') == -1:
148 InfPath = NormPath(self.InfFileName)
149 if not os.path.exists(InfPath):
150 InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath)
151 if not os.path.exists(InfPath):
152 EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName))
153
154 self.CurrentArch = self.GetCurrentArch()
155 #
156 # Get the InfClass object
157 #
158
159 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
160 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
161 if ErrorCode != 0:
162 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
163
164 if self.CurrentArch != None:
165
166 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
167 #
168 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
169 #
170 self.BaseName = Inf.BaseName
171 self.ModuleGuid = Inf.Guid
172 self.ModuleType = Inf.ModuleType
173 if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
174 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']
175 if Inf.AutoGenVersion < 0x00010005:
176 self.ModuleType = Inf.ComponentType
177 self.VersionString = Inf.Version
178 self.BinFileList = Inf.Binaries
179 self.SourceFileList = Inf.Sources
180 if self.KeepReloc == None and Inf.Shadow:
181 self.ShadowFromInfFile = Inf.Shadow
182
183 else:
184 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
185 self.BaseName = Inf.BaseName
186 self.ModuleGuid = Inf.Guid
187 self.ModuleType = Inf.ModuleType
188 if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
189 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']
190 self.VersionString = Inf.Version
191 self.BinFileList = Inf.Binaries
192 self.SourceFileList = Inf.Sources
193 if self.BinFileList == []:
194 EdkLogger.error("GenFds", GENFDS_ERROR,
195 "INF %s specified in FDF could not be found in build ARCH %s!" \
196 % (self.InfFileName, GenFdsGlobalVariable.ArchList))
197
198 if len(self.SourceFileList) != 0 and not self.InDsc:
199 EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))
200
201 if self.ModuleType == 'SMM_CORE' and int(self.PiSpecVersion, 16) < 0x0001000A:
202 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)
203
204 if Inf._Defs != None and len(Inf._Defs) > 0:
205 self.OptRomDefs.update(Inf._Defs)
206
207 self.InfModule = Inf
208
209 GenFdsGlobalVariable.VerboseLogger( "BaseName : %s" %self.BaseName)
210 GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" %self.ModuleGuid)
211 GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" %self.ModuleType)
212 GenFdsGlobalVariable.VerboseLogger("VersionString : %s" %self.VersionString)
213 GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" %self.InfFileName)
214
215 #
216 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
217 #
218
219 self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \
220 self.ModuleGuid + self.BaseName)
221 if not os.path.exists(self.OutputPath) :
222 os.makedirs(self.OutputPath)
223
224 self.EfiOutputPath = self.__GetEFIOutPutPath__()
225 GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)
226
227 ## GenFfs() method
228 #
229 # Generate FFS
230 #
231 # @param self The object pointer
232 # @param Dict dictionary contains macro and value pair
233 # @param FvChildAddr Array of the inside FvImage base address
234 # @param FvParentAddr Parent Fv base address
235 # @retval string Generated FFS file name
236 #
237 def GenFfs(self, Dict = {}, FvChildAddr = [], FvParentAddr=None):
238 #
239 # Parse Inf file get Module related information
240 #
241
242 self.__InfParse__(Dict)
243
244 #
245 # Allow binary type module not specify override rule in FDF file.
246 #
247 if len(self.BinFileList) >0 and not self.InDsc:
248 if self.Rule == None or self.Rule == "":
249 self.Rule = "BINARY"
250
251 #
252 # Get the rule of how to generate Ffs file
253 #
254 Rule = self.__GetRule__()
255 GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)
256 #
257 # Convert Fv File Type for PI1.1 SMM driver.
258 #
259 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
260 if Rule.FvFileType == 'DRIVER':
261 Rule.FvFileType = 'SMM'
262 #
263 # Framework SMM Driver has no SMM FV file type
264 #
265 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
266 if Rule.FvFileType == 'SMM' or Rule.FvFileType == 'SMM_CORE':
267 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File=self.InfFileName)
268 #
269 # For the rule only has simpleFile
270 #
271 if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) :
272 SectionOutputList = self.__GenSimpleFileSection__(Rule)
273 FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList)
274 return FfsOutput
275 #
276 # For Rule has ComplexFile
277 #
278 elif isinstance(Rule, RuleComplexFile.RuleComplexFile):
279 InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr)
280 FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments)
281
282 return FfsOutput
283
284 ## __ExtendMacro__() method
285 #
286 # Replace macro with its value
287 #
288 # @param self The object pointer
289 # @param String The string to be replaced
290 # @retval string Macro replaced string
291 #
292 def __ExtendMacro__ (self, String):
293 MacroDict = {
294 '$(INF_OUTPUT)' : self.EfiOutputPath,
295 '$(MODULE_NAME)' : self.BaseName,
296 '$(BUILD_NUMBER)': self.BuildNum,
297 '$(INF_VERSION)' : self.VersionString,
298 '$(NAMED_GUID)' : self.ModuleGuid
299 }
300 String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)
301 return String
302
303 ## __GetRule__() method
304 #
305 # Get correct rule for generating FFS for this INF
306 #
307 # @param self The object pointer
308 # @retval Rule Rule object
309 #
310 def __GetRule__ (self) :
311 CurrentArchList = []
312 if self.CurrentArch == None:
313 CurrentArchList = ['common']
314 else:
315 CurrentArchList.append(self.CurrentArch)
316
317 for CurrentArch in CurrentArchList:
318 RuleName = 'RULE' + \
319 '.' + \
320 CurrentArch.upper() + \
321 '.' + \
322 self.ModuleType.upper()
323 if self.Rule != None:
324 RuleName = RuleName + \
325 '.' + \
326 self.Rule.upper()
327
328 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
329 if Rule != None:
330 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
331 return Rule
332
333 RuleName = 'RULE' + \
334 '.' + \
335 'COMMON' + \
336 '.' + \
337 self.ModuleType.upper()
338
339 if self.Rule != None:
340 RuleName = RuleName + \
341 '.' + \
342 self.Rule.upper()
343
344 GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))
345
346 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
347 if Rule != None:
348 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
349 return Rule
350
351 if Rule == None :
352 EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \
353 % (RuleName, self.InfFileName))
354
355 ## __GetPlatformArchList__() method
356 #
357 # Get Arch list this INF built under
358 #
359 # @param self The object pointer
360 # @retval list Arch list
361 #
362 def __GetPlatformArchList__(self):
363
364 InfFileKey = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))
365 DscArchList = []
366 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IA32', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
367 if PlatformDataBase != None:
368 if InfFileKey in PlatformDataBase.Modules:
369 DscArchList.append ('IA32')
370
371 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'X64', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
372 if PlatformDataBase != None:
373 if InfFileKey in PlatformDataBase.Modules:
374 DscArchList.append ('X64')
375
376 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IPF', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
377 if PlatformDataBase != None:
378 if InfFileKey in (PlatformDataBase.Modules):
379 DscArchList.append ('IPF')
380
381 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'ARM', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
382 if PlatformDataBase != None:
383 if InfFileKey in (PlatformDataBase.Modules):
384 DscArchList.append ('ARM')
385
386 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'EBC', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
387 if PlatformDataBase != None:
388 if InfFileKey in (PlatformDataBase.Modules):
389 DscArchList.append ('EBC')
390
391 return DscArchList
392
393 ## GetCurrentArch() method
394 #
395 # Get Arch list of the module from this INF is to be placed into flash
396 #
397 # @param self The object pointer
398 # @retval list Arch list
399 #
400 def GetCurrentArch(self) :
401
402 TargetArchList = GenFdsGlobalVariable.ArchList
403
404 PlatformArchList = self.__GetPlatformArchList__()
405
406 CurArchList = TargetArchList
407 if PlatformArchList != []:
408 CurArchList = list(set (TargetArchList) & set (PlatformArchList))
409 GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))
410
411 ArchList = []
412 if self.KeyStringList != []:
413 for Key in self.KeyStringList:
414 Key = GenFdsGlobalVariable.MacroExtend(Key)
415 Target, Tag, Arch = Key.split('_')
416 if Arch in CurArchList:
417 ArchList.append(Arch)
418 if Target not in self.TargetOverrideList:
419 self.TargetOverrideList.append(Target)
420 else:
421 ArchList = CurArchList
422
423 UseArchList = TargetArchList
424 if self.UseArch != None:
425 UseArchList = []
426 UseArchList.append(self.UseArch)
427 ArchList = list(set (UseArchList) & set (ArchList))
428
429 self.InfFileName = NormPath(self.InfFileName)
430 if len(PlatformArchList) == 0:
431 self.InDsc = False
432 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
433 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
434 if ErrorCode != 0:
435 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
436 if len(ArchList) == 1:
437 Arch = ArchList[0]
438 return Arch
439 elif len(ArchList) > 1:
440 if len(PlatformArchList) == 0:
441 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))
442 else:
443 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))
444 else:
445 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." \
446 % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))
447
448 ## __GetEFIOutPutPath__() method
449 #
450 # Get the output path for generated files
451 #
452 # @param self The object pointer
453 # @retval string Path that output files from this INF go to
454 #
455 def __GetEFIOutPutPath__(self):
456 Arch = ''
457 OutputPath = ''
458 (ModulePath, FileName) = os.path.split(self.InfFileName)
459 Index = FileName.rfind('.')
460 FileName = FileName[0:Index]
461 Arch = "NoneArch"
462 if self.CurrentArch != None:
463 Arch = self.CurrentArch
464
465 OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
466 Arch ,
467 ModulePath,
468 FileName,
469 'OUTPUT'
470 )
471 OutputPath = os.path.realpath(OutputPath)
472 return OutputPath
473
474 ## __GenSimpleFileSection__() method
475 #
476 # Generate section by specified file name or a list of files with file extension
477 #
478 # @param self The object pointer
479 # @param Rule The rule object used to generate section
480 # @retval string File name of the generated section file
481 #
482 def __GenSimpleFileSection__(self, Rule):
483 #
484 # Prepare the parameter of GenSection
485 #
486 FileList = []
487 OutputFileList = []
488 GenSecInputFile = None
489 if Rule.FileName != None:
490 GenSecInputFile = self.__ExtendMacro__(Rule.FileName)
491 if os.path.isabs(GenSecInputFile):
492 GenSecInputFile = os.path.normpath(GenSecInputFile)
493 else:
494 GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))
495 else:
496 FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)
497
498 Index = 1
499 SectionType = Rule.SectionType
500 #
501 # Convert Fv Section Type for PI1.1 SMM driver.
502 #
503 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
504 if SectionType == 'DXE_DEPEX':
505 SectionType = 'SMM_DEPEX'
506 #
507 # Framework SMM Driver has no SMM_DEPEX section type
508 #
509 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
510 if SectionType == 'SMM_DEPEX':
511 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
512 NoStrip = True
513 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):
514 if self.KeepReloc != None:
515 NoStrip = self.KeepReloc
516 elif Rule.KeepReloc != None:
517 NoStrip = Rule.KeepReloc
518 elif self.ShadowFromInfFile != None:
519 NoStrip = self.ShadowFromInfFile
520
521 if FileList != [] :
522 for File in FileList:
523
524 SecNum = '%d' %Index
525 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
526 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum
527 Index = Index + 1
528 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
529 File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)
530
531 #Get PE Section alignment when align is set to AUTO
532 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):
533 ImageObj = PeImageClass (File)
534 if ImageObj.SectionAlignment < 0x400:
535 self.Alignment = str (ImageObj.SectionAlignment)
536 else:
537 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'
538
539 if not NoStrip:
540 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
541 if not os.path.exists(FileBeforeStrip) or \
542 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):
543 shutil.copyfile(File, FileBeforeStrip)
544 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
545 GenFdsGlobalVariable.GenerateFirmwareImage(
546 StrippedFile,
547 [File],
548 Strip=True
549 )
550 File = StrippedFile
551
552 if SectionType == 'TE':
553 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
554 GenFdsGlobalVariable.GenerateFirmwareImage(
555 TeFile,
556 [File],
557 Type='te'
558 )
559 File = TeFile
560
561 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType])
562 OutputFileList.append(OutputFile)
563 else:
564 SecNum = '%d' %Index
565 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
566 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum
567 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
568 GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)
569
570 #Get PE Section alignment when align is set to AUTO
571 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):
572 ImageObj = PeImageClass (GenSecInputFile)
573 if ImageObj.SectionAlignment < 0x400:
574 self.Alignment = str (ImageObj.SectionAlignment)
575 else:
576 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'
577
578 if not NoStrip:
579 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
580 if not os.path.exists(FileBeforeStrip) or \
581 (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):
582 shutil.copyfile(GenSecInputFile, FileBeforeStrip)
583 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
584 GenFdsGlobalVariable.GenerateFirmwareImage(
585 StrippedFile,
586 [GenSecInputFile],
587 Strip=True
588 )
589 GenSecInputFile = StrippedFile
590
591 if SectionType == 'TE':
592 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
593 GenFdsGlobalVariable.GenerateFirmwareImage(
594 TeFile,
595 [GenSecInputFile],
596 Type='te'
597 )
598 GenSecInputFile = TeFile
599
600 GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType])
601 OutputFileList.append(OutputFile)
602
603 return OutputFileList
604
605 ## __GenSimpleFileFfs__() method
606 #
607 # Generate FFS
608 #
609 # @param self The object pointer
610 # @param Rule The rule object used to generate section
611 # @param InputFileList The output file list from GenSection
612 # @retval string Generated FFS file name
613 #
614 def __GenSimpleFileFfs__(self, Rule, InputFileList):
615 FfsOutput = self.OutputPath + \
616 os.sep + \
617 self.__ExtendMacro__(Rule.NameGuid) + \
618 '.ffs'
619
620 GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))
621 InputSection = []
622 SectionAlignments = []
623 for InputFile in InputFileList:
624 InputSection.append(InputFile)
625 SectionAlignments.append(Rule.SectAlignment)
626
627 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):
628 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
629 if len(PcdValue) == 0:
630 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
631 % (Rule.NameGuid))
632 if PcdValue.startswith('{'):
633 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
634 RegistryGuidStr = PcdValue
635 if len(RegistryGuidStr) == 0:
636 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
637 % (Rule.NameGuid))
638 self.ModuleGuid = RegistryGuidStr
639
640 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,
641 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],
642 self.ModuleGuid, Fixed=Rule.Fixed,
643 CheckSum=Rule.CheckSum, Align=Rule.Alignment,
644 SectionAlign=SectionAlignments
645 )
646 return FfsOutput
647
648 ## __GenComplexFileSection__() method
649 #
650 # Generate section by sections in Rule
651 #
652 # @param self The object pointer
653 # @param Rule The rule object used to generate section
654 # @param FvChildAddr Array of the inside FvImage base address
655 # @param FvParentAddr Parent Fv base address
656 # @retval string File name of the generated section file
657 #
658 def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr):
659 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):
660 if Rule.KeepReloc != None:
661 self.KeepRelocFromRule = Rule.KeepReloc
662 SectFiles = []
663 SectAlignments = []
664 Index = 1
665 HasGneratedFlag = False
666 for Sect in Rule.SectionList:
667 SecIndex = '%d' %Index
668 SectList = []
669 #
670 # Convert Fv Section Type for PI1.1 SMM driver.
671 #
672 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
673 if Sect.SectionType == 'DXE_DEPEX':
674 Sect.SectionType = 'SMM_DEPEX'
675 #
676 # Framework SMM Driver has no SMM_DEPEX section type
677 #
678 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
679 if Sect.SectionType == 'SMM_DEPEX':
680 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
681 #
682 # process the inside FvImage from FvSection or GuidSection
683 #
684 if FvChildAddr != []:
685 if isinstance(Sect, FvImageSection):
686 Sect.FvAddr = FvChildAddr.pop(0)
687 elif isinstance(Sect, GuidSection):
688 Sect.FvAddr = FvChildAddr
689 if FvParentAddr != None and isinstance(Sect, GuidSection):
690 Sect.FvParentAddr = FvParentAddr
691
692 if Rule.KeyStringList != []:
693 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self)
694 else :
695 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self)
696
697 if not HasGneratedFlag:
698 UniVfrOffsetFileSection = ""
699 ModuleFileName = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)
700 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]
701 #
702 # Search the source list in InfData to find if there are .vfr file exist.
703 #
704 VfrUniBaseName = {}
705 VfrUniOffsetList = []
706 for SourceFile in InfData.Sources:
707 if SourceFile.Type.upper() == ".VFR" :
708 #
709 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
710 #
711 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
712 if SourceFile.Type.upper() == ".UNI" :
713 #
714 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
715 #
716 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")
717
718
719 if len(VfrUniBaseName) > 0:
720 VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)
721 #
722 # Generate the Raw data of raw section
723 #
724 os.path.join( self.OutputPath, self.BaseName + '.offset')
725 UniVfrOffsetFileName = os.path.join( self.OutputPath, self.BaseName + '.offset')
726 UniVfrOffsetFileSection = os.path.join( self.OutputPath, self.BaseName + 'Offset' + '.raw')
727
728 self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)
729
730 UniVfrOffsetFileNameList = []
731 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
732 """Call GenSection"""
733 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
734 UniVfrOffsetFileNameList,
735 "EFI_SECTION_RAW"
736 )
737 os.remove(UniVfrOffsetFileName)
738 SectList.append(UniVfrOffsetFileSection)
739 HasGneratedFlag = True
740
741 for SecName in SectList :
742 SectFiles.append(SecName)
743 SectAlignments.append(Align)
744 Index = Index + 1
745 return SectFiles, SectAlignments
746
747 ## __GenComplexFileFfs__() method
748 #
749 # Generate FFS
750 #
751 # @param self The object pointer
752 # @param Rule The rule object used to generate section
753 # @param InputFileList The output file list from GenSection
754 # @retval string Generated FFS file name
755 #
756 def __GenComplexFileFfs__(self, Rule, InputFile, Alignments):
757
758 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):
759 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
760 if len(PcdValue) == 0:
761 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
762 % (Rule.NameGuid))
763 if PcdValue.startswith('{'):
764 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
765 RegistryGuidStr = PcdValue
766 if len(RegistryGuidStr) == 0:
767 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
768 % (Rule.NameGuid))
769 self.ModuleGuid = RegistryGuidStr
770
771 FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
772 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,
773 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],
774 self.ModuleGuid, Fixed=Rule.Fixed,
775 CheckSum=Rule.CheckSum, Align=Rule.Alignment,
776 SectionAlign=Alignments
777 )
778 return FfsOutput
779
780 ## __GetGenFfsCmdParameter__() method
781 #
782 # Create parameter string for GenFfs
783 #
784 # @param self The object pointer
785 # @param Rule The rule object used to generate section
786 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
787 #
788 def __GetGenFfsCmdParameter__(self, Rule):
789 result = tuple()
790 result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType])
791 if Rule.Fixed != False:
792 result += ('-x',)
793 if Rule.CheckSum != False:
794 result += ('-s',)
795
796 if Rule.Alignment != None and Rule.Alignment != '':
797 result += ('-a', Rule.Alignment)
798
799 return result
800
801 ## __GetBuildOutputMapFileVfrUniInfo() method
802 #
803 # Find the offset of UNI/INF object offset in the EFI image file.
804 #
805 # @param self The object pointer
806 # @param VfrUniBaseName A name list contain the UNI/INF object name.
807 # @retval RetValue A list contain offset of UNI/INF object.
808 #
809 def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):
810
811 RetValue = []
812
813 MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")
814 try:
815 fInputfile = open(MapFileName, "r", 0)
816 try:
817 FileLinesList = fInputfile.readlines()
818 except:
819 EdkLogger.error("GenFds", FILE_READ_FAILURE, "File read failed for %s" %MapFileName,None)
820 finally:
821 fInputfile.close()
822 except:
823 EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %MapFileName,None)
824
825 IsHex = False
826 for eachLine in FileLinesList:
827 for eachName in VfrUniBaseName.values():
828 if eachLine.find(eachName) != -1:
829 eachLine = eachLine.strip()
830 Element = eachLine.split()
831 #
832 # MSFT/ICC/EBC map file
833 #
834 if (len(Element) == 4):
835 try:
836 int (Element[2], 16)
837 IsHex = True
838 except:
839 IsHex = False
840
841 if IsHex:
842 RetValue.append((eachName, Element[2]))
843 IsHex = False
844 #
845 # GCC map file
846 #
847 elif (len(Element) == 2) and Element[0].startswith("0x"):
848 RetValue.append((eachName, Element[0]))
849
850 return RetValue
851
852 ## __GenUniVfrOffsetFile() method
853 #
854 # Generate the offset file for the module which contain VFR or UNI file.
855 #
856 # @param self The object pointer
857 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
858 # @param UniVfrOffsetFileName The output offset file name.
859 #
860 def __GenUniVfrOffsetFile(self, VfrUniOffsetList, UniVfrOffsetFileName):
861
862 try:
863 fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
864 except:
865 EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %UniVfrOffsetFileName,None)
866
867 # Use a instance of StringIO to cache data
868 fStringIO = StringIO.StringIO('')
869
870 for Item in VfrUniOffsetList:
871 if (Item[0].find("Strings") != -1):
872 #
873 # UNI offset in image.
874 # GUID + Offset
875 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
876 #
877 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
878 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]
879 fStringIO.write(''.join(UniGuid))
880 UniValue = pack ('Q', int (Item[1], 16))
881 fStringIO.write (UniValue)
882 else:
883 #
884 # VFR binary offset in image.
885 # GUID + Offset
886 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
887 #
888 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
889 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]
890 fStringIO.write(''.join(VfrGuid))
891 type (Item[1])
892 VfrValue = pack ('Q', int (Item[1], 16))
893 fStringIO.write (VfrValue)
894
895 #
896 # write data into file.
897 #
898 try :
899 fInputfile.write (fStringIO.getvalue())
900 except:
901 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)
902
903 fStringIO.close ()
904 fInputfile.close ()
905
906
907
908
909
910
911
912