]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/FfsInfStatement.py
Sync BaseTool trunk (version r2599) into EDKII BaseTools.
[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 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'AARCH64', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
392 if PlatformDataBase != None:
393 if InfFileKey in (PlatformDataBase.Modules):
394 DscArchList.append ('AARCH64')
395
396 return DscArchList
397
398 ## GetCurrentArch() method
399 #
400 # Get Arch list of the module from this INF is to be placed into flash
401 #
402 # @param self The object pointer
403 # @retval list Arch list
404 #
405 def GetCurrentArch(self) :
406
407 TargetArchList = GenFdsGlobalVariable.ArchList
408
409 PlatformArchList = self.__GetPlatformArchList__()
410
411 CurArchList = TargetArchList
412 if PlatformArchList != []:
413 CurArchList = list(set (TargetArchList) & set (PlatformArchList))
414 GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))
415
416 ArchList = []
417 if self.KeyStringList != []:
418 for Key in self.KeyStringList:
419 Key = GenFdsGlobalVariable.MacroExtend(Key)
420 Target, Tag, Arch = Key.split('_')
421 if Arch in CurArchList:
422 ArchList.append(Arch)
423 if Target not in self.TargetOverrideList:
424 self.TargetOverrideList.append(Target)
425 else:
426 ArchList = CurArchList
427
428 UseArchList = TargetArchList
429 if self.UseArch != None:
430 UseArchList = []
431 UseArchList.append(self.UseArch)
432 ArchList = list(set (UseArchList) & set (ArchList))
433
434 self.InfFileName = NormPath(self.InfFileName)
435 if len(PlatformArchList) == 0:
436 self.InDsc = False
437 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
438 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
439 if ErrorCode != 0:
440 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
441 if len(ArchList) == 1:
442 Arch = ArchList[0]
443 return Arch
444 elif len(ArchList) > 1:
445 if len(PlatformArchList) == 0:
446 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))
447 else:
448 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))
449 else:
450 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." \
451 % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))
452
453 ## __GetEFIOutPutPath__() method
454 #
455 # Get the output path for generated files
456 #
457 # @param self The object pointer
458 # @retval string Path that output files from this INF go to
459 #
460 def __GetEFIOutPutPath__(self):
461 Arch = ''
462 OutputPath = ''
463 (ModulePath, FileName) = os.path.split(self.InfFileName)
464 Index = FileName.rfind('.')
465 FileName = FileName[0:Index]
466 Arch = "NoneArch"
467 if self.CurrentArch != None:
468 Arch = self.CurrentArch
469
470 OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
471 Arch ,
472 ModulePath,
473 FileName,
474 'OUTPUT'
475 )
476 OutputPath = os.path.realpath(OutputPath)
477 return OutputPath
478
479 ## __GenSimpleFileSection__() method
480 #
481 # Generate section by specified file name or a list of files with file extension
482 #
483 # @param self The object pointer
484 # @param Rule The rule object used to generate section
485 # @retval string File name of the generated section file
486 #
487 def __GenSimpleFileSection__(self, Rule):
488 #
489 # Prepare the parameter of GenSection
490 #
491 FileList = []
492 OutputFileList = []
493 GenSecInputFile = None
494 if Rule.FileName != None:
495 GenSecInputFile = self.__ExtendMacro__(Rule.FileName)
496 if os.path.isabs(GenSecInputFile):
497 GenSecInputFile = os.path.normpath(GenSecInputFile)
498 else:
499 GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))
500 else:
501 FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)
502
503 Index = 1
504 SectionType = Rule.SectionType
505 #
506 # Convert Fv Section Type for PI1.1 SMM driver.
507 #
508 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
509 if SectionType == 'DXE_DEPEX':
510 SectionType = 'SMM_DEPEX'
511 #
512 # Framework SMM Driver has no SMM_DEPEX section type
513 #
514 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
515 if SectionType == 'SMM_DEPEX':
516 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
517 NoStrip = True
518 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):
519 if self.KeepReloc != None:
520 NoStrip = self.KeepReloc
521 elif Rule.KeepReloc != None:
522 NoStrip = Rule.KeepReloc
523 elif self.ShadowFromInfFile != None:
524 NoStrip = self.ShadowFromInfFile
525
526 if FileList != [] :
527 for File in FileList:
528
529 SecNum = '%d' %Index
530 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
531 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum
532 Index = Index + 1
533 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
534 File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)
535
536 #Get PE Section alignment when align is set to AUTO
537 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):
538 ImageObj = PeImageClass (File)
539 if ImageObj.SectionAlignment < 0x400:
540 self.Alignment = str (ImageObj.SectionAlignment)
541 else:
542 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'
543
544 if not NoStrip:
545 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
546 if not os.path.exists(FileBeforeStrip) or \
547 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):
548 shutil.copyfile(File, FileBeforeStrip)
549 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
550 GenFdsGlobalVariable.GenerateFirmwareImage(
551 StrippedFile,
552 [File],
553 Strip=True
554 )
555 File = StrippedFile
556
557 if SectionType == 'TE':
558 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
559 GenFdsGlobalVariable.GenerateFirmwareImage(
560 TeFile,
561 [File],
562 Type='te'
563 )
564 File = TeFile
565
566 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType])
567 OutputFileList.append(OutputFile)
568 else:
569 SecNum = '%d' %Index
570 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
571 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum
572 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
573 GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)
574
575 #Get PE Section alignment when align is set to AUTO
576 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):
577 ImageObj = PeImageClass (GenSecInputFile)
578 if ImageObj.SectionAlignment < 0x400:
579 self.Alignment = str (ImageObj.SectionAlignment)
580 else:
581 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'
582
583 if not NoStrip:
584 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
585 if not os.path.exists(FileBeforeStrip) or \
586 (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):
587 shutil.copyfile(GenSecInputFile, FileBeforeStrip)
588 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
589 GenFdsGlobalVariable.GenerateFirmwareImage(
590 StrippedFile,
591 [GenSecInputFile],
592 Strip=True
593 )
594 GenSecInputFile = StrippedFile
595
596 if SectionType == 'TE':
597 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
598 GenFdsGlobalVariable.GenerateFirmwareImage(
599 TeFile,
600 [GenSecInputFile],
601 Type='te'
602 )
603 GenSecInputFile = TeFile
604
605 GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType])
606 OutputFileList.append(OutputFile)
607
608 return OutputFileList
609
610 ## __GenSimpleFileFfs__() method
611 #
612 # Generate FFS
613 #
614 # @param self The object pointer
615 # @param Rule The rule object used to generate section
616 # @param InputFileList The output file list from GenSection
617 # @retval string Generated FFS file name
618 #
619 def __GenSimpleFileFfs__(self, Rule, InputFileList):
620 FfsOutput = self.OutputPath + \
621 os.sep + \
622 self.__ExtendMacro__(Rule.NameGuid) + \
623 '.ffs'
624
625 GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))
626 InputSection = []
627 SectionAlignments = []
628 for InputFile in InputFileList:
629 InputSection.append(InputFile)
630 SectionAlignments.append(Rule.SectAlignment)
631
632 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):
633 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
634 if len(PcdValue) == 0:
635 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
636 % (Rule.NameGuid))
637 if PcdValue.startswith('{'):
638 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
639 RegistryGuidStr = PcdValue
640 if len(RegistryGuidStr) == 0:
641 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
642 % (Rule.NameGuid))
643 self.ModuleGuid = RegistryGuidStr
644
645 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,
646 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],
647 self.ModuleGuid, Fixed=Rule.Fixed,
648 CheckSum=Rule.CheckSum, Align=Rule.Alignment,
649 SectionAlign=SectionAlignments
650 )
651 return FfsOutput
652
653 ## __GenComplexFileSection__() method
654 #
655 # Generate section by sections in Rule
656 #
657 # @param self The object pointer
658 # @param Rule The rule object used to generate section
659 # @param FvChildAddr Array of the inside FvImage base address
660 # @param FvParentAddr Parent Fv base address
661 # @retval string File name of the generated section file
662 #
663 def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr):
664 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):
665 if Rule.KeepReloc != None:
666 self.KeepRelocFromRule = Rule.KeepReloc
667 SectFiles = []
668 SectAlignments = []
669 Index = 1
670 HasGneratedFlag = False
671 for Sect in Rule.SectionList:
672 SecIndex = '%d' %Index
673 SectList = []
674 #
675 # Convert Fv Section Type for PI1.1 SMM driver.
676 #
677 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
678 if Sect.SectionType == 'DXE_DEPEX':
679 Sect.SectionType = 'SMM_DEPEX'
680 #
681 # Framework SMM Driver has no SMM_DEPEX section type
682 #
683 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
684 if Sect.SectionType == 'SMM_DEPEX':
685 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
686 #
687 # process the inside FvImage from FvSection or GuidSection
688 #
689 if FvChildAddr != []:
690 if isinstance(Sect, FvImageSection):
691 Sect.FvAddr = FvChildAddr.pop(0)
692 elif isinstance(Sect, GuidSection):
693 Sect.FvAddr = FvChildAddr
694 if FvParentAddr != None and isinstance(Sect, GuidSection):
695 Sect.FvParentAddr = FvParentAddr
696
697 if Rule.KeyStringList != []:
698 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self)
699 else :
700 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self)
701
702 if not HasGneratedFlag:
703 UniVfrOffsetFileSection = ""
704 ModuleFileName = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)
705 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]
706 #
707 # Search the source list in InfData to find if there are .vfr file exist.
708 #
709 VfrUniBaseName = {}
710 VfrUniOffsetList = []
711 for SourceFile in InfData.Sources:
712 if SourceFile.Type.upper() == ".VFR" :
713 #
714 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
715 #
716 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
717 if SourceFile.Type.upper() == ".UNI" :
718 #
719 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
720 #
721 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")
722
723
724 if len(VfrUniBaseName) > 0:
725 VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)
726 #
727 # Generate the Raw data of raw section
728 #
729 os.path.join( self.OutputPath, self.BaseName + '.offset')
730 UniVfrOffsetFileName = os.path.join( self.OutputPath, self.BaseName + '.offset')
731 UniVfrOffsetFileSection = os.path.join( self.OutputPath, self.BaseName + 'Offset' + '.raw')
732
733 self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)
734
735 UniVfrOffsetFileNameList = []
736 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
737 """Call GenSection"""
738 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
739 UniVfrOffsetFileNameList,
740 "EFI_SECTION_RAW"
741 )
742 os.remove(UniVfrOffsetFileName)
743 SectList.append(UniVfrOffsetFileSection)
744 HasGneratedFlag = True
745
746 for SecName in SectList :
747 SectFiles.append(SecName)
748 SectAlignments.append(Align)
749 Index = Index + 1
750 return SectFiles, SectAlignments
751
752 ## __GenComplexFileFfs__() method
753 #
754 # Generate FFS
755 #
756 # @param self The object pointer
757 # @param Rule The rule object used to generate section
758 # @param InputFileList The output file list from GenSection
759 # @retval string Generated FFS file name
760 #
761 def __GenComplexFileFfs__(self, Rule, InputFile, Alignments):
762
763 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):
764 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
765 if len(PcdValue) == 0:
766 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
767 % (Rule.NameGuid))
768 if PcdValue.startswith('{'):
769 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
770 RegistryGuidStr = PcdValue
771 if len(RegistryGuidStr) == 0:
772 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
773 % (Rule.NameGuid))
774 self.ModuleGuid = RegistryGuidStr
775
776 FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
777 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,
778 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],
779 self.ModuleGuid, Fixed=Rule.Fixed,
780 CheckSum=Rule.CheckSum, Align=Rule.Alignment,
781 SectionAlign=Alignments
782 )
783 return FfsOutput
784
785 ## __GetGenFfsCmdParameter__() method
786 #
787 # Create parameter string for GenFfs
788 #
789 # @param self The object pointer
790 # @param Rule The rule object used to generate section
791 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
792 #
793 def __GetGenFfsCmdParameter__(self, Rule):
794 result = tuple()
795 result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType])
796 if Rule.Fixed != False:
797 result += ('-x',)
798 if Rule.CheckSum != False:
799 result += ('-s',)
800
801 if Rule.Alignment != None and Rule.Alignment != '':
802 result += ('-a', Rule.Alignment)
803
804 return result
805
806 ## __GetBuildOutputMapFileVfrUniInfo() method
807 #
808 # Find the offset of UNI/INF object offset in the EFI image file.
809 #
810 # @param self The object pointer
811 # @param VfrUniBaseName A name list contain the UNI/INF object name.
812 # @retval RetValue A list contain offset of UNI/INF object.
813 #
814 def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):
815
816 RetValue = []
817
818 MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")
819 try:
820 fInputfile = open(MapFileName, "r", 0)
821 try:
822 FileLinesList = fInputfile.readlines()
823 except:
824 EdkLogger.error("GenFds", FILE_READ_FAILURE, "File read failed for %s" %MapFileName,None)
825 finally:
826 fInputfile.close()
827 except:
828 EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %MapFileName,None)
829
830 IsHex = False
831 for eachLine in FileLinesList:
832 for eachName in VfrUniBaseName.values():
833 if eachLine.find(eachName) != -1:
834 eachLine = eachLine.strip()
835 Element = eachLine.split()
836 #
837 # MSFT/ICC/EBC map file
838 #
839 if (len(Element) == 4):
840 try:
841 int (Element[2], 16)
842 IsHex = True
843 except:
844 IsHex = False
845
846 if IsHex:
847 RetValue.append((eachName, Element[2]))
848 IsHex = False
849 #
850 # GCC map file
851 #
852 elif (len(Element) == 2) and Element[0].startswith("0x"):
853 RetValue.append((eachName, Element[0]))
854
855 return RetValue
856
857 ## __GenUniVfrOffsetFile() method
858 #
859 # Generate the offset file for the module which contain VFR or UNI file.
860 #
861 # @param self The object pointer
862 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
863 # @param UniVfrOffsetFileName The output offset file name.
864 #
865 def __GenUniVfrOffsetFile(self, VfrUniOffsetList, UniVfrOffsetFileName):
866
867 try:
868 fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
869 except:
870 EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %UniVfrOffsetFileName,None)
871
872 # Use a instance of StringIO to cache data
873 fStringIO = StringIO.StringIO('')
874
875 for Item in VfrUniOffsetList:
876 if (Item[0].find("Strings") != -1):
877 #
878 # UNI offset in image.
879 # GUID + Offset
880 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
881 #
882 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
883 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]
884 fStringIO.write(''.join(UniGuid))
885 UniValue = pack ('Q', int (Item[1], 16))
886 fStringIO.write (UniValue)
887 else:
888 #
889 # VFR binary offset in image.
890 # GUID + Offset
891 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
892 #
893 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
894 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]
895 fStringIO.write(''.join(VfrGuid))
896 type (Item[1])
897 VfrValue = pack ('Q', int (Item[1], 16))
898 fStringIO.write (VfrValue)
899
900 #
901 # write data into file.
902 #
903 try :
904 fInputfile.write (fStringIO.getvalue())
905 except:
906 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)
907
908 fStringIO.close ()
909 fInputfile.close ()
910
911
912
913
914
915
916
917