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