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
.String
import *
32 from Common
.Misc
import PathClass
33 from Common
.Misc
import GuidStructureByteArrayToGuidString
34 from Common
.Misc
import ProcessDuplicatedInf
35 from Common
.Misc
import GetVariableOffset
36 from Common
import EdkLogger
37 from Common
.BuildToolError
import *
38 from GuidSection
import GuidSection
39 from FvImageSection
import FvImageSection
40 from Common
.Misc
import PeImageClass
41 from AutoGen
.GenDepex
import DependencyExpression
42 from PatchPcdValue
.PatchPcdValue
import PatchBinaryFile
43 from Common
.LongFilePathSupport
import CopyLongFilePath
44 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
46 ## generate FFS from INF
49 class FfsInfStatement(FfsInfStatementClassObject
):
50 ## The mapping dictionary from datum type to its maximum number.
51 _MAX_SIZE_TYPE
= {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}
54 # @param self The object pointer
57 FfsInfStatementClassObject
.__init
__(self
)
58 self
.TargetOverrideList
= []
59 self
.ShadowFromInfFile
= None
60 self
.KeepRelocFromRule
= None
63 self
.PiSpecVersion
= '0x00000000'
65 self
.FinalTargetSuffixMap
= {}
66 self
.CurrentLineNum
= None
67 self
.CurrentLineContent
= None
69 self
.InfFileName
= None
70 self
.OverrideGuid
= None
71 self
.PatchedBinFile
= ''
74 ## GetFinalTargetSuffixMap() method
76 # Get final build target list
77 def GetFinalTargetSuffixMap(self
):
78 if not self
.InfModule
or not self
.CurrentArch
:
80 if not self
.FinalTargetSuffixMap
:
81 FinalBuildTargetList
= GenFdsGlobalVariable
.GetModuleCodaTargetList(self
.InfModule
, self
.CurrentArch
)
82 for File
in FinalBuildTargetList
:
83 self
.FinalTargetSuffixMap
.setdefault(os
.path
.splitext(File
)[1], []).append(File
)
85 # Check if current INF module has DEPEX
86 if '.depex' not in self
.FinalTargetSuffixMap
and self
.InfModule
.ModuleType
!= "USER_DEFINED" \
87 and not self
.InfModule
.DxsFile
and not self
.InfModule
.LibraryClass
:
88 ModuleType
= self
.InfModule
.ModuleType
89 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
91 if ModuleType
!= DataType
.SUP_MODULE_USER_DEFINED
:
92 for LibraryClass
in PlatformDataBase
.LibraryClasses
.GetKeys():
93 if LibraryClass
.startswith("NULL") and PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]:
94 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]
96 StrModule
= str(self
.InfModule
)
98 if StrModule
in PlatformDataBase
.Modules
:
99 PlatformModule
= PlatformDataBase
.Modules
[StrModule
]
100 for LibraryClass
in PlatformModule
.LibraryClasses
:
101 if LibraryClass
.startswith("NULL"):
102 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
104 DependencyList
= [self
.InfModule
]
107 while len(DependencyList
) > 0:
108 Module
= DependencyList
.pop(0)
111 for Dep
in Module
.Depex
[self
.CurrentArch
, ModuleType
]:
113 DepexList
.append('AND')
114 DepexList
.append('(')
115 DepexList
.extend(Dep
)
116 if DepexList
[-1] == 'END': # no need of a END at this time
118 DepexList
.append(')')
119 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
121 for LibName
in Module
.LibraryClasses
:
122 if LibName
in LibraryInstance
:
124 if PlatformModule
and LibName
in PlatformModule
.LibraryClasses
:
125 LibraryPath
= PlatformModule
.LibraryClasses
[LibName
]
127 LibraryPath
= PlatformDataBase
.LibraryClasses
[LibName
, ModuleType
]
129 LibraryPath
= Module
.LibraryClasses
[LibName
]
132 LibraryModule
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[LibraryPath
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
133 LibraryInstance
[LibName
] = LibraryModule
134 DependencyList
.append(LibraryModule
)
136 Dpx
= DependencyExpression(DepexList
, ModuleType
, True)
137 if len(Dpx
.PostfixNotation
) != 0:
138 # It means this module has DEPEX
139 self
.FinalTargetSuffixMap
['.depex'] = [os
.path
.join(self
.EfiOutputPath
, self
.BaseName
) + '.depex']
140 return self
.FinalTargetSuffixMap
142 ## __InfParse() method
144 # Parse inf file to get module information
146 # @param self The object pointer
147 # @param Dict dictionary contains macro and value pair
149 def __InfParse__(self
, Dict
= {}):
151 GenFdsGlobalVariable
.VerboseLogger( " Begine parsing INf file : %s" %self
.InfFileName
)
153 self
.InfFileName
= self
.InfFileName
.replace('$(WORKSPACE)', '')
154 if len(self
.InfFileName
) > 1 and self
.InfFileName
[0] == '\\' and self
.InfFileName
[1] == '\\':
156 elif self
.InfFileName
[0] == '\\' or self
.InfFileName
[0] == '/' :
157 self
.InfFileName
= self
.InfFileName
[1:]
159 if self
.InfFileName
.find('$') == -1:
160 InfPath
= NormPath(self
.InfFileName
)
161 if not os
.path
.exists(InfPath
):
162 InfPath
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(InfPath
)
163 if not os
.path
.exists(InfPath
):
164 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Non-existant Module %s !" % (self
.InfFileName
))
166 self
.CurrentArch
= self
.GetCurrentArch()
168 # Get the InfClass object
171 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
172 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
174 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
176 if self
.OverrideGuid
:
177 PathClassObj
= ProcessDuplicatedInf(PathClassObj
, self
.OverrideGuid
, GenFdsGlobalVariable
.WorkSpaceDir
)
178 if self
.CurrentArch
!= None:
180 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
182 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
184 self
.BaseName
= Inf
.BaseName
185 self
.ModuleGuid
= Inf
.Guid
186 self
.ModuleType
= Inf
.ModuleType
187 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
188 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
189 if Inf
.AutoGenVersion
< 0x00010005:
190 self
.ModuleType
= Inf
.ComponentType
191 self
.VersionString
= Inf
.Version
192 self
.BinFileList
= Inf
.Binaries
193 self
.SourceFileList
= Inf
.Sources
194 if self
.KeepReloc
== None and Inf
.Shadow
:
195 self
.ShadowFromInfFile
= Inf
.Shadow
198 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
199 self
.BaseName
= Inf
.BaseName
200 self
.ModuleGuid
= Inf
.Guid
201 self
.ModuleType
= Inf
.ModuleType
202 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
203 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
204 self
.VersionString
= Inf
.Version
205 self
.BinFileList
= Inf
.Binaries
206 self
.SourceFileList
= Inf
.Sources
207 if self
.BinFileList
== []:
208 EdkLogger
.error("GenFds", GENFDS_ERROR
,
209 "INF %s specified in FDF could not be found in build ARCH %s!" \
210 % (self
.InfFileName
, GenFdsGlobalVariable
.ArchList
))
212 if self
.OverrideGuid
:
213 self
.ModuleGuid
= self
.OverrideGuid
215 if len(self
.SourceFileList
) != 0 and not self
.InDsc
:
216 EdkLogger
.warn("GenFds", GENFDS_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % (self
.InfFileName
))
218 if self
.ModuleType
== 'SMM_CORE' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
219 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
)
221 if Inf
._Defs
!= None and len(Inf
._Defs
) > 0:
222 self
.OptRomDefs
.update(Inf
._Defs
)
226 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
227 FdfPcdDict
= GenFdsGlobalVariable
.FdfParser
.Profile
.PcdDict
229 # Workaround here: both build and GenFds tool convert the workspace path to lower case
230 # But INF file path in FDF and DSC file may have real case characters.
231 # Try to convert the path to lower case to see if PCDs value are override by DSC.
233 for DscModule
in Platform
.Modules
:
234 DscModules
[str(DscModule
).lower()] = Platform
.Modules
[DscModule
]
235 for PcdKey
in InfPcds
:
236 Pcd
= InfPcds
[PcdKey
]
237 if not hasattr(Pcd
, 'Offset'):
239 if Pcd
.Type
!= 'PatchableInModule':
241 # Override Patchable PCD value by the value from DSC
243 InfLowerPath
= str(PathClassObj
).lower()
244 if InfLowerPath
in DscModules
and PcdKey
in DscModules
[InfLowerPath
].Pcds
:
245 PatchPcd
= DscModules
[InfLowerPath
].Pcds
[PcdKey
]
246 elif PcdKey
in Platform
.Pcds
:
247 PatchPcd
= Platform
.Pcds
[PcdKey
]
249 if PatchPcd
and Pcd
.Type
== PatchPcd
.Type
:
250 DefaultValue
= PatchPcd
.DefaultValue
253 # Override Patchable PCD value by the value from FDF
255 if PcdKey
in FdfPcdDict
:
256 DefaultValue
= FdfPcdDict
[PcdKey
]
259 if not DscOverride
and not FdfOverride
:
261 # Check value, if value are equal, no need to patch
262 if Pcd
.DatumType
== "VOID*":
263 if Pcd
.DefaultValue
== DefaultValue
or DefaultValue
in [None, '']:
265 # Get the string size from FDF or DSC
266 if DefaultValue
[0] == 'L':
267 # Remove L"", but the '\0' must be appended
268 MaxDatumSize
= str((len(DefaultValue
) - 2) * 2)
269 elif DefaultValue
[0] == '{':
270 MaxDatumSize
= str(len(DefaultValue
.split(',')))
272 MaxDatumSize
= str(len(DefaultValue
) - 1)
274 Pcd
.MaxDatumSize
= PatchPcd
.MaxDatumSize
275 # If no defined the maximum size in DSC, try to get current size from INF
276 if Pcd
.MaxDatumSize
in ['', None]:
277 Pcd
.MaxDatumSize
= str(len(Pcd
.DefaultValue
.split(',')))
280 if Pcd
.DefaultValue
.upper().startswith('0X'):
282 if DefaultValue
.upper().startswith('0X'):
285 PcdValueInImg
= int(Pcd
.DefaultValue
, Base1
)
286 PcdValueInDscOrFdf
= int(DefaultValue
, Base2
)
287 if PcdValueInImg
== PcdValueInDscOrFdf
:
291 # Check the Pcd size and data type
292 if Pcd
.DatumType
== "VOID*":
293 if int(MaxDatumSize
) > int(Pcd
.MaxDatumSize
):
294 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
295 % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, int(MaxDatumSize
) - int(Pcd
.MaxDatumSize
)))
297 if PcdValueInDscOrFdf
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
] \
298 or PcdValueInImg
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
]:
299 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of %s type PCD '%s.%s' doesn't match its data type." \
300 % (Pcd
.DatumType
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
301 self
.PatchPcds
.append((Pcd
, DefaultValue
))
304 self
.PcdIsDriver
= Inf
.PcdIsDriver
305 self
.IsBinaryModule
= Inf
.IsBinaryModule
306 GenFdsGlobalVariable
.VerboseLogger("BaseName : %s" % self
.BaseName
)
307 GenFdsGlobalVariable
.VerboseLogger("ModuleGuid : %s" % self
.ModuleGuid
)
308 GenFdsGlobalVariable
.VerboseLogger("ModuleType : %s" % self
.ModuleType
)
309 GenFdsGlobalVariable
.VerboseLogger("VersionString : %s" % self
.VersionString
)
310 GenFdsGlobalVariable
.VerboseLogger("InfFileName :%s" % self
.InfFileName
)
313 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
316 self
.OutputPath
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, \
317 self
.ModuleGuid
+ self
.BaseName
)
318 if not os
.path
.exists(self
.OutputPath
) :
319 os
.makedirs(self
.OutputPath
)
321 self
.EfiOutputPath
= self
.__GetEFIOutPutPath
__()
322 GenFdsGlobalVariable
.VerboseLogger( "ModuelEFIPath: " + self
.EfiOutputPath
)
326 # Patch EFI file with patch PCD
328 # @param EfiFile: EFI file needs to be patched.
329 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
330 # If passed in file does not end with efi, return as is
332 def PatchEfiFile(self
, EfiFile
, FileType
):
333 if not self
.PatchPcds
:
335 if FileType
!= 'PE32' and self
.ModuleType
!= "USER_DEFINED":
337 if self
.PatchedBinFile
:
338 EdkLogger
.error("GenFds", GENFDS_ERROR
,
339 'Only one binary file can be patched:\n'
340 ' a binary file has been patched: %s\n'
341 ' current file: %s' % (self
.PatchedBinFile
, EfiFile
),
342 File
=self
.InfFileName
)
343 Basename
= os
.path
.basename(EfiFile
)
344 Output
= os
.path
.join(self
.OutputPath
, Basename
)
345 CopyLongFilePath(EfiFile
, Output
)
346 for Pcd
, Value
in self
.PatchPcds
:
347 RetVal
, RetStr
= PatchBinaryFile(Output
, int(Pcd
.Offset
, 0), Pcd
.DatumType
, Value
, Pcd
.MaxDatumSize
)
349 EdkLogger
.error("GenFds", GENFDS_ERROR
, RetStr
, File
=self
.InfFileName
)
350 self
.PatchedBinFile
= os
.path
.normpath(EfiFile
)
356 # @param self The object pointer
357 # @param Dict dictionary contains macro and value pair
358 # @param FvChildAddr Array of the inside FvImage base address
359 # @param FvParentAddr Parent Fv base address
360 # @retval string Generated FFS file name
362 def GenFfs(self
, Dict
= {}, FvChildAddr
= [], FvParentAddr
=None):
364 # Parse Inf file get Module related information
367 self
.__InfParse
__(Dict
)
368 SrcFile
= os
.path
.join( GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
);
369 DestFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
372 SrcPath
= os
.path
.dirname(SrcFile
)
373 SrcFileName
= os
.path
.basename(SrcFile
)
374 SrcFileBase
, SrcFileExt
= os
.path
.splitext(SrcFileName
)
375 DestPath
= os
.path
.dirname(DestFile
)
376 DestFileName
= os
.path
.basename(DestFile
)
377 DestFileBase
, DestFileExt
= os
.path
.splitext(DestFileName
)
381 "${s_path}" : SrcPath
,
382 "${s_dir}" : SrcFileDir
,
383 "${s_name}" : SrcFileName
,
384 "${s_base}" : SrcFileBase
,
385 "${s_ext}" : SrcFileExt
,
388 "${d_path}" : DestPath
,
389 "${d_name}" : DestFileName
,
390 "${d_base}" : DestFileBase
,
391 "${d_ext}" : DestFileExt
394 # Allow binary type module not specify override rule in FDF file.
396 if len(self
.BinFileList
) > 0:
397 if self
.Rule
== None or self
.Rule
== "":
401 # Get the rule of how to generate Ffs file
403 Rule
= self
.__GetRule
__()
404 GenFdsGlobalVariable
.VerboseLogger( "Packing binaries from inf file : %s" %self
.InfFileName
)
406 # Convert Fv File Type for PI1.1 SMM driver.
408 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
409 if Rule
.FvFileType
== 'DRIVER':
410 Rule
.FvFileType
= 'SMM'
412 # Framework SMM Driver has no SMM FV file type
414 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
415 if Rule
.FvFileType
== 'SMM' or Rule
.FvFileType
== 'SMM_CORE':
416 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File
=self
.InfFileName
)
418 # For the rule only has simpleFile
420 if isinstance (Rule
, RuleSimpleFile
.RuleSimpleFile
) :
421 SectionOutputList
= self
.__GenSimpleFileSection
__(Rule
)
422 FfsOutput
= self
.__GenSimpleFileFfs
__(Rule
, SectionOutputList
)
425 # For Rule has ComplexFile
427 elif isinstance(Rule
, RuleComplexFile
.RuleComplexFile
):
428 InputSectList
, InputSectAlignments
= self
.__GenComplexFileSection
__(Rule
, FvChildAddr
, FvParentAddr
)
429 FfsOutput
= self
.__GenComplexFileFfs
__(Rule
, InputSectList
, InputSectAlignments
)
433 ## __ExtendMacro__() method
435 # Replace macro with its value
437 # @param self The object pointer
438 # @param String The string to be replaced
439 # @retval string Macro replaced string
441 def __ExtendMacro__ (self
, String
):
443 '$(INF_OUTPUT)' : self
.EfiOutputPath
,
444 '$(MODULE_NAME)' : self
.BaseName
,
445 '$(BUILD_NUMBER)': self
.BuildNum
,
446 '$(INF_VERSION)' : self
.VersionString
,
447 '$(NAMED_GUID)' : self
.ModuleGuid
449 String
= GenFdsGlobalVariable
.MacroExtend(String
, MacroDict
)
450 String
= GenFdsGlobalVariable
.MacroExtend(String
, self
.MacroDict
)
453 ## __GetRule__() method
455 # Get correct rule for generating FFS for this INF
457 # @param self The object pointer
458 # @retval Rule Rule object
460 def __GetRule__ (self
) :
462 if self
.CurrentArch
== None:
463 CurrentArchList
= ['common']
465 CurrentArchList
.append(self
.CurrentArch
)
467 for CurrentArch
in CurrentArchList
:
468 RuleName
= 'RULE' + \
470 CurrentArch
.upper() + \
472 self
.ModuleType
.upper()
473 if self
.Rule
!= None:
474 RuleName
= RuleName
+ \
478 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
480 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
483 RuleName
= 'RULE' + \
487 self
.ModuleType
.upper()
489 if self
.Rule
!= None:
490 RuleName
= RuleName
+ \
494 GenFdsGlobalVariable
.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName
, self
.InfFileName
))
496 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
498 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
502 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'Don\'t Find common rule %s for INF %s' \
503 % (RuleName
, self
.InfFileName
))
505 ## __GetPlatformArchList__() method
507 # Get Arch list this INF built under
509 # @param self The object pointer
510 # @retval list Arch list
512 def __GetPlatformArchList__(self
):
514 InfFileKey
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
))
516 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IA32', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
517 if PlatformDataBase
!= None:
518 if InfFileKey
in PlatformDataBase
.Modules
:
519 DscArchList
.append ('IA32')
521 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'X64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
522 if PlatformDataBase
!= None:
523 if InfFileKey
in PlatformDataBase
.Modules
:
524 DscArchList
.append ('X64')
526 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IPF', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
527 if PlatformDataBase
!= None:
528 if InfFileKey
in (PlatformDataBase
.Modules
):
529 DscArchList
.append ('IPF')
531 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'ARM', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
532 if PlatformDataBase
!= None:
533 if InfFileKey
in (PlatformDataBase
.Modules
):
534 DscArchList
.append ('ARM')
536 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'EBC', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
537 if PlatformDataBase
!= None:
538 if InfFileKey
in (PlatformDataBase
.Modules
):
539 DscArchList
.append ('EBC')
541 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'AARCH64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
542 if PlatformDataBase
!= None:
543 if InfFileKey
in (PlatformDataBase
.Modules
):
544 DscArchList
.append ('AARCH64')
548 ## GetCurrentArch() method
550 # Get Arch list of the module from this INF is to be placed into flash
552 # @param self The object pointer
553 # @retval list Arch list
555 def GetCurrentArch(self
) :
557 TargetArchList
= GenFdsGlobalVariable
.ArchList
559 PlatformArchList
= self
.__GetPlatformArchList
__()
561 CurArchList
= TargetArchList
562 if PlatformArchList
!= []:
563 CurArchList
= list(set (TargetArchList
) & set (PlatformArchList
))
564 GenFdsGlobalVariable
.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList
))
567 if self
.KeyStringList
!= []:
568 for Key
in self
.KeyStringList
:
569 Key
= GenFdsGlobalVariable
.MacroExtend(Key
)
570 Target
, Tag
, Arch
= Key
.split('_')
571 if Arch
in CurArchList
:
572 ArchList
.append(Arch
)
573 if Target
not in self
.TargetOverrideList
:
574 self
.TargetOverrideList
.append(Target
)
576 ArchList
= CurArchList
578 UseArchList
= TargetArchList
579 if self
.UseArch
!= None:
581 UseArchList
.append(self
.UseArch
)
582 ArchList
= list(set (UseArchList
) & set (ArchList
))
584 self
.InfFileName
= NormPath(self
.InfFileName
)
585 if len(PlatformArchList
) == 0:
587 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
588 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
590 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
591 if len(ArchList
) == 1:
594 elif len(ArchList
) > 1:
595 if len(PlatformArchList
) == 0:
596 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
))
598 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
))
600 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." \
601 % (self
.InfFileName
, str(PlatformArchList
), GenFdsGlobalVariable
.ActivePlatform
, str(set (UseArchList
) & set (TargetArchList
))))
603 ## __GetEFIOutPutPath__() method
605 # Get the output path for generated files
607 # @param self The object pointer
608 # @retval string Path that output files from this INF go to
610 def __GetEFIOutPutPath__(self
):
613 (ModulePath
, FileName
) = os
.path
.split(self
.InfFileName
)
614 Index
= FileName
.rfind('.')
615 FileName
= FileName
[0:Index
]
616 if self
.OverrideGuid
:
617 FileName
= self
.OverrideGuid
619 if self
.CurrentArch
!= None:
620 Arch
= self
.CurrentArch
622 OutputPath
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
],
628 OutputPath
= os
.path
.realpath(OutputPath
)
631 ## __GenSimpleFileSection__() method
633 # Generate section by specified file name or a list of files with file extension
635 # @param self The object pointer
636 # @param Rule The rule object used to generate section
637 # @retval string File name of the generated section file
639 def __GenSimpleFileSection__(self
, Rule
):
641 # Prepare the parameter of GenSection
645 GenSecInputFile
= None
646 if Rule
.FileName
!= None:
647 GenSecInputFile
= self
.__ExtendMacro
__(Rule
.FileName
)
648 if os
.path
.isabs(GenSecInputFile
):
649 GenSecInputFile
= os
.path
.normpath(GenSecInputFile
)
651 GenSecInputFile
= os
.path
.normpath(os
.path
.join(self
.EfiOutputPath
, GenSecInputFile
))
653 FileList
, IsSect
= Section
.Section
.GetFileList(self
, '', Rule
.FileExtension
)
656 SectionType
= Rule
.SectionType
658 # Convert Fv Section Type for PI1.1 SMM driver.
660 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
661 if SectionType
== 'DXE_DEPEX':
662 SectionType
= 'SMM_DEPEX'
664 # Framework SMM Driver has no SMM_DEPEX section type
666 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
667 if SectionType
== 'SMM_DEPEX':
668 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
670 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
671 if self
.KeepReloc
!= None:
672 NoStrip
= self
.KeepReloc
673 elif Rule
.KeepReloc
!= None:
674 NoStrip
= Rule
.KeepReloc
675 elif self
.ShadowFromInfFile
!= None:
676 NoStrip
= self
.ShadowFromInfFile
679 for File
in FileList
:
682 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
683 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
685 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
686 File
= GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)
688 #Get PE Section alignment when align is set to AUTO
689 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
690 ImageObj
= PeImageClass (File
)
691 if ImageObj
.SectionAlignment
< 0x400:
692 self
.Alignment
= str (ImageObj
.SectionAlignment
)
694 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
697 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
698 if not os
.path
.exists(FileBeforeStrip
) or \
699 (os
.path
.getmtime(File
) > os
.path
.getmtime(FileBeforeStrip
)):
700 CopyLongFilePath(File
, FileBeforeStrip
)
701 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
702 GenFdsGlobalVariable
.GenerateFirmwareImage(
709 if SectionType
== 'TE':
710 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
711 GenFdsGlobalVariable
.GenerateFirmwareImage(
718 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [File
], Section
.Section
.SectionType
[SectionType
])
719 OutputFileList
.append(OutputFile
)
722 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
723 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
724 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
725 GenSecInputFile
= GenFdsGlobalVariable
.MacroExtend(GenSecInputFile
, Dict
, self
.CurrentArch
)
727 #Get PE Section alignment when align is set to AUTO
728 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
729 ImageObj
= PeImageClass (GenSecInputFile
)
730 if ImageObj
.SectionAlignment
< 0x400:
731 self
.Alignment
= str (ImageObj
.SectionAlignment
)
733 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
736 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
737 if not os
.path
.exists(FileBeforeStrip
) or \
738 (os
.path
.getmtime(GenSecInputFile
) > os
.path
.getmtime(FileBeforeStrip
)):
739 CopyLongFilePath(GenSecInputFile
, FileBeforeStrip
)
741 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
742 GenFdsGlobalVariable
.GenerateFirmwareImage(
747 GenSecInputFile
= StrippedFile
749 if SectionType
== 'TE':
750 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
751 GenFdsGlobalVariable
.GenerateFirmwareImage(
756 GenSecInputFile
= TeFile
758 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [GenSecInputFile
], Section
.Section
.SectionType
[SectionType
])
759 OutputFileList
.append(OutputFile
)
761 return OutputFileList
763 ## __GenSimpleFileFfs__() method
767 # @param self The object pointer
768 # @param Rule The rule object used to generate section
769 # @param InputFileList The output file list from GenSection
770 # @retval string Generated FFS file name
772 def __GenSimpleFileFfs__(self
, Rule
, InputFileList
):
773 FfsOutput
= self
.OutputPath
+ \
775 self
.__ExtendMacro
__(Rule
.NameGuid
) + \
778 GenFdsGlobalVariable
.VerboseLogger(self
.__ExtendMacro
__(Rule
.NameGuid
))
780 SectionAlignments
= []
781 for InputFile
in InputFileList
:
782 InputSection
.append(InputFile
)
783 SectionAlignments
.append(Rule
.SectAlignment
)
785 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
786 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
787 if len(PcdValue
) == 0:
788 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
790 if PcdValue
.startswith('{'):
791 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
792 RegistryGuidStr
= PcdValue
793 if len(RegistryGuidStr
) == 0:
794 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
796 self
.ModuleGuid
= RegistryGuidStr
798 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputSection
,
799 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
800 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
801 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
802 SectionAlign
=SectionAlignments
806 ## __GenComplexFileSection__() method
808 # Generate section by sections in Rule
810 # @param self The object pointer
811 # @param Rule The rule object used to generate section
812 # @param FvChildAddr Array of the inside FvImage base address
813 # @param FvParentAddr Parent Fv base address
814 # @retval string File name of the generated section file
816 def __GenComplexFileSection__(self
, Rule
, FvChildAddr
, FvParentAddr
):
817 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
818 if Rule
.KeepReloc
!= None:
819 self
.KeepRelocFromRule
= Rule
.KeepReloc
823 HasGneratedFlag
= False
824 if self
.PcdIsDriver
== 'PEI_PCD_DRIVER':
825 if self
.IsBinaryModule
:
826 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "PEIPcdDataBase.raw")
828 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "PEIPcdDataBase.raw")
829 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "PEIPcdDataBaseSec.raw")
830 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
834 SectFiles
.append(PcdExDbSecName
)
835 SectAlignments
.append(None)
836 elif self
.PcdIsDriver
== 'DXE_PCD_DRIVER':
837 if self
.IsBinaryModule
:
838 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "DXEPcdDataBase.raw")
840 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "DXEPcdDataBase.raw")
841 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "DXEPcdDataBaseSec.raw")
842 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
846 SectFiles
.append(PcdExDbSecName
)
847 SectAlignments
.append(None)
848 for Sect
in Rule
.SectionList
:
849 SecIndex
= '%d' %Index
852 # Convert Fv Section Type for PI1.1 SMM driver.
854 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
855 if Sect
.SectionType
== 'DXE_DEPEX':
856 Sect
.SectionType
= 'SMM_DEPEX'
858 # Framework SMM Driver has no SMM_DEPEX section type
860 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
861 if Sect
.SectionType
== 'SMM_DEPEX':
862 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
864 # process the inside FvImage from FvSection or GuidSection
866 if FvChildAddr
!= []:
867 if isinstance(Sect
, FvImageSection
):
868 Sect
.FvAddr
= FvChildAddr
.pop(0)
869 elif isinstance(Sect
, GuidSection
):
870 Sect
.FvAddr
= FvChildAddr
871 if FvParentAddr
!= None and isinstance(Sect
, GuidSection
):
872 Sect
.FvParentAddr
= FvParentAddr
874 if Rule
.KeyStringList
!= []:
875 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, Rule
.KeyStringList
, self
)
877 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, self
.KeyStringList
, self
)
879 if not HasGneratedFlag
:
880 UniVfrOffsetFileSection
= ""
881 ModuleFileName
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
)
882 InfData
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClass(ModuleFileName
), self
.CurrentArch
]
884 # Search the source list in InfData to find if there are .vfr file exist.
887 VfrUniOffsetList
= []
888 for SourceFile
in InfData
.Sources
:
889 if SourceFile
.Type
.upper() == ".VFR" :
891 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
893 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
894 if SourceFile
.Type
.upper() == ".UNI" :
896 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
898 VfrUniBaseName
["UniOffsetName"] = (self
.BaseName
+ "Strings")
901 if len(VfrUniBaseName
) > 0:
902 VfrUniOffsetList
= self
.__GetBuildOutputMapFileVfrUniInfo
(VfrUniBaseName
)
904 # Generate the Raw data of raw section
906 os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
907 UniVfrOffsetFileName
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
908 UniVfrOffsetFileSection
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ 'Offset' + '.raw')
910 self
.__GenUniVfrOffsetFile
(VfrUniOffsetList
, UniVfrOffsetFileName
)
912 UniVfrOffsetFileNameList
= []
913 UniVfrOffsetFileNameList
.append(UniVfrOffsetFileName
)
914 """Call GenSection"""
915 GenFdsGlobalVariable
.GenerateSection(UniVfrOffsetFileSection
,
916 UniVfrOffsetFileNameList
,
919 os
.remove(UniVfrOffsetFileName
)
920 SectList
.append(UniVfrOffsetFileSection
)
921 HasGneratedFlag
= True
923 for SecName
in SectList
:
924 SectFiles
.append(SecName
)
925 SectAlignments
.append(Align
)
927 return SectFiles
, SectAlignments
929 ## __GenComplexFileFfs__() method
933 # @param self The object pointer
934 # @param Rule The rule object used to generate section
935 # @param InputFileList The output file list from GenSection
936 # @retval string Generated FFS file name
938 def __GenComplexFileFfs__(self
, Rule
, InputFile
, Alignments
):
940 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
941 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
942 if len(PcdValue
) == 0:
943 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
945 if PcdValue
.startswith('{'):
946 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
947 RegistryGuidStr
= PcdValue
948 if len(RegistryGuidStr
) == 0:
949 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
951 self
.ModuleGuid
= RegistryGuidStr
953 FfsOutput
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
954 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputFile
,
955 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
956 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
957 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
958 SectionAlign
=Alignments
962 ## __GetGenFfsCmdParameter__() method
964 # Create parameter string for GenFfs
966 # @param self The object pointer
967 # @param Rule The rule object used to generate section
968 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
970 def __GetGenFfsCmdParameter__(self
, Rule
):
972 result
+= ('-t', Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
])
973 if Rule
.Fixed
!= False:
975 if Rule
.CheckSum
!= False:
978 if Rule
.Alignment
!= None and Rule
.Alignment
!= '':
979 result
+= ('-a', Rule
.Alignment
)
983 ## __GetBuildOutputMapFileVfrUniInfo() method
985 # Find the offset of UNI/INF object offset in the EFI image file.
987 # @param self The object pointer
988 # @param VfrUniBaseName A name list contain the UNI/INF object name.
989 # @retval RetValue A list contain offset of UNI/INF object.
991 def __GetBuildOutputMapFileVfrUniInfo(self
, VfrUniBaseName
):
992 MapFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".map")
993 EfiFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".efi")
994 return GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
996 ## __GenUniVfrOffsetFile() method
998 # Generate the offset file for the module which contain VFR or UNI file.
1000 # @param self The object pointer
1001 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
1002 # @param UniVfrOffsetFileName The output offset file name.
1004 def __GenUniVfrOffsetFile(self
, VfrUniOffsetList
, UniVfrOffsetFileName
):
1007 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
1009 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %UniVfrOffsetFileName
,None)
1011 # Use a instance of StringIO to cache data
1012 fStringIO
= StringIO
.StringIO('')
1014 for Item
in VfrUniOffsetList
:
1015 if (Item
[0].find("Strings") != -1):
1017 # UNI offset in image.
1019 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1021 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
1022 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
1023 fStringIO
.write(''.join(UniGuid
))
1024 UniValue
= pack ('Q', int (Item
[1], 16))
1025 fStringIO
.write (UniValue
)
1028 # VFR binary offset in image.
1030 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1032 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
1033 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
1034 fStringIO
.write(''.join(VfrGuid
))
1036 VfrValue
= pack ('Q', int (Item
[1], 16))
1037 fStringIO
.write (VfrValue
)
1040 # write data into file.
1043 fInputfile
.write (fStringIO
.getvalue())
1045 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)