2 # process FFS generation from INF statement
4 # Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
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
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.
23 from GenFdsGlobalVariable
import GenFdsGlobalVariable
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 from PatchPcdValue
.PatchPcdValue
import PatchBinaryFile
42 ## generate FFS from INF
45 class FfsInfStatement(FfsInfStatementClassObject
):
46 ## The mapping dictionary from datum type to its maximum number.
47 _MAX_SIZE_TYPE
= {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}
50 # @param self The object pointer
53 FfsInfStatementClassObject
.__init
__(self
)
54 self
.TargetOverrideList
= []
55 self
.ShadowFromInfFile
= None
56 self
.KeepRelocFromRule
= None
59 self
.PiSpecVersion
= '0x00000000'
61 self
.FinalTargetSuffixMap
= {}
62 self
.CurrentLineNum
= None
63 self
.CurrentLineContent
= None
65 self
.InfFileName
= None
67 ## GetFinalTargetSuffixMap() method
69 # Get final build target list
70 def GetFinalTargetSuffixMap(self
):
71 if not self
.InfModule
or not self
.CurrentArch
:
73 if not self
.FinalTargetSuffixMap
:
74 FinalBuildTargetList
= GenFdsGlobalVariable
.GetModuleCodaTargetList(self
.InfModule
, self
.CurrentArch
)
75 for File
in FinalBuildTargetList
:
76 self
.FinalTargetSuffixMap
.setdefault(os
.path
.splitext(File
)[1], []).append(File
)
78 # Check if current INF module has DEPEX
79 if '.depex' not in self
.FinalTargetSuffixMap
and self
.InfModule
.ModuleType
!= "USER_DEFINED" \
80 and not self
.InfModule
.DxsFile
and not self
.InfModule
.LibraryClass
:
81 ModuleType
= self
.InfModule
.ModuleType
82 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
84 if ModuleType
!= DataType
.SUP_MODULE_USER_DEFINED
:
85 for LibraryClass
in PlatformDataBase
.LibraryClasses
.GetKeys():
86 if LibraryClass
.startswith("NULL") and PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]:
87 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]
89 StrModule
= str(self
.InfModule
)
91 if StrModule
in PlatformDataBase
.Modules
:
92 PlatformModule
= PlatformDataBase
.Modules
[StrModule
]
93 for LibraryClass
in PlatformModule
.LibraryClasses
:
94 if LibraryClass
.startswith("NULL"):
95 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
97 DependencyList
= [self
.InfModule
]
100 while len(DependencyList
) > 0:
101 Module
= DependencyList
.pop(0)
104 for Dep
in Module
.Depex
[self
.CurrentArch
, ModuleType
]:
106 DepexList
.append('AND')
107 DepexList
.append('(')
108 DepexList
.extend(Dep
)
109 if DepexList
[-1] == 'END': # no need of a END at this time
111 DepexList
.append(')')
112 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
114 for LibName
in Module
.LibraryClasses
:
115 if LibName
in LibraryInstance
:
117 if PlatformModule
and LibName
in PlatformModule
.LibraryClasses
:
118 LibraryPath
= PlatformModule
.LibraryClasses
[LibName
]
120 LibraryPath
= PlatformDataBase
.LibraryClasses
[LibName
, ModuleType
]
122 LibraryPath
= Module
.LibraryClasses
[LibName
]
125 LibraryModule
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[LibraryPath
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
126 LibraryInstance
[LibName
] = LibraryModule
127 DependencyList
.append(LibraryModule
)
129 Dpx
= DependencyExpression(DepexList
, ModuleType
, True)
130 if len(Dpx
.PostfixNotation
) != 0:
131 # It means this module has DEPEX
132 self
.FinalTargetSuffixMap
['.depex'] = [os
.path
.join(self
.EfiOutputPath
, self
.BaseName
) + '.depex']
133 return self
.FinalTargetSuffixMap
135 ## __InfParse() method
137 # Parse inf file to get module information
139 # @param self The object pointer
140 # @param Dict dictionary contains macro and value pair
142 def __InfParse__(self
, Dict
= {}):
144 GenFdsGlobalVariable
.VerboseLogger( " Begine parsing INf file : %s" %self
.InfFileName
)
146 self
.InfFileName
= self
.InfFileName
.replace('$(WORKSPACE)', '')
147 if self
.InfFileName
[0] == '\\' or self
.InfFileName
[0] == '/' :
148 self
.InfFileName
= self
.InfFileName
[1:]
150 if self
.InfFileName
.find('$') == -1:
151 InfPath
= NormPath(self
.InfFileName
)
152 if not os
.path
.exists(InfPath
):
153 InfPath
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(InfPath
)
154 if not os
.path
.exists(InfPath
):
155 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Non-existant Module %s !" % (self
.InfFileName
))
157 self
.CurrentArch
= self
.GetCurrentArch()
159 # Get the InfClass object
162 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
163 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
165 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
167 if self
.CurrentArch
!= None:
169 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
171 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
173 self
.BaseName
= Inf
.BaseName
174 self
.ModuleGuid
= Inf
.Guid
175 self
.ModuleType
= Inf
.ModuleType
176 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
177 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
178 if Inf
.AutoGenVersion
< 0x00010005:
179 self
.ModuleType
= Inf
.ComponentType
180 self
.VersionString
= Inf
.Version
181 self
.BinFileList
= Inf
.Binaries
182 self
.SourceFileList
= Inf
.Sources
183 if self
.KeepReloc
== None and Inf
.Shadow
:
184 self
.ShadowFromInfFile
= Inf
.Shadow
187 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
188 self
.BaseName
= Inf
.BaseName
189 self
.ModuleGuid
= Inf
.Guid
190 self
.ModuleType
= Inf
.ModuleType
191 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
192 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
193 self
.VersionString
= Inf
.Version
194 self
.BinFileList
= Inf
.Binaries
195 self
.SourceFileList
= Inf
.Sources
196 if self
.BinFileList
== []:
197 EdkLogger
.error("GenFds", GENFDS_ERROR
,
198 "INF %s specified in FDF could not be found in build ARCH %s!" \
199 % (self
.InfFileName
, GenFdsGlobalVariable
.ArchList
))
201 if len(self
.SourceFileList
) != 0 and not self
.InDsc
:
202 EdkLogger
.warn("GenFds", GENFDS_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % (self
.InfFileName
))
204 if self
.ModuleType
== 'SMM_CORE' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
205 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
)
207 if Inf
._Defs
!= None and len(Inf
._Defs
) > 0:
208 self
.OptRomDefs
.update(Inf
._Defs
)
212 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
213 FdfPcdDict
= GenFdsGlobalVariable
.FdfParser
.Profile
.PcdDict
215 # Workaround here: both build and GenFds tool convert the workspace path to lower case
216 # But INF file path in FDF and DSC file may have real case characters.
217 # Try to convert the path to lower case to see if PCDs value are override by DSC.
219 for DscModule
in Platform
.Modules
:
220 DscModules
[str(DscModule
).lower()] = Platform
.Modules
[DscModule
]
221 for PcdKey
in InfPcds
:
222 Pcd
= InfPcds
[PcdKey
]
223 if not hasattr(Pcd
, 'Offset'):
225 if Pcd
.Type
!= 'PatchableInModule':
227 # Override Patchable PCD value by the value from DSC
229 InfLowerPath
= str(PathClassObj
).lower()
230 if InfLowerPath
in DscModules
and PcdKey
in DscModules
[InfLowerPath
].Pcds
:
231 PatchPcd
= DscModules
[InfLowerPath
].Pcds
[PcdKey
]
232 elif PcdKey
in Platform
.Pcds
:
233 PatchPcd
= Platform
.Pcds
[PcdKey
]
235 if PatchPcd
and Pcd
.Type
== PatchPcd
.Type
:
236 DefaultValue
= PatchPcd
.DefaultValue
239 # Override Patchable PCD value by the value from FDF
241 if PcdKey
in FdfPcdDict
:
242 DefaultValue
= FdfPcdDict
[PcdKey
]
245 if not DscOverride
and not FdfOverride
:
247 # Check value, if value are equal, no need to patch
248 if Pcd
.DatumType
== "VOID*":
249 if Pcd
.DefaultValue
== DefaultValue
or DefaultValue
in [None, '']:
251 # Get the string size from FDF or DSC
252 if DefaultValue
[0] == 'L':
253 # Remove L"", but the '\0' must be appended
254 MaxDatumSize
= str((len(DefaultValue
) - 2) * 2)
255 elif DefaultValue
[0] == '{':
256 MaxDatumSize
= str(len(DefaultValue
.split(',')))
258 MaxDatumSize
= str(len(DefaultValue
) - 1)
260 Pcd
.MaxDatumSize
= PatchPcd
.MaxDatumSize
261 # If no defined the maximum size in DSC, try to get current size from INF
262 if Pcd
.MaxDatumSize
in ['', None]:
263 Pcd
.MaxDatumSize
= str(len(Pcd
.DefaultValue
.split(',')))
266 if Pcd
.DefaultValue
.upper().startswith('0X'):
268 if DefaultValue
.upper().startswith('0X'):
271 PcdValueInImg
= int(Pcd
.DefaultValue
, Base1
)
272 PcdValueInDscOrFdf
= int(DefaultValue
, Base2
)
273 if PcdValueInImg
== PcdValueInDscOrFdf
:
277 # Check the Pcd size and data type
278 if Pcd
.DatumType
== "VOID*":
279 if int(MaxDatumSize
) > int(Pcd
.MaxDatumSize
):
280 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
281 % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, int(MaxDatumSize
) - int(Pcd
.MaxDatumSize
)))
283 if PcdValueInDscOrFdf
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
] \
284 or PcdValueInImg
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
]:
285 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of %s type PCD '%s.%s' doesn't match its data type." \
286 % (Pcd
.DatumType
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
287 Pcd
.DefaultValue
= DefaultValue
288 self
.PatchPcds
.append(Pcd
)
290 self
.PcdIsDriver
= Inf
.PcdIsDriver
291 self
.IsBinaryModule
= Inf
.IsBinaryModule
292 GenFdsGlobalVariable
.VerboseLogger("BaseName : %s" % self
.BaseName
)
293 GenFdsGlobalVariable
.VerboseLogger("ModuleGuid : %s" % self
.ModuleGuid
)
294 GenFdsGlobalVariable
.VerboseLogger("ModuleType : %s" % self
.ModuleType
)
295 GenFdsGlobalVariable
.VerboseLogger("VersionString : %s" % self
.VersionString
)
296 GenFdsGlobalVariable
.VerboseLogger("InfFileName :%s" % self
.InfFileName
)
299 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
302 self
.OutputPath
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, \
303 self
.ModuleGuid
+ self
.BaseName
)
304 if not os
.path
.exists(self
.OutputPath
) :
305 os
.makedirs(self
.OutputPath
)
307 self
.EfiOutputPath
= self
.__GetEFIOutPutPath
__()
308 GenFdsGlobalVariable
.VerboseLogger( "ModuelEFIPath: " + self
.EfiOutputPath
)
312 # Patch EFI file with patch PCD
314 # @param EfiFile: EFI file needs to be patched.
315 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
316 # If passed in file does not end with efi, return as is
318 def PatchEfiFile(self
, EfiFile
):
319 if os
.path
.splitext(EfiFile
)[1].lower() != '.efi':
321 if not self
.PatchPcds
:
323 Basename
= os
.path
.basename(EfiFile
)
324 Output
= os
.path
.join(self
.OutputPath
, Basename
)
325 shutil
.copy(EfiFile
, Output
)
326 for Pcd
in self
.PatchPcds
:
327 RetVal
, RetStr
= PatchBinaryFile(Output
, int(Pcd
.Offset
, 0), Pcd
.DatumType
, Pcd
.DefaultValue
, Pcd
.MaxDatumSize
)
329 EdkLogger
.error("GenFds", GENFDS_ERROR
, RetStr
, File
=self
.InfFileName
)
335 # @param self The object pointer
336 # @param Dict dictionary contains macro and value pair
337 # @param FvChildAddr Array of the inside FvImage base address
338 # @param FvParentAddr Parent Fv base address
339 # @retval string Generated FFS file name
341 def GenFfs(self
, Dict
= {}, FvChildAddr
= [], FvParentAddr
=None):
343 # Parse Inf file get Module related information
346 self
.__InfParse
__(Dict
)
349 # Allow binary type module not specify override rule in FDF file.
351 if len(self
.BinFileList
) >0 and not self
.InDsc
:
352 if self
.Rule
== None or self
.Rule
== "":
356 # Get the rule of how to generate Ffs file
358 Rule
= self
.__GetRule
__()
359 GenFdsGlobalVariable
.VerboseLogger( "Packing binaries from inf file : %s" %self
.InfFileName
)
361 # Convert Fv File Type for PI1.1 SMM driver.
363 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
364 if Rule
.FvFileType
== 'DRIVER':
365 Rule
.FvFileType
= 'SMM'
367 # Framework SMM Driver has no SMM FV file type
369 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
370 if Rule
.FvFileType
== 'SMM' or Rule
.FvFileType
== 'SMM_CORE':
371 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File
=self
.InfFileName
)
373 # For the rule only has simpleFile
375 if isinstance (Rule
, RuleSimpleFile
.RuleSimpleFile
) :
376 SectionOutputList
= self
.__GenSimpleFileSection
__(Rule
)
377 FfsOutput
= self
.__GenSimpleFileFfs
__(Rule
, SectionOutputList
)
380 # For Rule has ComplexFile
382 elif isinstance(Rule
, RuleComplexFile
.RuleComplexFile
):
383 InputSectList
, InputSectAlignments
= self
.__GenComplexFileSection
__(Rule
, FvChildAddr
, FvParentAddr
)
384 FfsOutput
= self
.__GenComplexFileFfs
__(Rule
, InputSectList
, InputSectAlignments
)
388 ## __ExtendMacro__() method
390 # Replace macro with its value
392 # @param self The object pointer
393 # @param String The string to be replaced
394 # @retval string Macro replaced string
396 def __ExtendMacro__ (self
, String
):
398 '$(INF_OUTPUT)' : self
.EfiOutputPath
,
399 '$(MODULE_NAME)' : self
.BaseName
,
400 '$(BUILD_NUMBER)': self
.BuildNum
,
401 '$(INF_VERSION)' : self
.VersionString
,
402 '$(NAMED_GUID)' : self
.ModuleGuid
404 String
= GenFdsGlobalVariable
.MacroExtend(String
, MacroDict
)
407 ## __GetRule__() method
409 # Get correct rule for generating FFS for this INF
411 # @param self The object pointer
412 # @retval Rule Rule object
414 def __GetRule__ (self
) :
416 if self
.CurrentArch
== None:
417 CurrentArchList
= ['common']
419 CurrentArchList
.append(self
.CurrentArch
)
421 for CurrentArch
in CurrentArchList
:
422 RuleName
= 'RULE' + \
424 CurrentArch
.upper() + \
426 self
.ModuleType
.upper()
427 if self
.Rule
!= None:
428 RuleName
= RuleName
+ \
432 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
434 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
437 RuleName
= 'RULE' + \
441 self
.ModuleType
.upper()
443 if self
.Rule
!= None:
444 RuleName
= RuleName
+ \
448 GenFdsGlobalVariable
.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName
, self
.InfFileName
))
450 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
452 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
456 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'Don\'t Find common rule %s for INF %s' \
457 % (RuleName
, self
.InfFileName
))
459 ## __GetPlatformArchList__() method
461 # Get Arch list this INF built under
463 # @param self The object pointer
464 # @retval list Arch list
466 def __GetPlatformArchList__(self
):
468 InfFileKey
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
))
470 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IA32', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
471 if PlatformDataBase
!= None:
472 if InfFileKey
in PlatformDataBase
.Modules
:
473 DscArchList
.append ('IA32')
475 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'X64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
476 if PlatformDataBase
!= None:
477 if InfFileKey
in PlatformDataBase
.Modules
:
478 DscArchList
.append ('X64')
480 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IPF', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
481 if PlatformDataBase
!= None:
482 if InfFileKey
in (PlatformDataBase
.Modules
):
483 DscArchList
.append ('IPF')
485 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'ARM', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
486 if PlatformDataBase
!= None:
487 if InfFileKey
in (PlatformDataBase
.Modules
):
488 DscArchList
.append ('ARM')
490 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'EBC', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
491 if PlatformDataBase
!= None:
492 if InfFileKey
in (PlatformDataBase
.Modules
):
493 DscArchList
.append ('EBC')
495 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'AARCH64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
496 if PlatformDataBase
!= None:
497 if InfFileKey
in (PlatformDataBase
.Modules
):
498 DscArchList
.append ('AARCH64')
502 ## GetCurrentArch() method
504 # Get Arch list of the module from this INF is to be placed into flash
506 # @param self The object pointer
507 # @retval list Arch list
509 def GetCurrentArch(self
) :
511 TargetArchList
= GenFdsGlobalVariable
.ArchList
513 PlatformArchList
= self
.__GetPlatformArchList
__()
515 CurArchList
= TargetArchList
516 if PlatformArchList
!= []:
517 CurArchList
= list(set (TargetArchList
) & set (PlatformArchList
))
518 GenFdsGlobalVariable
.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList
))
521 if self
.KeyStringList
!= []:
522 for Key
in self
.KeyStringList
:
523 Key
= GenFdsGlobalVariable
.MacroExtend(Key
)
524 Target
, Tag
, Arch
= Key
.split('_')
525 if Arch
in CurArchList
:
526 ArchList
.append(Arch
)
527 if Target
not in self
.TargetOverrideList
:
528 self
.TargetOverrideList
.append(Target
)
530 ArchList
= CurArchList
532 UseArchList
= TargetArchList
533 if self
.UseArch
!= None:
535 UseArchList
.append(self
.UseArch
)
536 ArchList
= list(set (UseArchList
) & set (ArchList
))
538 self
.InfFileName
= NormPath(self
.InfFileName
)
539 if len(PlatformArchList
) == 0:
541 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
542 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
544 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
545 if len(ArchList
) == 1:
548 elif len(ArchList
) > 1:
549 if len(PlatformArchList
) == 0:
550 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
))
552 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
))
554 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." \
555 % (self
.InfFileName
, str(PlatformArchList
), GenFdsGlobalVariable
.ActivePlatform
, str(set (UseArchList
) & set (TargetArchList
))))
557 ## __GetEFIOutPutPath__() method
559 # Get the output path for generated files
561 # @param self The object pointer
562 # @retval string Path that output files from this INF go to
564 def __GetEFIOutPutPath__(self
):
567 (ModulePath
, FileName
) = os
.path
.split(self
.InfFileName
)
568 Index
= FileName
.rfind('.')
569 FileName
= FileName
[0:Index
]
571 if self
.CurrentArch
!= None:
572 Arch
= self
.CurrentArch
574 OutputPath
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
],
580 OutputPath
= os
.path
.realpath(OutputPath
)
583 ## __GenSimpleFileSection__() method
585 # Generate section by specified file name or a list of files with file extension
587 # @param self The object pointer
588 # @param Rule The rule object used to generate section
589 # @retval string File name of the generated section file
591 def __GenSimpleFileSection__(self
, Rule
):
593 # Prepare the parameter of GenSection
597 GenSecInputFile
= None
598 if Rule
.FileName
!= None:
599 GenSecInputFile
= self
.__ExtendMacro
__(Rule
.FileName
)
600 if os
.path
.isabs(GenSecInputFile
):
601 GenSecInputFile
= os
.path
.normpath(GenSecInputFile
)
603 GenSecInputFile
= os
.path
.normpath(os
.path
.join(self
.EfiOutputPath
, GenSecInputFile
))
605 FileList
, IsSect
= Section
.Section
.GetFileList(self
, '', Rule
.FileExtension
)
608 SectionType
= Rule
.SectionType
610 # Convert Fv Section Type for PI1.1 SMM driver.
612 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
613 if SectionType
== 'DXE_DEPEX':
614 SectionType
= 'SMM_DEPEX'
616 # Framework SMM Driver has no SMM_DEPEX section type
618 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
619 if SectionType
== 'SMM_DEPEX':
620 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
622 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
623 if self
.KeepReloc
!= None:
624 NoStrip
= self
.KeepReloc
625 elif Rule
.KeepReloc
!= None:
626 NoStrip
= Rule
.KeepReloc
627 elif self
.ShadowFromInfFile
!= None:
628 NoStrip
= self
.ShadowFromInfFile
631 for File
in FileList
:
634 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
635 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
637 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
638 File
= GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)
640 #Get PE Section alignment when align is set to AUTO
641 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
642 ImageObj
= PeImageClass (File
)
643 if ImageObj
.SectionAlignment
< 0x400:
644 self
.Alignment
= str (ImageObj
.SectionAlignment
)
646 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
649 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
650 if not os
.path
.exists(FileBeforeStrip
) or \
651 (os
.path
.getmtime(File
) > os
.path
.getmtime(FileBeforeStrip
)):
652 shutil
.copyfile(File
, FileBeforeStrip
)
653 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
654 GenFdsGlobalVariable
.GenerateFirmwareImage(
661 if SectionType
== 'TE':
662 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
663 GenFdsGlobalVariable
.GenerateFirmwareImage(
670 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [File
], Section
.Section
.SectionType
[SectionType
])
671 OutputFileList
.append(OutputFile
)
674 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
675 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
676 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
677 GenSecInputFile
= GenFdsGlobalVariable
.MacroExtend(GenSecInputFile
, Dict
, self
.CurrentArch
)
679 #Get PE Section alignment when align is set to AUTO
680 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
681 ImageObj
= PeImageClass (GenSecInputFile
)
682 if ImageObj
.SectionAlignment
< 0x400:
683 self
.Alignment
= str (ImageObj
.SectionAlignment
)
685 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
688 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
689 if not os
.path
.exists(FileBeforeStrip
) or \
690 (os
.path
.getmtime(GenSecInputFile
) > os
.path
.getmtime(FileBeforeStrip
)):
691 shutil
.copyfile(GenSecInputFile
, FileBeforeStrip
)
692 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
693 GenFdsGlobalVariable
.GenerateFirmwareImage(
698 GenSecInputFile
= StrippedFile
700 if SectionType
== 'TE':
701 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
702 GenFdsGlobalVariable
.GenerateFirmwareImage(
707 GenSecInputFile
= TeFile
709 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [GenSecInputFile
], Section
.Section
.SectionType
[SectionType
])
710 OutputFileList
.append(OutputFile
)
712 return OutputFileList
714 ## __GenSimpleFileFfs__() method
718 # @param self The object pointer
719 # @param Rule The rule object used to generate section
720 # @param InputFileList The output file list from GenSection
721 # @retval string Generated FFS file name
723 def __GenSimpleFileFfs__(self
, Rule
, InputFileList
):
724 FfsOutput
= self
.OutputPath
+ \
726 self
.__ExtendMacro
__(Rule
.NameGuid
) + \
729 GenFdsGlobalVariable
.VerboseLogger(self
.__ExtendMacro
__(Rule
.NameGuid
))
731 SectionAlignments
= []
732 for InputFile
in InputFileList
:
733 InputSection
.append(InputFile
)
734 SectionAlignments
.append(Rule
.SectAlignment
)
736 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
737 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
738 if len(PcdValue
) == 0:
739 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
741 if PcdValue
.startswith('{'):
742 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
743 RegistryGuidStr
= PcdValue
744 if len(RegistryGuidStr
) == 0:
745 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
747 self
.ModuleGuid
= RegistryGuidStr
749 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputSection
,
750 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
751 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
752 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
753 SectionAlign
=SectionAlignments
757 ## __GenComplexFileSection__() method
759 # Generate section by sections in Rule
761 # @param self The object pointer
762 # @param Rule The rule object used to generate section
763 # @param FvChildAddr Array of the inside FvImage base address
764 # @param FvParentAddr Parent Fv base address
765 # @retval string File name of the generated section file
767 def __GenComplexFileSection__(self
, Rule
, FvChildAddr
, FvParentAddr
):
768 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
769 if Rule
.KeepReloc
!= None:
770 self
.KeepRelocFromRule
= Rule
.KeepReloc
774 HasGneratedFlag
= False
775 if self
.PcdIsDriver
== 'PEI_PCD_DRIVER':
776 if self
.IsBinaryModule
:
777 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "PEIPcdDataBase.raw")
779 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "PEIPcdDataBase.raw")
780 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "PEIPcdDataBaseSec.raw")
781 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
785 SectFiles
.append(PcdExDbSecName
)
786 SectAlignments
.append(None)
787 elif self
.PcdIsDriver
== 'DXE_PCD_DRIVER':
788 if self
.IsBinaryModule
:
789 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "DXEPcdDataBase.raw")
791 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "DXEPcdDataBase.raw")
792 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "DXEPcdDataBaseSec.raw")
793 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
797 SectFiles
.append(PcdExDbSecName
)
798 SectAlignments
.append(None)
799 for Sect
in Rule
.SectionList
:
800 SecIndex
= '%d' %Index
803 # Convert Fv Section Type for PI1.1 SMM driver.
805 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
806 if Sect
.SectionType
== 'DXE_DEPEX':
807 Sect
.SectionType
= 'SMM_DEPEX'
809 # Framework SMM Driver has no SMM_DEPEX section type
811 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
812 if Sect
.SectionType
== 'SMM_DEPEX':
813 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
815 # process the inside FvImage from FvSection or GuidSection
817 if FvChildAddr
!= []:
818 if isinstance(Sect
, FvImageSection
):
819 Sect
.FvAddr
= FvChildAddr
.pop(0)
820 elif isinstance(Sect
, GuidSection
):
821 Sect
.FvAddr
= FvChildAddr
822 if FvParentAddr
!= None and isinstance(Sect
, GuidSection
):
823 Sect
.FvParentAddr
= FvParentAddr
825 if Rule
.KeyStringList
!= []:
826 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, Rule
.KeyStringList
, self
)
828 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, self
.KeyStringList
, self
)
830 if not HasGneratedFlag
:
831 UniVfrOffsetFileSection
= ""
832 ModuleFileName
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
)
833 InfData
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClass(ModuleFileName
), self
.CurrentArch
]
835 # Search the source list in InfData to find if there are .vfr file exist.
838 VfrUniOffsetList
= []
839 for SourceFile
in InfData
.Sources
:
840 if SourceFile
.Type
.upper() == ".VFR" :
842 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
844 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
845 if SourceFile
.Type
.upper() == ".UNI" :
847 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
849 VfrUniBaseName
["UniOffsetName"] = (self
.BaseName
+ "Strings")
852 if len(VfrUniBaseName
) > 0:
853 VfrUniOffsetList
= self
.__GetBuildOutputMapFileVfrUniInfo
(VfrUniBaseName
)
855 # Generate the Raw data of raw section
857 os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
858 UniVfrOffsetFileName
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
859 UniVfrOffsetFileSection
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ 'Offset' + '.raw')
861 self
.__GenUniVfrOffsetFile
(VfrUniOffsetList
, UniVfrOffsetFileName
)
863 UniVfrOffsetFileNameList
= []
864 UniVfrOffsetFileNameList
.append(UniVfrOffsetFileName
)
865 """Call GenSection"""
866 GenFdsGlobalVariable
.GenerateSection(UniVfrOffsetFileSection
,
867 UniVfrOffsetFileNameList
,
870 os
.remove(UniVfrOffsetFileName
)
871 SectList
.append(UniVfrOffsetFileSection
)
872 HasGneratedFlag
= True
874 for SecName
in SectList
:
875 SectFiles
.append(SecName
)
876 SectAlignments
.append(Align
)
878 return SectFiles
, SectAlignments
880 ## __GenComplexFileFfs__() method
884 # @param self The object pointer
885 # @param Rule The rule object used to generate section
886 # @param InputFileList The output file list from GenSection
887 # @retval string Generated FFS file name
889 def __GenComplexFileFfs__(self
, Rule
, InputFile
, Alignments
):
891 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
892 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
893 if len(PcdValue
) == 0:
894 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
896 if PcdValue
.startswith('{'):
897 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
898 RegistryGuidStr
= PcdValue
899 if len(RegistryGuidStr
) == 0:
900 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
902 self
.ModuleGuid
= RegistryGuidStr
904 FfsOutput
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
905 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputFile
,
906 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
907 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
908 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
909 SectionAlign
=Alignments
913 ## __GetGenFfsCmdParameter__() method
915 # Create parameter string for GenFfs
917 # @param self The object pointer
918 # @param Rule The rule object used to generate section
919 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
921 def __GetGenFfsCmdParameter__(self
, Rule
):
923 result
+= ('-t', Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
])
924 if Rule
.Fixed
!= False:
926 if Rule
.CheckSum
!= False:
929 if Rule
.Alignment
!= None and Rule
.Alignment
!= '':
930 result
+= ('-a', Rule
.Alignment
)
934 ## __GetBuildOutputMapFileVfrUniInfo() method
936 # Find the offset of UNI/INF object offset in the EFI image file.
938 # @param self The object pointer
939 # @param VfrUniBaseName A name list contain the UNI/INF object name.
940 # @retval RetValue A list contain offset of UNI/INF object.
942 def __GetBuildOutputMapFileVfrUniInfo(self
, VfrUniBaseName
):
946 MapFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".map")
948 fInputfile
= open(MapFileName
, "r", 0)
950 FileLinesList
= fInputfile
.readlines()
952 EdkLogger
.error("GenFds", FILE_READ_FAILURE
, "File read failed for %s" %MapFileName
,None)
956 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %MapFileName
,None)
959 for eachLine
in FileLinesList
:
960 for eachName
in VfrUniBaseName
.values():
961 if eachLine
.find(eachName
) != -1:
962 eachLine
= eachLine
.strip()
963 Element
= eachLine
.split()
965 # MSFT/ICC/EBC map file
967 if (len(Element
) == 4):
975 RetValue
.append((eachName
, Element
[2]))
980 elif (len(Element
) == 2) and Element
[0].startswith("0x"):
981 RetValue
.append((eachName
, Element
[0]))
985 ## __GenUniVfrOffsetFile() method
987 # Generate the offset file for the module which contain VFR or UNI file.
989 # @param self The object pointer
990 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
991 # @param UniVfrOffsetFileName The output offset file name.
993 def __GenUniVfrOffsetFile(self
, VfrUniOffsetList
, UniVfrOffsetFileName
):
996 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
998 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %UniVfrOffsetFileName
,None)
1000 # Use a instance of StringIO to cache data
1001 fStringIO
= StringIO
.StringIO('')
1003 for Item
in VfrUniOffsetList
:
1004 if (Item
[0].find("Strings") != -1):
1006 # UNI offset in image.
1008 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1010 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
1011 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
1012 fStringIO
.write(''.join(UniGuid
))
1013 UniValue
= pack ('Q', int (Item
[1], 16))
1014 fStringIO
.write (UniValue
)
1017 # VFR binary offset in image.
1019 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1021 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
1022 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
1023 fStringIO
.write(''.join(VfrGuid
))
1025 VfrValue
= pack ('Q', int (Item
[1], 16))
1026 fStringIO
.write (VfrValue
)
1029 # write data into file.
1032 fInputfile
.write (fStringIO
.getvalue())
1034 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)