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