2 # process FFS generation from INF statement
4 # Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2014 Hewlett-Packard Development Company, L.P.<BR>
7 # This program and the accompanying materials
8 # are licensed and made available under the terms and conditions of the BSD License
9 # which accompanies this distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 import Common
.LongFilePathOs
as os
23 from GenFdsGlobalVariable
import GenFdsGlobalVariable
29 import RuleComplexFile
30 from CommonDataClass
.FdfClass
import FfsInfStatementClassObject
31 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
32 from Common
.String
import *
33 from Common
.Misc
import PathClass
34 from Common
.Misc
import GuidStructureByteArrayToGuidString
35 from Common
.Misc
import ProcessDuplicatedInf
36 from Common
.Misc
import GetVariableOffset
37 from Common
import EdkLogger
38 from Common
.BuildToolError
import *
39 from GuidSection
import GuidSection
40 from FvImageSection
import FvImageSection
41 from Common
.Misc
import PeImageClass
42 from AutoGen
.GenDepex
import DependencyExpression
43 from PatchPcdValue
.PatchPcdValue
import PatchBinaryFile
44 from Common
.LongFilePathSupport
import CopyLongFilePath
45 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
47 ## generate FFS from INF
50 class FfsInfStatement(FfsInfStatementClassObject
):
51 ## The mapping dictionary from datum type to its maximum number.
52 _MAX_SIZE_TYPE
= {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}
55 # @param self The object pointer
58 FfsInfStatementClassObject
.__init
__(self
)
59 self
.TargetOverrideList
= []
60 self
.ShadowFromInfFile
= None
61 self
.KeepRelocFromRule
= None
64 self
.PiSpecVersion
= '0x00000000'
66 self
.FinalTargetSuffixMap
= {}
67 self
.CurrentLineNum
= None
68 self
.CurrentLineContent
= None
70 self
.InfFileName
= None
71 self
.OverrideGuid
= None
72 self
.PatchedBinFile
= ''
75 ## GetFinalTargetSuffixMap() method
77 # Get final build target list
78 def GetFinalTargetSuffixMap(self
):
79 if not self
.InfModule
or not self
.CurrentArch
:
81 if not self
.FinalTargetSuffixMap
:
82 FinalBuildTargetList
= GenFdsGlobalVariable
.GetModuleCodaTargetList(self
.InfModule
, self
.CurrentArch
)
83 for File
in FinalBuildTargetList
:
84 self
.FinalTargetSuffixMap
.setdefault(os
.path
.splitext(File
)[1], []).append(File
)
86 # Check if current INF module has DEPEX
87 if '.depex' not in self
.FinalTargetSuffixMap
and self
.InfModule
.ModuleType
!= "USER_DEFINED" \
88 and not self
.InfModule
.DxsFile
and not self
.InfModule
.LibraryClass
:
89 ModuleType
= self
.InfModule
.ModuleType
90 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
92 if ModuleType
!= DataType
.SUP_MODULE_USER_DEFINED
:
93 for LibraryClass
in PlatformDataBase
.LibraryClasses
.GetKeys():
94 if LibraryClass
.startswith("NULL") and PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]:
95 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]
97 StrModule
= str(self
.InfModule
)
99 if StrModule
in PlatformDataBase
.Modules
:
100 PlatformModule
= PlatformDataBase
.Modules
[StrModule
]
101 for LibraryClass
in PlatformModule
.LibraryClasses
:
102 if LibraryClass
.startswith("NULL"):
103 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
105 DependencyList
= [self
.InfModule
]
108 while len(DependencyList
) > 0:
109 Module
= DependencyList
.pop(0)
112 for Dep
in Module
.Depex
[self
.CurrentArch
, ModuleType
]:
114 DepexList
.append('AND')
115 DepexList
.append('(')
116 DepexList
.extend(Dep
)
117 if DepexList
[-1] == 'END': # no need of a END at this time
119 DepexList
.append(')')
120 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
122 for LibName
in Module
.LibraryClasses
:
123 if LibName
in LibraryInstance
:
125 if PlatformModule
and LibName
in PlatformModule
.LibraryClasses
:
126 LibraryPath
= PlatformModule
.LibraryClasses
[LibName
]
128 LibraryPath
= PlatformDataBase
.LibraryClasses
[LibName
, ModuleType
]
130 LibraryPath
= Module
.LibraryClasses
[LibName
]
133 LibraryModule
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[LibraryPath
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
134 LibraryInstance
[LibName
] = LibraryModule
135 DependencyList
.append(LibraryModule
)
137 Dpx
= DependencyExpression(DepexList
, ModuleType
, True)
138 if len(Dpx
.PostfixNotation
) != 0:
139 # It means this module has DEPEX
140 self
.FinalTargetSuffixMap
['.depex'] = [os
.path
.join(self
.EfiOutputPath
, self
.BaseName
) + '.depex']
141 return self
.FinalTargetSuffixMap
143 ## __InfParse() method
145 # Parse inf file to get module information
147 # @param self The object pointer
148 # @param Dict dictionary contains macro and value pair
150 def __InfParse__(self
, Dict
= {}):
152 GenFdsGlobalVariable
.VerboseLogger( " Begine parsing INf file : %s" %self
.InfFileName
)
154 self
.InfFileName
= self
.InfFileName
.replace('$(WORKSPACE)', '')
155 if len(self
.InfFileName
) > 1 and self
.InfFileName
[0] == '\\' and self
.InfFileName
[1] == '\\':
157 elif self
.InfFileName
[0] == '\\' or self
.InfFileName
[0] == '/' :
158 self
.InfFileName
= self
.InfFileName
[1:]
160 if self
.InfFileName
.find('$') == -1:
161 InfPath
= NormPath(self
.InfFileName
)
162 if not os
.path
.exists(InfPath
):
163 InfPath
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(InfPath
)
164 if not os
.path
.exists(InfPath
):
165 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Non-existant Module %s !" % (self
.InfFileName
))
167 self
.CurrentArch
= self
.GetCurrentArch()
169 # Get the InfClass object
172 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
173 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
175 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
177 if self
.OverrideGuid
:
178 PathClassObj
= ProcessDuplicatedInf(PathClassObj
, self
.OverrideGuid
, GenFdsGlobalVariable
.WorkSpaceDir
)
179 if self
.CurrentArch
!= None:
181 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
183 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
185 self
.BaseName
= Inf
.BaseName
186 self
.ModuleGuid
= Inf
.Guid
187 self
.ModuleType
= Inf
.ModuleType
188 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
189 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
190 if Inf
.AutoGenVersion
< 0x00010005:
191 self
.ModuleType
= Inf
.ComponentType
192 self
.VersionString
= Inf
.Version
193 self
.BinFileList
= Inf
.Binaries
194 self
.SourceFileList
= Inf
.Sources
195 if self
.KeepReloc
== None and Inf
.Shadow
:
196 self
.ShadowFromInfFile
= Inf
.Shadow
199 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
200 self
.BaseName
= Inf
.BaseName
201 self
.ModuleGuid
= Inf
.Guid
202 self
.ModuleType
= Inf
.ModuleType
203 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
204 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
205 self
.VersionString
= Inf
.Version
206 self
.BinFileList
= Inf
.Binaries
207 self
.SourceFileList
= Inf
.Sources
208 if self
.BinFileList
== []:
209 EdkLogger
.error("GenFds", GENFDS_ERROR
,
210 "INF %s specified in FDF could not be found in build ARCH %s!" \
211 % (self
.InfFileName
, GenFdsGlobalVariable
.ArchList
))
213 if self
.OverrideGuid
:
214 self
.ModuleGuid
= self
.OverrideGuid
216 if len(self
.SourceFileList
) != 0 and not self
.InDsc
:
217 EdkLogger
.warn("GenFds", GENFDS_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % (self
.InfFileName
))
219 if self
.ModuleType
== 'SMM_CORE' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
220 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
)
222 if Inf
._Defs
!= None and len(Inf
._Defs
) > 0:
223 self
.OptRomDefs
.update(Inf
._Defs
)
227 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
228 FdfPcdDict
= GenFdsGlobalVariable
.FdfParser
.Profile
.PcdDict
230 # Workaround here: both build and GenFds tool convert the workspace path to lower case
231 # But INF file path in FDF and DSC file may have real case characters.
232 # Try to convert the path to lower case to see if PCDs value are override by DSC.
234 for DscModule
in Platform
.Modules
:
235 DscModules
[str(DscModule
).lower()] = Platform
.Modules
[DscModule
]
236 for PcdKey
in InfPcds
:
237 Pcd
= InfPcds
[PcdKey
]
238 if not hasattr(Pcd
, 'Offset'):
240 if Pcd
.Type
!= 'PatchableInModule':
242 # Override Patchable PCD value by the value from DSC
244 InfLowerPath
= str(PathClassObj
).lower()
245 if InfLowerPath
in DscModules
and PcdKey
in DscModules
[InfLowerPath
].Pcds
:
246 PatchPcd
= DscModules
[InfLowerPath
].Pcds
[PcdKey
]
247 elif PcdKey
in Platform
.Pcds
:
248 PatchPcd
= Platform
.Pcds
[PcdKey
]
250 if PatchPcd
and Pcd
.Type
== PatchPcd
.Type
:
251 DefaultValue
= PatchPcd
.DefaultValue
254 # Override Patchable PCD value by the value from FDF
256 if PcdKey
in FdfPcdDict
:
257 DefaultValue
= FdfPcdDict
[PcdKey
]
260 if not DscOverride
and not FdfOverride
:
262 # Check value, if value are equal, no need to patch
263 if Pcd
.DatumType
== "VOID*":
264 if Pcd
.DefaultValue
== DefaultValue
or DefaultValue
in [None, '']:
266 # Get the string size from FDF or DSC
267 if DefaultValue
[0] == 'L':
268 # Remove L"", but the '\0' must be appended
269 MaxDatumSize
= str((len(DefaultValue
) - 2) * 2)
270 elif DefaultValue
[0] == '{':
271 MaxDatumSize
= str(len(DefaultValue
.split(',')))
273 MaxDatumSize
= str(len(DefaultValue
) - 1)
275 Pcd
.MaxDatumSize
= PatchPcd
.MaxDatumSize
276 # If no defined the maximum size in DSC, try to get current size from INF
277 if Pcd
.MaxDatumSize
in ['', None]:
278 Pcd
.MaxDatumSize
= str(len(Pcd
.DefaultValue
.split(',')))
281 if Pcd
.DefaultValue
.upper().startswith('0X'):
283 if DefaultValue
.upper().startswith('0X'):
286 PcdValueInImg
= int(Pcd
.DefaultValue
, Base1
)
287 PcdValueInDscOrFdf
= int(DefaultValue
, Base2
)
288 if PcdValueInImg
== PcdValueInDscOrFdf
:
292 # Check the Pcd size and data type
293 if Pcd
.DatumType
== "VOID*":
294 if int(MaxDatumSize
) > int(Pcd
.MaxDatumSize
):
295 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
296 % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, int(MaxDatumSize
) - int(Pcd
.MaxDatumSize
)))
298 if PcdValueInDscOrFdf
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
] \
299 or PcdValueInImg
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
]:
300 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of %s type PCD '%s.%s' doesn't match its data type." \
301 % (Pcd
.DatumType
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
302 self
.PatchPcds
.append((Pcd
, DefaultValue
))
305 self
.PcdIsDriver
= Inf
.PcdIsDriver
306 self
.IsBinaryModule
= Inf
.IsBinaryModule
307 GenFdsGlobalVariable
.VerboseLogger("BaseName : %s" % self
.BaseName
)
308 GenFdsGlobalVariable
.VerboseLogger("ModuleGuid : %s" % self
.ModuleGuid
)
309 GenFdsGlobalVariable
.VerboseLogger("ModuleType : %s" % self
.ModuleType
)
310 GenFdsGlobalVariable
.VerboseLogger("VersionString : %s" % self
.VersionString
)
311 GenFdsGlobalVariable
.VerboseLogger("InfFileName :%s" % self
.InfFileName
)
314 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
317 self
.OutputPath
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, \
318 self
.ModuleGuid
+ self
.BaseName
)
319 if not os
.path
.exists(self
.OutputPath
) :
320 os
.makedirs(self
.OutputPath
)
322 self
.EfiOutputPath
= self
.__GetEFIOutPutPath
__()
323 GenFdsGlobalVariable
.VerboseLogger( "ModuelEFIPath: " + self
.EfiOutputPath
)
327 # Patch EFI file with patch PCD
329 # @param EfiFile: EFI file needs to be patched.
330 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
331 # If passed in file does not end with efi, return as is
333 def PatchEfiFile(self
, EfiFile
, FileType
):
334 if not self
.PatchPcds
:
336 if FileType
!= 'PE32' and self
.ModuleType
!= "USER_DEFINED":
338 if self
.PatchedBinFile
:
339 EdkLogger
.error("GenFds", GENFDS_ERROR
,
340 'Only one binary file can be patched:\n'
341 ' a binary file has been patched: %s\n'
342 ' current file: %s' % (self
.PatchedBinFile
, EfiFile
),
343 File
=self
.InfFileName
)
344 Basename
= os
.path
.basename(EfiFile
)
345 Output
= os
.path
.join(self
.OutputPath
, Basename
)
346 CopyLongFilePath(EfiFile
, Output
)
347 for Pcd
, Value
in self
.PatchPcds
:
348 RetVal
, RetStr
= PatchBinaryFile(Output
, int(Pcd
.Offset
, 0), Pcd
.DatumType
, Value
, Pcd
.MaxDatumSize
)
350 EdkLogger
.error("GenFds", GENFDS_ERROR
, RetStr
, File
=self
.InfFileName
)
351 self
.PatchedBinFile
= os
.path
.normpath(EfiFile
)
357 # @param self The object pointer
358 # @param Dict dictionary contains macro and value pair
359 # @param FvChildAddr Array of the inside FvImage base address
360 # @param FvParentAddr Parent Fv base address
361 # @retval string Generated FFS file name
363 def GenFfs(self
, Dict
= {}, FvChildAddr
= [], FvParentAddr
=None):
365 # Parse Inf file get Module related information
368 self
.__InfParse
__(Dict
)
369 SrcFile
= mws
.join( GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
);
370 DestFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
373 SrcPath
= os
.path
.dirname(SrcFile
)
374 SrcFileName
= os
.path
.basename(SrcFile
)
375 SrcFileBase
, SrcFileExt
= os
.path
.splitext(SrcFileName
)
376 DestPath
= os
.path
.dirname(DestFile
)
377 DestFileName
= os
.path
.basename(DestFile
)
378 DestFileBase
, DestFileExt
= os
.path
.splitext(DestFileName
)
382 "${s_path}" : SrcPath
,
383 "${s_dir}" : SrcFileDir
,
384 "${s_name}" : SrcFileName
,
385 "${s_base}" : SrcFileBase
,
386 "${s_ext}" : SrcFileExt
,
389 "${d_path}" : DestPath
,
390 "${d_name}" : DestFileName
,
391 "${d_base}" : DestFileBase
,
392 "${d_ext}" : DestFileExt
395 # Allow binary type module not specify override rule in FDF file.
397 if len(self
.BinFileList
) > 0:
398 if self
.Rule
== None or self
.Rule
== "":
402 # Get the rule of how to generate Ffs file
404 Rule
= self
.__GetRule
__()
405 GenFdsGlobalVariable
.VerboseLogger( "Packing binaries from inf file : %s" %self
.InfFileName
)
407 # Convert Fv File Type for PI1.1 SMM driver.
409 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
410 if Rule
.FvFileType
== 'DRIVER':
411 Rule
.FvFileType
= 'SMM'
413 # Framework SMM Driver has no SMM FV file type
415 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
416 if Rule
.FvFileType
== 'SMM' or Rule
.FvFileType
== 'SMM_CORE':
417 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File
=self
.InfFileName
)
419 # For the rule only has simpleFile
421 if isinstance (Rule
, RuleSimpleFile
.RuleSimpleFile
) :
422 SectionOutputList
= self
.__GenSimpleFileSection
__(Rule
)
423 FfsOutput
= self
.__GenSimpleFileFfs
__(Rule
, SectionOutputList
)
426 # For Rule has ComplexFile
428 elif isinstance(Rule
, RuleComplexFile
.RuleComplexFile
):
429 InputSectList
, InputSectAlignments
= self
.__GenComplexFileSection
__(Rule
, FvChildAddr
, FvParentAddr
)
430 FfsOutput
= self
.__GenComplexFileFfs
__(Rule
, InputSectList
, InputSectAlignments
)
434 ## __ExtendMacro__() method
436 # Replace macro with its value
438 # @param self The object pointer
439 # @param String The string to be replaced
440 # @retval string Macro replaced string
442 def __ExtendMacro__ (self
, String
):
444 '$(INF_OUTPUT)' : self
.EfiOutputPath
,
445 '$(MODULE_NAME)' : self
.BaseName
,
446 '$(BUILD_NUMBER)': self
.BuildNum
,
447 '$(INF_VERSION)' : self
.VersionString
,
448 '$(NAMED_GUID)' : self
.ModuleGuid
450 String
= GenFdsGlobalVariable
.MacroExtend(String
, MacroDict
)
451 String
= GenFdsGlobalVariable
.MacroExtend(String
, self
.MacroDict
)
454 ## __GetRule__() method
456 # Get correct rule for generating FFS for this INF
458 # @param self The object pointer
459 # @retval Rule Rule object
461 def __GetRule__ (self
) :
463 if self
.CurrentArch
== None:
464 CurrentArchList
= ['common']
466 CurrentArchList
.append(self
.CurrentArch
)
468 for CurrentArch
in CurrentArchList
:
469 RuleName
= 'RULE' + \
471 CurrentArch
.upper() + \
473 self
.ModuleType
.upper()
474 if self
.Rule
!= None:
475 RuleName
= RuleName
+ \
479 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
481 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
484 RuleName
= 'RULE' + \
488 self
.ModuleType
.upper()
490 if self
.Rule
!= None:
491 RuleName
= RuleName
+ \
495 GenFdsGlobalVariable
.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName
, self
.InfFileName
))
497 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
499 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
503 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'Don\'t Find common rule %s for INF %s' \
504 % (RuleName
, self
.InfFileName
))
506 ## __GetPlatformArchList__() method
508 # Get Arch list this INF built under
510 # @param self The object pointer
511 # @retval list Arch list
513 def __GetPlatformArchList__(self
):
515 InfFileKey
= os
.path
.normpath(mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
))
517 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IA32', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
518 if PlatformDataBase
!= None:
519 if InfFileKey
in PlatformDataBase
.Modules
:
520 DscArchList
.append ('IA32')
522 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'X64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
523 if PlatformDataBase
!= None:
524 if InfFileKey
in PlatformDataBase
.Modules
:
525 DscArchList
.append ('X64')
527 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IPF', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
528 if PlatformDataBase
!= None:
529 if InfFileKey
in (PlatformDataBase
.Modules
):
530 DscArchList
.append ('IPF')
532 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'ARM', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
533 if PlatformDataBase
!= None:
534 if InfFileKey
in (PlatformDataBase
.Modules
):
535 DscArchList
.append ('ARM')
537 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'EBC', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
538 if PlatformDataBase
!= None:
539 if InfFileKey
in (PlatformDataBase
.Modules
):
540 DscArchList
.append ('EBC')
542 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'AARCH64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
543 if PlatformDataBase
!= None:
544 if InfFileKey
in (PlatformDataBase
.Modules
):
545 DscArchList
.append ('AARCH64')
549 ## GetCurrentArch() method
551 # Get Arch list of the module from this INF is to be placed into flash
553 # @param self The object pointer
554 # @retval list Arch list
556 def GetCurrentArch(self
) :
558 TargetArchList
= GenFdsGlobalVariable
.ArchList
560 PlatformArchList
= self
.__GetPlatformArchList
__()
562 CurArchList
= TargetArchList
563 if PlatformArchList
!= []:
564 CurArchList
= list(set (TargetArchList
) & set (PlatformArchList
))
565 GenFdsGlobalVariable
.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList
))
568 if self
.KeyStringList
!= []:
569 for Key
in self
.KeyStringList
:
570 Key
= GenFdsGlobalVariable
.MacroExtend(Key
)
571 Target
, Tag
, Arch
= Key
.split('_')
572 if Arch
in CurArchList
:
573 ArchList
.append(Arch
)
574 if Target
not in self
.TargetOverrideList
:
575 self
.TargetOverrideList
.append(Target
)
577 ArchList
= CurArchList
579 UseArchList
= TargetArchList
580 if self
.UseArch
!= None:
582 UseArchList
.append(self
.UseArch
)
583 ArchList
= list(set (UseArchList
) & set (ArchList
))
585 self
.InfFileName
= NormPath(self
.InfFileName
)
586 if len(PlatformArchList
) == 0:
588 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
589 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
591 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
592 if len(ArchList
) == 1:
595 elif len(ArchList
) > 1:
596 if len(PlatformArchList
) == 0:
597 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
))
599 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
))
601 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." \
602 % (self
.InfFileName
, str(PlatformArchList
), GenFdsGlobalVariable
.ActivePlatform
, str(set (UseArchList
) & set (TargetArchList
))))
604 ## __GetEFIOutPutPath__() method
606 # Get the output path for generated files
608 # @param self The object pointer
609 # @retval string Path that output files from this INF go to
611 def __GetEFIOutPutPath__(self
):
614 (ModulePath
, FileName
) = os
.path
.split(self
.InfFileName
)
615 Index
= FileName
.rfind('.')
616 FileName
= FileName
[0:Index
]
617 if self
.OverrideGuid
:
618 FileName
= self
.OverrideGuid
620 if self
.CurrentArch
!= None:
621 Arch
= self
.CurrentArch
623 OutputPath
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
],
629 OutputPath
= os
.path
.realpath(OutputPath
)
632 ## __GenSimpleFileSection__() method
634 # Generate section by specified file name or a list of files with file extension
636 # @param self The object pointer
637 # @param Rule The rule object used to generate section
638 # @retval string File name of the generated section file
640 def __GenSimpleFileSection__(self
, Rule
):
642 # Prepare the parameter of GenSection
646 GenSecInputFile
= None
647 if Rule
.FileName
!= None:
648 GenSecInputFile
= self
.__ExtendMacro
__(Rule
.FileName
)
649 if os
.path
.isabs(GenSecInputFile
):
650 GenSecInputFile
= os
.path
.normpath(GenSecInputFile
)
652 GenSecInputFile
= os
.path
.normpath(os
.path
.join(self
.EfiOutputPath
, GenSecInputFile
))
654 FileList
, IsSect
= Section
.Section
.GetFileList(self
, '', Rule
.FileExtension
)
657 SectionType
= Rule
.SectionType
659 # Convert Fv Section Type for PI1.1 SMM driver.
661 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
662 if SectionType
== 'DXE_DEPEX':
663 SectionType
= 'SMM_DEPEX'
665 # Framework SMM Driver has no SMM_DEPEX section type
667 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
668 if SectionType
== 'SMM_DEPEX':
669 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
671 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
672 if self
.KeepReloc
!= None:
673 NoStrip
= self
.KeepReloc
674 elif Rule
.KeepReloc
!= None:
675 NoStrip
= Rule
.KeepReloc
676 elif self
.ShadowFromInfFile
!= None:
677 NoStrip
= self
.ShadowFromInfFile
680 for File
in FileList
:
683 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
684 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
686 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
687 File
= GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)
689 #Get PE Section alignment when align is set to AUTO
690 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
691 ImageObj
= PeImageClass (File
)
692 if ImageObj
.SectionAlignment
< 0x400:
693 self
.Alignment
= str (ImageObj
.SectionAlignment
)
695 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
698 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
699 if not os
.path
.exists(FileBeforeStrip
) or \
700 (os
.path
.getmtime(File
) > os
.path
.getmtime(FileBeforeStrip
)):
701 CopyLongFilePath(File
, FileBeforeStrip
)
702 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
703 GenFdsGlobalVariable
.GenerateFirmwareImage(
710 if SectionType
== 'TE':
711 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
712 GenFdsGlobalVariable
.GenerateFirmwareImage(
719 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [File
], Section
.Section
.SectionType
[SectionType
])
720 OutputFileList
.append(OutputFile
)
723 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
724 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
725 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
726 GenSecInputFile
= GenFdsGlobalVariable
.MacroExtend(GenSecInputFile
, Dict
, self
.CurrentArch
)
728 #Get PE Section alignment when align is set to AUTO
729 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
730 ImageObj
= PeImageClass (GenSecInputFile
)
731 if ImageObj
.SectionAlignment
< 0x400:
732 self
.Alignment
= str (ImageObj
.SectionAlignment
)
734 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
737 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
738 if not os
.path
.exists(FileBeforeStrip
) or \
739 (os
.path
.getmtime(GenSecInputFile
) > os
.path
.getmtime(FileBeforeStrip
)):
740 CopyLongFilePath(GenSecInputFile
, FileBeforeStrip
)
742 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
743 GenFdsGlobalVariable
.GenerateFirmwareImage(
748 GenSecInputFile
= StrippedFile
750 if SectionType
== 'TE':
751 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
752 GenFdsGlobalVariable
.GenerateFirmwareImage(
757 GenSecInputFile
= TeFile
759 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [GenSecInputFile
], Section
.Section
.SectionType
[SectionType
])
760 OutputFileList
.append(OutputFile
)
762 return OutputFileList
764 ## __GenSimpleFileFfs__() method
768 # @param self The object pointer
769 # @param Rule The rule object used to generate section
770 # @param InputFileList The output file list from GenSection
771 # @retval string Generated FFS file name
773 def __GenSimpleFileFfs__(self
, Rule
, InputFileList
):
774 FfsOutput
= self
.OutputPath
+ \
776 self
.__ExtendMacro
__(Rule
.NameGuid
) + \
779 GenFdsGlobalVariable
.VerboseLogger(self
.__ExtendMacro
__(Rule
.NameGuid
))
781 SectionAlignments
= []
782 for InputFile
in InputFileList
:
783 InputSection
.append(InputFile
)
784 SectionAlignments
.append(Rule
.SectAlignment
)
786 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
787 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
788 if len(PcdValue
) == 0:
789 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
791 if PcdValue
.startswith('{'):
792 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
793 RegistryGuidStr
= PcdValue
794 if len(RegistryGuidStr
) == 0:
795 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
797 self
.ModuleGuid
= RegistryGuidStr
799 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputSection
,
800 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
801 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
802 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
803 SectionAlign
=SectionAlignments
807 ## __GenComplexFileSection__() method
809 # Generate section by sections in Rule
811 # @param self The object pointer
812 # @param Rule The rule object used to generate section
813 # @param FvChildAddr Array of the inside FvImage base address
814 # @param FvParentAddr Parent Fv base address
815 # @retval string File name of the generated section file
817 def __GenComplexFileSection__(self
, Rule
, FvChildAddr
, FvParentAddr
):
818 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
819 if Rule
.KeepReloc
!= None:
820 self
.KeepRelocFromRule
= Rule
.KeepReloc
824 HasGneratedFlag
= False
825 if self
.PcdIsDriver
== 'PEI_PCD_DRIVER':
826 if self
.IsBinaryModule
:
827 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "PEIPcdDataBase.raw")
829 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "PEIPcdDataBase.raw")
830 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "PEIPcdDataBaseSec.raw")
831 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
835 SectFiles
.append(PcdExDbSecName
)
836 SectAlignments
.append(None)
837 elif self
.PcdIsDriver
== 'DXE_PCD_DRIVER':
838 if self
.IsBinaryModule
:
839 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "DXEPcdDataBase.raw")
841 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "DXEPcdDataBase.raw")
842 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "DXEPcdDataBaseSec.raw")
843 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
847 SectFiles
.append(PcdExDbSecName
)
848 SectAlignments
.append(None)
849 for Sect
in Rule
.SectionList
:
850 SecIndex
= '%d' %Index
853 # Convert Fv Section Type for PI1.1 SMM driver.
855 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
856 if Sect
.SectionType
== 'DXE_DEPEX':
857 Sect
.SectionType
= 'SMM_DEPEX'
859 # Framework SMM Driver has no SMM_DEPEX section type
861 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
862 if Sect
.SectionType
== 'SMM_DEPEX':
863 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
865 # process the inside FvImage from FvSection or GuidSection
867 if FvChildAddr
!= []:
868 if isinstance(Sect
, FvImageSection
):
869 Sect
.FvAddr
= FvChildAddr
.pop(0)
870 elif isinstance(Sect
, GuidSection
):
871 Sect
.FvAddr
= FvChildAddr
872 if FvParentAddr
!= None and isinstance(Sect
, GuidSection
):
873 Sect
.FvParentAddr
= FvParentAddr
875 if Rule
.KeyStringList
!= []:
876 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, Rule
.KeyStringList
, self
)
878 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, self
.KeyStringList
, self
)
880 if not HasGneratedFlag
:
881 UniVfrOffsetFileSection
= ""
882 ModuleFileName
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
)
883 InfData
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClass(ModuleFileName
), self
.CurrentArch
]
885 # Search the source list in InfData to find if there are .vfr file exist.
888 VfrUniOffsetList
= []
889 for SourceFile
in InfData
.Sources
:
890 if SourceFile
.Type
.upper() == ".VFR" :
892 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
894 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
895 if SourceFile
.Type
.upper() == ".UNI" :
897 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
899 VfrUniBaseName
["UniOffsetName"] = (self
.BaseName
+ "Strings")
902 if len(VfrUniBaseName
) > 0:
903 VfrUniOffsetList
= self
.__GetBuildOutputMapFileVfrUniInfo
(VfrUniBaseName
)
905 # Generate the Raw data of raw section
907 os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
908 UniVfrOffsetFileName
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
909 UniVfrOffsetFileSection
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ 'Offset' + '.raw')
911 self
.__GenUniVfrOffsetFile
(VfrUniOffsetList
, UniVfrOffsetFileName
)
913 UniVfrOffsetFileNameList
= []
914 UniVfrOffsetFileNameList
.append(UniVfrOffsetFileName
)
915 """Call GenSection"""
916 GenFdsGlobalVariable
.GenerateSection(UniVfrOffsetFileSection
,
917 UniVfrOffsetFileNameList
,
920 os
.remove(UniVfrOffsetFileName
)
921 SectList
.append(UniVfrOffsetFileSection
)
922 HasGneratedFlag
= True
924 for SecName
in SectList
:
925 SectFiles
.append(SecName
)
926 SectAlignments
.append(Align
)
928 return SectFiles
, SectAlignments
930 ## __GenComplexFileFfs__() method
934 # @param self The object pointer
935 # @param Rule The rule object used to generate section
936 # @param InputFileList The output file list from GenSection
937 # @retval string Generated FFS file name
939 def __GenComplexFileFfs__(self
, Rule
, InputFile
, Alignments
):
941 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
942 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
943 if len(PcdValue
) == 0:
944 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
946 if PcdValue
.startswith('{'):
947 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
948 RegistryGuidStr
= PcdValue
949 if len(RegistryGuidStr
) == 0:
950 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
952 self
.ModuleGuid
= RegistryGuidStr
954 FfsOutput
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
955 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputFile
,
956 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
957 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
958 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
959 SectionAlign
=Alignments
963 ## __GetGenFfsCmdParameter__() method
965 # Create parameter string for GenFfs
967 # @param self The object pointer
968 # @param Rule The rule object used to generate section
969 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
971 def __GetGenFfsCmdParameter__(self
, Rule
):
973 result
+= ('-t', Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
])
974 if Rule
.Fixed
!= False:
976 if Rule
.CheckSum
!= False:
979 if Rule
.Alignment
!= None and Rule
.Alignment
!= '':
980 result
+= ('-a', Rule
.Alignment
)
984 ## __GetBuildOutputMapFileVfrUniInfo() method
986 # Find the offset of UNI/INF object offset in the EFI image file.
988 # @param self The object pointer
989 # @param VfrUniBaseName A name list contain the UNI/INF object name.
990 # @retval RetValue A list contain offset of UNI/INF object.
992 def __GetBuildOutputMapFileVfrUniInfo(self
, VfrUniBaseName
):
993 MapFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".map")
994 EfiFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".efi")
995 return GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
997 ## __GenUniVfrOffsetFile() method
999 # Generate the offset file for the module which contain VFR or UNI file.
1001 # @param self The object pointer
1002 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
1003 # @param UniVfrOffsetFileName The output offset file name.
1005 def __GenUniVfrOffsetFile(self
, VfrUniOffsetList
, UniVfrOffsetFileName
):
1008 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
1010 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %UniVfrOffsetFileName
,None)
1012 # Use a instance of StringIO to cache data
1013 fStringIO
= StringIO
.StringIO('')
1015 for Item
in VfrUniOffsetList
:
1016 if (Item
[0].find("Strings") != -1):
1018 # UNI offset in image.
1020 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1022 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
1023 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
1024 fStringIO
.write(''.join(UniGuid
))
1025 UniValue
= pack ('Q', int (Item
[1], 16))
1026 fStringIO
.write (UniValue
)
1029 # VFR binary offset in image.
1031 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1033 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
1034 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
1035 fStringIO
.write(''.join(VfrGuid
))
1037 VfrValue
= pack ('Q', int (Item
[1], 16))
1038 fStringIO
.write (VfrValue
)
1041 # write data into file.
1044 fInputfile
.write (fStringIO
.getvalue())
1046 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)