2 # process FFS generation from INF statement
4 # Copyright (c) 2007, Intel Corporation
6 # All rights reserved. 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
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.
21 from GenFdsGlobalVariable
import GenFdsGlobalVariable
27 import RuleComplexFile
28 from CommonDataClass
.FdfClass
import FfsInfStatementClassObject
29 from Common
.String
import *
30 from Common
.Misc
import PathClass
31 from Common
.Misc
import GuidStructureByteArrayToGuidString
32 from Common
import EdkLogger
33 from Common
.BuildToolError
import *
35 ## generate FFS from INF
38 class FfsInfStatement(FfsInfStatementClassObject
):
41 # @param self The object pointer
44 FfsInfStatementClassObject
.__init
__(self
)
45 self
.TargetOverrideList
= []
46 self
.ShadowFromInfFile
= None
47 self
.KeepRelocFromRule
= None
51 ## __InfParse() method
53 # Parse inf file to get module information
55 # @param self The object pointer
56 # @param Dict dictionary contains macro and value pair
58 def __InfParse__(self
, Dict
= {}):
60 GenFdsGlobalVariable
.VerboseLogger( " Begine parsing INf file : %s" %self
.InfFileName
)
62 self
.InfFileName
= self
.InfFileName
.replace('$(WORKSPACE)', '')
63 if self
.InfFileName
[0] == '\\' or self
.InfFileName
[0] == '/' :
64 self
.InfFileName
= self
.InfFileName
[1:]
66 if self
.InfFileName
.find('$') == -1:
67 InfPath
= NormPath(self
.InfFileName
)
68 if not os
.path
.exists(InfPath
):
69 InfPath
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(InfPath
)
70 if not os
.path
.exists(InfPath
):
71 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Non-existant Module %s !" % (self
.InfFileName
))
73 self
.CurrentArch
= self
.GetCurrentArch()
75 # Get the InfClass object
78 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
79 ErrorCode
, ErrorInfo
= PathClassObj
.Validate()
81 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
83 if self
.CurrentArch
!= None:
85 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, self
.CurrentArch
]
87 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
89 self
.BaseName
= Inf
.BaseName
90 self
.ModuleGuid
= Inf
.Guid
91 self
.ModuleType
= Inf
.ModuleType
92 if Inf
.AutoGenVersion
< 0x00010005:
93 self
.ModuleType
= Inf
.ComponentType
94 self
.VersionString
= Inf
.Version
95 self
.BinFileList
= Inf
.Binaries
96 self
.SourceFileList
= Inf
.Sources
97 if self
.KeepReloc
== None and Inf
.Shadow
:
98 self
.ShadowFromInfFile
= Inf
.Shadow
101 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, 'COMMON']
102 self
.BaseName
= Inf
.BaseName
103 self
.ModuleGuid
= Inf
.Guid
104 self
.ModuleType
= Inf
.ModuleType
105 self
.VersionString
= Inf
.Version
106 self
.BinFileList
= Inf
.Binaries
107 self
.SourceFileList
= Inf
.Sources
108 if self
.BinFileList
== []:
109 EdkLogger
.error("GenFds", GENFDS_ERROR
,
110 "INF %s specified in FDF could not be found in build ARCH %s!" \
111 % (self
.InfFileName
, GenFdsGlobalVariable
.ArchList
))
113 if len(self
.SourceFileList
) != 0 and not self
.InDsc
:
114 EdkLogger
.warn("GenFds", GENFDS_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % (self
.InfFileName
))
116 if Inf
._Defs
!= None and len(Inf
._Defs
) > 0:
117 self
.OptRomDefs
.update(Inf
._Defs
)
119 GenFdsGlobalVariable
.VerboseLogger( "BaseName : %s" %self
.BaseName
)
120 GenFdsGlobalVariable
.VerboseLogger("ModuleGuid : %s" %self
.ModuleGuid
)
121 GenFdsGlobalVariable
.VerboseLogger("ModuleType : %s" %self
.ModuleType
)
122 GenFdsGlobalVariable
.VerboseLogger("VersionString : %s" %self
.VersionString
)
123 GenFdsGlobalVariable
.VerboseLogger("InfFileName :%s" %self
.InfFileName
)
126 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
129 self
.OutputPath
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, \
130 self
.ModuleGuid
+ self
.BaseName
)
131 if not os
.path
.exists(self
.OutputPath
) :
132 os
.makedirs(self
.OutputPath
)
134 self
.EfiOutputPath
= self
.__GetEFIOutPutPath
__()
135 GenFdsGlobalVariable
.VerboseLogger( "ModuelEFIPath: " + self
.EfiOutputPath
)
141 # @param self The object pointer
142 # @param Dict dictionary contains macro and value pair
143 # @retval string Generated FFS file name
145 def GenFfs(self
, Dict
= {}):
147 # Parse Inf file get Module related information
150 self
.__InfParse
__(Dict
)
152 # Get the rule of how to generate Ffs file
154 Rule
= self
.__GetRule
__()
155 GenFdsGlobalVariable
.VerboseLogger( "Packing binaries from inf file : %s" %self
.InfFileName
)
156 #FileType = Ffs.Ffs.ModuleTypeToFileType[Rule.ModuleType]
158 # For the rule only has simpleFile
160 if isinstance (Rule
, RuleSimpleFile
.RuleSimpleFile
) :
161 SectionOutputList
= self
.__GenSimpleFileSection
__(Rule
)
162 FfsOutput
= self
.__GenSimpleFileFfs
__(Rule
, SectionOutputList
)
165 # For Rule has ComplexFile
167 elif isinstance(Rule
, RuleComplexFile
.RuleComplexFile
):
168 InputSectList
, InputSectAlignments
= self
.__GenComplexFileSection
__(Rule
)
169 FfsOutput
= self
.__GenComplexFileFfs
__(Rule
, InputSectList
, InputSectAlignments
)
173 ## __ExtendMacro__() method
175 # Replace macro with its value
177 # @param self The object pointer
178 # @param String The string to be replaced
179 # @retval string Macro replaced string
181 def __ExtendMacro__ (self
, String
):
183 '$(INF_OUTPUT)' : self
.EfiOutputPath
,
184 '$(MODULE_NAME)' : self
.BaseName
,
185 '$(BUILD_NUMBER)': self
.BuildNum
,
186 '$(INF_VERSION)' : self
.VersionString
,
187 '$(NAMED_GUID)' : self
.ModuleGuid
189 String
= GenFdsGlobalVariable
.MacroExtend(String
, MacroDict
)
192 ## __GetRule__() method
194 # Get correct rule for generating FFS for this INF
196 # @param self The object pointer
197 # @retval Rule Rule object
199 def __GetRule__ (self
) :
201 if self
.CurrentArch
== None:
202 CurrentArchList
= ['common']
204 CurrentArchList
.append(self
.CurrentArch
)
206 for CurrentArch
in CurrentArchList
:
207 RuleName
= 'RULE' + \
209 CurrentArch
.upper() + \
211 self
.ModuleType
.upper()
212 if self
.Rule
!= None:
213 RuleName
= RuleName
+ \
217 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
219 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
222 RuleName
= 'RULE' + \
226 self
.ModuleType
.upper()
228 if self
.Rule
!= None:
229 RuleName
= RuleName
+ \
233 GenFdsGlobalVariable
.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName
, self
.InfFileName
))
235 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
237 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
241 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'Don\'t Find common rule %s for INF %s' \
242 % (RuleName
, self
.InfFileName
))
244 ## __GetPlatformArchList__() method
246 # Get Arch list this INF built under
248 # @param self The object pointer
249 # @retval list Arch list
251 def __GetPlatformArchList__(self
):
253 InfFileKey
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
))
255 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IA32']
256 if PlatformDataBase
!= None:
257 if InfFileKey
in PlatformDataBase
.Modules
:
258 DscArchList
.append ('IA32')
260 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'X64']
261 if PlatformDataBase
!= None:
262 if InfFileKey
in PlatformDataBase
.Modules
:
263 DscArchList
.append ('X64')
265 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IPF']
266 if PlatformDataBase
!= None:
267 if InfFileKey
in (PlatformDataBase
.Modules
):
268 DscArchList
.append ('IPF')
270 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'ARM']
271 if PlatformDataBase
!= None:
272 if InfFileKey
in (PlatformDataBase
.Modules
):
273 DscArchList
.append ('ARM')
275 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'EBC']
276 if PlatformDataBase
!= None:
277 if InfFileKey
in (PlatformDataBase
.Modules
):
278 DscArchList
.append ('EBC')
282 ## GetCurrentArch() method
284 # Get Arch list of the module from this INF is to be placed into flash
286 # @param self The object pointer
287 # @retval list Arch list
289 def GetCurrentArch(self
) :
291 TargetArchList
= GenFdsGlobalVariable
.ArchList
293 PlatformArchList
= self
.__GetPlatformArchList
__()
295 CurArchList
= TargetArchList
296 if PlatformArchList
!= []:
297 CurArchList
= list(set (TargetArchList
) & set (PlatformArchList
))
298 GenFdsGlobalVariable
.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList
))
301 if self
.KeyStringList
!= []:
302 for Key
in self
.KeyStringList
:
303 Key
= GenFdsGlobalVariable
.MacroExtend(Key
)
304 Target
, Tag
, Arch
= Key
.split('_')
305 if Arch
in CurArchList
:
306 ArchList
.append(Arch
)
307 if Target
not in self
.TargetOverrideList
:
308 self
.TargetOverrideList
.append(Target
)
310 ArchList
= CurArchList
312 UseArchList
= TargetArchList
313 if self
.UseArch
!= None:
315 UseArchList
.append(self
.UseArch
)
316 ArchList
= list(set (UseArchList
) & set (ArchList
))
318 self
.InfFileName
= NormPath(self
.InfFileName
)
319 if len(PlatformArchList
) == 0:
321 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
322 ErrorCode
, ErrorInfo
= PathClassObj
.Validate()
324 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
325 if len(ArchList
) == 1:
328 elif len(ArchList
) > 1:
329 if len(PlatformArchList
) == 0:
330 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
))
332 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
))
334 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." \
335 % (self
.InfFileName
, str(PlatformArchList
), GenFdsGlobalVariable
.ActivePlatform
, str(set (UseArchList
) & set (TargetArchList
))))
337 ## __GetEFIOutPutPath__() method
339 # Get the output path for generated files
341 # @param self The object pointer
342 # @retval string Path that output files from this INF go to
344 def __GetEFIOutPutPath__(self
):
347 (ModulePath
, FileName
) = os
.path
.split(self
.InfFileName
)
348 Index
= FileName
.find('.')
349 FileName
= FileName
[0:Index
]
351 if self
.CurrentArch
!= None:
352 Arch
= self
.CurrentArch
354 OutputPath
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
],
360 OutputPath
= os
.path
.realpath(OutputPath
)
363 ## __GenSimpleFileSection__() method
365 # Generate section by specified file name or a list of files with file extension
367 # @param self The object pointer
368 # @param Rule The rule object used to generate section
369 # @retval string File name of the generated section file
371 def __GenSimpleFileSection__(self
, Rule
):
373 # Prepare the parameter of GenSection
377 if Rule
.FileName
!= None:
378 GenSecInputFile
= self
.__ExtendMacro
__(Rule
.FileName
)
380 FileList
, IsSect
= Section
.Section
.GetFileList(self
, '', Rule
.FileExtension
)
383 SectionType
= Rule
.SectionType
385 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
386 if self
.KeepReloc
!= None:
387 NoStrip
= self
.KeepReloc
388 elif Rule
.KeepReloc
!= None:
389 NoStrip
= Rule
.KeepReloc
390 elif self
.ShadowFromInfFile
!= None:
391 NoStrip
= self
.ShadowFromInfFile
394 for File
in FileList
:
397 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
398 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
400 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
403 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
404 if not os
.path
.exists(FileBeforeStrip
) or \
405 (os
.path
.getmtime(File
) > os
.path
.getmtime(FileBeforeStrip
)):
406 shutil
.copyfile(File
, FileBeforeStrip
)
407 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
408 GenFdsGlobalVariable
.GenerateFirmwareImage(
410 [GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)],
415 if SectionType
== 'TE':
416 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
417 GenFdsGlobalVariable
.GenerateFirmwareImage(
419 [GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)],
424 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [File
], Section
.Section
.SectionType
[SectionType
])
425 OutputFileList
.append(OutputFile
)
428 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
429 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
430 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
433 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
434 if not os
.path
.exists(FileBeforeStrip
) or \
435 (os
.path
.getmtime(GenSecInputFile
) > os
.path
.getmtime(FileBeforeStrip
)):
436 shutil
.copyfile(GenSecInputFile
, FileBeforeStrip
)
437 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
438 GenFdsGlobalVariable
.GenerateFirmwareImage(
440 [GenFdsGlobalVariable
.MacroExtend(GenSecInputFile
, Dict
, self
.CurrentArch
)],
443 GenSecInputFile
= StrippedFile
445 if SectionType
== 'TE':
446 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
447 GenFdsGlobalVariable
.GenerateFirmwareImage(
449 [GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)],
452 GenSecInputFile
= TeFile
454 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [GenSecInputFile
], Section
.Section
.SectionType
[SectionType
])
455 OutputFileList
.append(OutputFile
)
457 return OutputFileList
459 ## __GenSimpleFileFfs__() method
463 # @param self The object pointer
464 # @param Rule The rule object used to generate section
465 # @param InputFileList The output file list from GenSection
466 # @retval string Generated FFS file name
468 def __GenSimpleFileFfs__(self
, Rule
, InputFileList
):
469 FfsOutput
= self
.OutputPath
+ \
471 self
.__ExtendMacro
__(Rule
.NameGuid
) + \
474 GenFdsGlobalVariable
.VerboseLogger(self
.__ExtendMacro
__(Rule
.NameGuid
))
476 SectionAlignments
= []
477 for InputFile
in InputFileList
:
478 InputSection
.append(InputFile
)
479 SectionAlignments
.append(Rule
.Alignment
)
481 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
482 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
483 if len(PcdValue
) == 0:
484 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
486 if PcdValue
.startswith('{'):
487 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
488 RegistryGuidStr
= PcdValue
489 if len(RegistryGuidStr
) == 0:
490 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
492 self
.ModuleGuid
= RegistryGuidStr
494 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputSection
,
495 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
496 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
497 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
498 SectionAlign
=SectionAlignments
502 ## __GenComplexFileSection__() method
504 # Generate section by sections in Rule
506 # @param self The object pointer
507 # @param Rule The rule object used to generate section
508 # @retval string File name of the generated section file
510 def __GenComplexFileSection__(self
, Rule
):
511 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
512 if Rule
.KeepReloc
!= None:
513 self
.KeepRelocFromRule
= Rule
.KeepReloc
517 for Sect
in Rule
.SectionList
:
518 SecIndex
= '%d' %Index
520 if Rule
.KeyStringList
!= []:
521 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, Rule
.KeyStringList
, self
)
523 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, self
.KeyStringList
, self
)
524 for SecName
in SectList
:
525 SectFiles
.append(SecName
)
526 SectAlignments
.append(Align
)
528 return SectFiles
, SectAlignments
530 ## __GenComplexFileFfs__() method
534 # @param self The object pointer
535 # @param Rule The rule object used to generate section
536 # @param InputFileList The output file list from GenSection
537 # @retval string Generated FFS file name
539 def __GenComplexFileFfs__(self
, Rule
, InputFile
, Alignments
):
541 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
542 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
543 if len(PcdValue
) == 0:
544 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
546 if PcdValue
.startswith('{'):
547 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
548 RegistryGuidStr
= PcdValue
549 if len(RegistryGuidStr
) == 0:
550 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
552 self
.ModuleGuid
= RegistryGuidStr
554 FfsOutput
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
555 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputFile
,
556 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
557 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
558 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
559 SectionAlign
=Alignments
563 ## __GetGenFfsCmdParameter__() method
565 # Create parameter string for GenFfs
567 # @param self The object pointer
568 # @param Rule The rule object used to generate section
569 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
571 def __GetGenFfsCmdParameter__(self
, Rule
):
573 result
+= ('-t', Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
])
574 if Rule
.Fixed
!= False:
576 if Rule
.CheckSum
!= False:
579 if Rule
.Alignment
!= None and Rule
.Alignment
!= '':
580 result
+= ('-a', Rule
.Alignment
)