2 # process FFS generation from INF statement
4 # Copyright (c) 2007 - 2014, 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.
19 import Common
.LongFilePathOs
as os
22 from GenFdsGlobalVariable
import GenFdsGlobalVariable
28 import RuleComplexFile
29 from CommonDataClass
.FdfClass
import FfsInfStatementClassObject
30 from Common
.String
import *
31 from Common
.Misc
import PathClass
32 from Common
.Misc
import GuidStructureByteArrayToGuidString
33 from Common
.Misc
import ProcessDuplicatedInf
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
41 from Common
.LongFilePathSupport
import CopyLongFilePath
42 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
44 ## generate FFS from INF
47 class FfsInfStatement(FfsInfStatementClassObject
):
48 ## The mapping dictionary from datum type to its maximum number.
49 _MAX_SIZE_TYPE
= {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}
52 # @param self The object pointer
55 FfsInfStatementClassObject
.__init
__(self
)
56 self
.TargetOverrideList
= []
57 self
.ShadowFromInfFile
= None
58 self
.KeepRelocFromRule
= None
61 self
.PiSpecVersion
= '0x00000000'
63 self
.FinalTargetSuffixMap
= {}
64 self
.CurrentLineNum
= None
65 self
.CurrentLineContent
= None
67 self
.InfFileName
= None
68 self
.OverrideGuid
= None
69 self
.PatchedBinFile
= ''
71 ## GetFinalTargetSuffixMap() method
73 # Get final build target list
74 def GetFinalTargetSuffixMap(self
):
75 if not self
.InfModule
or not self
.CurrentArch
:
77 if not self
.FinalTargetSuffixMap
:
78 FinalBuildTargetList
= GenFdsGlobalVariable
.GetModuleCodaTargetList(self
.InfModule
, self
.CurrentArch
)
79 for File
in FinalBuildTargetList
:
80 self
.FinalTargetSuffixMap
.setdefault(os
.path
.splitext(File
)[1], []).append(File
)
82 # Check if current INF module has DEPEX
83 if '.depex' not in self
.FinalTargetSuffixMap
and self
.InfModule
.ModuleType
!= "USER_DEFINED" \
84 and not self
.InfModule
.DxsFile
and not self
.InfModule
.LibraryClass
:
85 ModuleType
= self
.InfModule
.ModuleType
86 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
88 if ModuleType
!= DataType
.SUP_MODULE_USER_DEFINED
:
89 for LibraryClass
in PlatformDataBase
.LibraryClasses
.GetKeys():
90 if LibraryClass
.startswith("NULL") and PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]:
91 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]
93 StrModule
= str(self
.InfModule
)
95 if StrModule
in PlatformDataBase
.Modules
:
96 PlatformModule
= PlatformDataBase
.Modules
[StrModule
]
97 for LibraryClass
in PlatformModule
.LibraryClasses
:
98 if LibraryClass
.startswith("NULL"):
99 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
101 DependencyList
= [self
.InfModule
]
104 while len(DependencyList
) > 0:
105 Module
= DependencyList
.pop(0)
108 for Dep
in Module
.Depex
[self
.CurrentArch
, ModuleType
]:
110 DepexList
.append('AND')
111 DepexList
.append('(')
112 DepexList
.extend(Dep
)
113 if DepexList
[-1] == 'END': # no need of a END at this time
115 DepexList
.append(')')
116 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
118 for LibName
in Module
.LibraryClasses
:
119 if LibName
in LibraryInstance
:
121 if PlatformModule
and LibName
in PlatformModule
.LibraryClasses
:
122 LibraryPath
= PlatformModule
.LibraryClasses
[LibName
]
124 LibraryPath
= PlatformDataBase
.LibraryClasses
[LibName
, ModuleType
]
126 LibraryPath
= Module
.LibraryClasses
[LibName
]
129 LibraryModule
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[LibraryPath
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
130 LibraryInstance
[LibName
] = LibraryModule
131 DependencyList
.append(LibraryModule
)
133 Dpx
= DependencyExpression(DepexList
, ModuleType
, True)
134 if len(Dpx
.PostfixNotation
) != 0:
135 # It means this module has DEPEX
136 self
.FinalTargetSuffixMap
['.depex'] = [os
.path
.join(self
.EfiOutputPath
, self
.BaseName
) + '.depex']
137 return self
.FinalTargetSuffixMap
139 ## __InfParse() method
141 # Parse inf file to get module information
143 # @param self The object pointer
144 # @param Dict dictionary contains macro and value pair
146 def __InfParse__(self
, Dict
= {}):
148 GenFdsGlobalVariable
.VerboseLogger( " Begine parsing INf file : %s" %self
.InfFileName
)
150 self
.InfFileName
= self
.InfFileName
.replace('$(WORKSPACE)', '')
151 if len(self
.InfFileName
) > 1 and self
.InfFileName
[0] == '\\' and self
.InfFileName
[1] == '\\':
153 elif self
.InfFileName
[0] == '\\' or self
.InfFileName
[0] == '/' :
154 self
.InfFileName
= self
.InfFileName
[1:]
156 if self
.InfFileName
.find('$') == -1:
157 InfPath
= NormPath(self
.InfFileName
)
158 if not os
.path
.exists(InfPath
):
159 InfPath
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(InfPath
)
160 if not os
.path
.exists(InfPath
):
161 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Non-existant Module %s !" % (self
.InfFileName
))
163 self
.CurrentArch
= self
.GetCurrentArch()
165 # Get the InfClass object
168 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
169 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
171 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
173 if self
.OverrideGuid
:
174 PathClassObj
= ProcessDuplicatedInf(PathClassObj
, self
.OverrideGuid
, GenFdsGlobalVariable
.WorkSpaceDir
)
175 if self
.CurrentArch
!= None:
177 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
179 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
181 self
.BaseName
= Inf
.BaseName
182 self
.ModuleGuid
= Inf
.Guid
183 self
.ModuleType
= Inf
.ModuleType
184 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
185 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
186 if Inf
.AutoGenVersion
< 0x00010005:
187 self
.ModuleType
= Inf
.ComponentType
188 self
.VersionString
= Inf
.Version
189 self
.BinFileList
= Inf
.Binaries
190 self
.SourceFileList
= Inf
.Sources
191 if self
.KeepReloc
== None and Inf
.Shadow
:
192 self
.ShadowFromInfFile
= Inf
.Shadow
195 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
196 self
.BaseName
= Inf
.BaseName
197 self
.ModuleGuid
= Inf
.Guid
198 self
.ModuleType
= Inf
.ModuleType
199 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
200 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
201 self
.VersionString
= Inf
.Version
202 self
.BinFileList
= Inf
.Binaries
203 self
.SourceFileList
= Inf
.Sources
204 if self
.BinFileList
== []:
205 EdkLogger
.error("GenFds", GENFDS_ERROR
,
206 "INF %s specified in FDF could not be found in build ARCH %s!" \
207 % (self
.InfFileName
, GenFdsGlobalVariable
.ArchList
))
209 if self
.OverrideGuid
:
210 self
.ModuleGuid
= self
.OverrideGuid
212 if len(self
.SourceFileList
) != 0 and not self
.InDsc
:
213 EdkLogger
.warn("GenFds", GENFDS_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % (self
.InfFileName
))
215 if self
.ModuleType
== 'SMM_CORE' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
216 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
)
218 if Inf
._Defs
!= None and len(Inf
._Defs
) > 0:
219 self
.OptRomDefs
.update(Inf
._Defs
)
223 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
224 FdfPcdDict
= GenFdsGlobalVariable
.FdfParser
.Profile
.PcdDict
226 # Workaround here: both build and GenFds tool convert the workspace path to lower case
227 # But INF file path in FDF and DSC file may have real case characters.
228 # Try to convert the path to lower case to see if PCDs value are override by DSC.
230 for DscModule
in Platform
.Modules
:
231 DscModules
[str(DscModule
).lower()] = Platform
.Modules
[DscModule
]
232 for PcdKey
in InfPcds
:
233 Pcd
= InfPcds
[PcdKey
]
234 if not hasattr(Pcd
, 'Offset'):
236 if Pcd
.Type
!= 'PatchableInModule':
238 # Override Patchable PCD value by the value from DSC
240 InfLowerPath
= str(PathClassObj
).lower()
241 if InfLowerPath
in DscModules
and PcdKey
in DscModules
[InfLowerPath
].Pcds
:
242 PatchPcd
= DscModules
[InfLowerPath
].Pcds
[PcdKey
]
243 elif PcdKey
in Platform
.Pcds
:
244 PatchPcd
= Platform
.Pcds
[PcdKey
]
246 if PatchPcd
and Pcd
.Type
== PatchPcd
.Type
:
247 DefaultValue
= PatchPcd
.DefaultValue
250 # Override Patchable PCD value by the value from FDF
252 if PcdKey
in FdfPcdDict
:
253 DefaultValue
= FdfPcdDict
[PcdKey
]
256 if not DscOverride
and not FdfOverride
:
258 # Check value, if value are equal, no need to patch
259 if Pcd
.DatumType
== "VOID*":
260 if Pcd
.DefaultValue
== DefaultValue
or DefaultValue
in [None, '']:
262 # Get the string size from FDF or DSC
263 if DefaultValue
[0] == 'L':
264 # Remove L"", but the '\0' must be appended
265 MaxDatumSize
= str((len(DefaultValue
) - 2) * 2)
266 elif DefaultValue
[0] == '{':
267 MaxDatumSize
= str(len(DefaultValue
.split(',')))
269 MaxDatumSize
= str(len(DefaultValue
) - 1)
271 Pcd
.MaxDatumSize
= PatchPcd
.MaxDatumSize
272 # If no defined the maximum size in DSC, try to get current size from INF
273 if Pcd
.MaxDatumSize
in ['', None]:
274 Pcd
.MaxDatumSize
= str(len(Pcd
.DefaultValue
.split(',')))
277 if Pcd
.DefaultValue
.upper().startswith('0X'):
279 if DefaultValue
.upper().startswith('0X'):
282 PcdValueInImg
= int(Pcd
.DefaultValue
, Base1
)
283 PcdValueInDscOrFdf
= int(DefaultValue
, Base2
)
284 if PcdValueInImg
== PcdValueInDscOrFdf
:
288 # Check the Pcd size and data type
289 if Pcd
.DatumType
== "VOID*":
290 if int(MaxDatumSize
) > int(Pcd
.MaxDatumSize
):
291 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
292 % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, int(MaxDatumSize
) - int(Pcd
.MaxDatumSize
)))
294 if PcdValueInDscOrFdf
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
] \
295 or PcdValueInImg
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
]:
296 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of %s type PCD '%s.%s' doesn't match its data type." \
297 % (Pcd
.DatumType
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
298 self
.PatchPcds
.append((Pcd
, DefaultValue
))
301 self
.PcdIsDriver
= Inf
.PcdIsDriver
302 self
.IsBinaryModule
= Inf
.IsBinaryModule
303 GenFdsGlobalVariable
.VerboseLogger("BaseName : %s" % self
.BaseName
)
304 GenFdsGlobalVariable
.VerboseLogger("ModuleGuid : %s" % self
.ModuleGuid
)
305 GenFdsGlobalVariable
.VerboseLogger("ModuleType : %s" % self
.ModuleType
)
306 GenFdsGlobalVariable
.VerboseLogger("VersionString : %s" % self
.VersionString
)
307 GenFdsGlobalVariable
.VerboseLogger("InfFileName :%s" % self
.InfFileName
)
310 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
313 self
.OutputPath
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, \
314 self
.ModuleGuid
+ self
.BaseName
)
315 if not os
.path
.exists(self
.OutputPath
) :
316 os
.makedirs(self
.OutputPath
)
318 self
.EfiOutputPath
= self
.__GetEFIOutPutPath
__()
319 GenFdsGlobalVariable
.VerboseLogger( "ModuelEFIPath: " + self
.EfiOutputPath
)
323 # Patch EFI file with patch PCD
325 # @param EfiFile: EFI file needs to be patched.
326 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
327 # If passed in file does not end with efi, return as is
329 def PatchEfiFile(self
, EfiFile
, FileType
):
330 if not self
.PatchPcds
:
332 if FileType
!= 'PE32' and self
.ModuleType
!= "USER_DEFINED":
334 if self
.PatchedBinFile
:
335 EdkLogger
.error("GenFds", GENFDS_ERROR
,
336 'Only one binary file can be patched:\n'
337 ' a binary file has been patched: %s\n'
338 ' current file: %s' % (self
.PatchedBinFile
, EfiFile
),
339 File
=self
.InfFileName
)
340 Basename
= os
.path
.basename(EfiFile
)
341 Output
= os
.path
.join(self
.OutputPath
, Basename
)
342 CopyLongFilePath(EfiFile
, Output
)
343 for Pcd
, Value
in self
.PatchPcds
:
344 RetVal
, RetStr
= PatchBinaryFile(Output
, int(Pcd
.Offset
, 0), Pcd
.DatumType
, Value
, Pcd
.MaxDatumSize
)
346 EdkLogger
.error("GenFds", GENFDS_ERROR
, RetStr
, File
=self
.InfFileName
)
347 self
.PatchedBinFile
= os
.path
.normpath(EfiFile
)
353 # @param self The object pointer
354 # @param Dict dictionary contains macro and value pair
355 # @param FvChildAddr Array of the inside FvImage base address
356 # @param FvParentAddr Parent Fv base address
357 # @retval string Generated FFS file name
359 def GenFfs(self
, Dict
= {}, FvChildAddr
= [], FvParentAddr
=None):
361 # Parse Inf file get Module related information
364 self
.__InfParse
__(Dict
)
367 # Allow binary type module not specify override rule in FDF file.
369 if len(self
.BinFileList
) > 0:
370 if self
.Rule
== None or self
.Rule
== "":
374 # Get the rule of how to generate Ffs file
376 Rule
= self
.__GetRule
__()
377 GenFdsGlobalVariable
.VerboseLogger( "Packing binaries from inf file : %s" %self
.InfFileName
)
379 # Convert Fv File Type for PI1.1 SMM driver.
381 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
382 if Rule
.FvFileType
== 'DRIVER':
383 Rule
.FvFileType
= 'SMM'
385 # Framework SMM Driver has no SMM FV file type
387 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
388 if Rule
.FvFileType
== 'SMM' or Rule
.FvFileType
== 'SMM_CORE':
389 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File
=self
.InfFileName
)
391 # For the rule only has simpleFile
393 if isinstance (Rule
, RuleSimpleFile
.RuleSimpleFile
) :
394 SectionOutputList
= self
.__GenSimpleFileSection
__(Rule
)
395 FfsOutput
= self
.__GenSimpleFileFfs
__(Rule
, SectionOutputList
)
398 # For Rule has ComplexFile
400 elif isinstance(Rule
, RuleComplexFile
.RuleComplexFile
):
401 InputSectList
, InputSectAlignments
= self
.__GenComplexFileSection
__(Rule
, FvChildAddr
, FvParentAddr
)
402 FfsOutput
= self
.__GenComplexFileFfs
__(Rule
, InputSectList
, InputSectAlignments
)
406 ## __ExtendMacro__() method
408 # Replace macro with its value
410 # @param self The object pointer
411 # @param String The string to be replaced
412 # @retval string Macro replaced string
414 def __ExtendMacro__ (self
, String
):
416 '$(INF_OUTPUT)' : self
.EfiOutputPath
,
417 '$(MODULE_NAME)' : self
.BaseName
,
418 '$(BUILD_NUMBER)': self
.BuildNum
,
419 '$(INF_VERSION)' : self
.VersionString
,
420 '$(NAMED_GUID)' : self
.ModuleGuid
422 String
= GenFdsGlobalVariable
.MacroExtend(String
, MacroDict
)
425 ## __GetRule__() method
427 # Get correct rule for generating FFS for this INF
429 # @param self The object pointer
430 # @retval Rule Rule object
432 def __GetRule__ (self
) :
434 if self
.CurrentArch
== None:
435 CurrentArchList
= ['common']
437 CurrentArchList
.append(self
.CurrentArch
)
439 for CurrentArch
in CurrentArchList
:
440 RuleName
= 'RULE' + \
442 CurrentArch
.upper() + \
444 self
.ModuleType
.upper()
445 if self
.Rule
!= None:
446 RuleName
= RuleName
+ \
450 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
452 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
455 RuleName
= 'RULE' + \
459 self
.ModuleType
.upper()
461 if self
.Rule
!= None:
462 RuleName
= RuleName
+ \
466 GenFdsGlobalVariable
.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName
, self
.InfFileName
))
468 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
470 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
474 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'Don\'t Find common rule %s for INF %s' \
475 % (RuleName
, self
.InfFileName
))
477 ## __GetPlatformArchList__() method
479 # Get Arch list this INF built under
481 # @param self The object pointer
482 # @retval list Arch list
484 def __GetPlatformArchList__(self
):
486 InfFileKey
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
))
488 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IA32', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
489 if PlatformDataBase
!= None:
490 if InfFileKey
in PlatformDataBase
.Modules
:
491 DscArchList
.append ('IA32')
493 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'X64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
494 if PlatformDataBase
!= None:
495 if InfFileKey
in PlatformDataBase
.Modules
:
496 DscArchList
.append ('X64')
498 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IPF', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
499 if PlatformDataBase
!= None:
500 if InfFileKey
in (PlatformDataBase
.Modules
):
501 DscArchList
.append ('IPF')
503 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'ARM', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
504 if PlatformDataBase
!= None:
505 if InfFileKey
in (PlatformDataBase
.Modules
):
506 DscArchList
.append ('ARM')
508 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'EBC', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
509 if PlatformDataBase
!= None:
510 if InfFileKey
in (PlatformDataBase
.Modules
):
511 DscArchList
.append ('EBC')
513 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'AARCH64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
514 if PlatformDataBase
!= None:
515 if InfFileKey
in (PlatformDataBase
.Modules
):
516 DscArchList
.append ('AARCH64')
520 ## GetCurrentArch() method
522 # Get Arch list of the module from this INF is to be placed into flash
524 # @param self The object pointer
525 # @retval list Arch list
527 def GetCurrentArch(self
) :
529 TargetArchList
= GenFdsGlobalVariable
.ArchList
531 PlatformArchList
= self
.__GetPlatformArchList
__()
533 CurArchList
= TargetArchList
534 if PlatformArchList
!= []:
535 CurArchList
= list(set (TargetArchList
) & set (PlatformArchList
))
536 GenFdsGlobalVariable
.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList
))
539 if self
.KeyStringList
!= []:
540 for Key
in self
.KeyStringList
:
541 Key
= GenFdsGlobalVariable
.MacroExtend(Key
)
542 Target
, Tag
, Arch
= Key
.split('_')
543 if Arch
in CurArchList
:
544 ArchList
.append(Arch
)
545 if Target
not in self
.TargetOverrideList
:
546 self
.TargetOverrideList
.append(Target
)
548 ArchList
= CurArchList
550 UseArchList
= TargetArchList
551 if self
.UseArch
!= None:
553 UseArchList
.append(self
.UseArch
)
554 ArchList
= list(set (UseArchList
) & set (ArchList
))
556 self
.InfFileName
= NormPath(self
.InfFileName
)
557 if len(PlatformArchList
) == 0:
559 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
560 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
562 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
563 if len(ArchList
) == 1:
566 elif len(ArchList
) > 1:
567 if len(PlatformArchList
) == 0:
568 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
))
570 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
))
572 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." \
573 % (self
.InfFileName
, str(PlatformArchList
), GenFdsGlobalVariable
.ActivePlatform
, str(set (UseArchList
) & set (TargetArchList
))))
575 ## __GetEFIOutPutPath__() method
577 # Get the output path for generated files
579 # @param self The object pointer
580 # @retval string Path that output files from this INF go to
582 def __GetEFIOutPutPath__(self
):
585 (ModulePath
, FileName
) = os
.path
.split(self
.InfFileName
)
586 Index
= FileName
.rfind('.')
587 FileName
= FileName
[0:Index
]
588 if self
.OverrideGuid
:
589 FileName
= self
.OverrideGuid
591 if self
.CurrentArch
!= None:
592 Arch
= self
.CurrentArch
594 OutputPath
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
],
600 OutputPath
= os
.path
.realpath(OutputPath
)
603 ## __GenSimpleFileSection__() method
605 # Generate section by specified file name or a list of files with file extension
607 # @param self The object pointer
608 # @param Rule The rule object used to generate section
609 # @retval string File name of the generated section file
611 def __GenSimpleFileSection__(self
, Rule
):
613 # Prepare the parameter of GenSection
617 GenSecInputFile
= None
618 if Rule
.FileName
!= None:
619 GenSecInputFile
= self
.__ExtendMacro
__(Rule
.FileName
)
620 if os
.path
.isabs(GenSecInputFile
):
621 GenSecInputFile
= os
.path
.normpath(GenSecInputFile
)
623 GenSecInputFile
= os
.path
.normpath(os
.path
.join(self
.EfiOutputPath
, GenSecInputFile
))
625 FileList
, IsSect
= Section
.Section
.GetFileList(self
, '', Rule
.FileExtension
)
628 SectionType
= Rule
.SectionType
630 # Convert Fv Section Type for PI1.1 SMM driver.
632 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
633 if SectionType
== 'DXE_DEPEX':
634 SectionType
= 'SMM_DEPEX'
636 # Framework SMM Driver has no SMM_DEPEX section type
638 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
639 if SectionType
== 'SMM_DEPEX':
640 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
642 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
643 if self
.KeepReloc
!= None:
644 NoStrip
= self
.KeepReloc
645 elif Rule
.KeepReloc
!= None:
646 NoStrip
= Rule
.KeepReloc
647 elif self
.ShadowFromInfFile
!= None:
648 NoStrip
= self
.ShadowFromInfFile
651 for File
in FileList
:
654 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
655 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
657 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
658 File
= GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)
660 #Get PE Section alignment when align is set to AUTO
661 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
662 ImageObj
= PeImageClass (File
)
663 if ImageObj
.SectionAlignment
< 0x400:
664 self
.Alignment
= str (ImageObj
.SectionAlignment
)
666 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
669 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
670 if not os
.path
.exists(FileBeforeStrip
) or \
671 (os
.path
.getmtime(File
) > os
.path
.getmtime(FileBeforeStrip
)):
672 CopyLongFilePath(File
, FileBeforeStrip
)
673 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
674 GenFdsGlobalVariable
.GenerateFirmwareImage(
681 if SectionType
== 'TE':
682 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
683 GenFdsGlobalVariable
.GenerateFirmwareImage(
690 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [File
], Section
.Section
.SectionType
[SectionType
])
691 OutputFileList
.append(OutputFile
)
694 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
695 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
696 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
697 GenSecInputFile
= GenFdsGlobalVariable
.MacroExtend(GenSecInputFile
, Dict
, self
.CurrentArch
)
699 #Get PE Section alignment when align is set to AUTO
700 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
701 ImageObj
= PeImageClass (GenSecInputFile
)
702 if ImageObj
.SectionAlignment
< 0x400:
703 self
.Alignment
= str (ImageObj
.SectionAlignment
)
705 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
708 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
709 if not os
.path
.exists(FileBeforeStrip
) or \
710 (os
.path
.getmtime(GenSecInputFile
) > os
.path
.getmtime(FileBeforeStrip
)):
711 CopyLongFilePath(GenSecInputFile
, FileBeforeStrip
)
713 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
714 GenFdsGlobalVariable
.GenerateFirmwareImage(
719 GenSecInputFile
= StrippedFile
721 if SectionType
== 'TE':
722 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
723 GenFdsGlobalVariable
.GenerateFirmwareImage(
728 GenSecInputFile
= TeFile
730 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [GenSecInputFile
], Section
.Section
.SectionType
[SectionType
])
731 OutputFileList
.append(OutputFile
)
733 return OutputFileList
735 ## __GenSimpleFileFfs__() method
739 # @param self The object pointer
740 # @param Rule The rule object used to generate section
741 # @param InputFileList The output file list from GenSection
742 # @retval string Generated FFS file name
744 def __GenSimpleFileFfs__(self
, Rule
, InputFileList
):
745 FfsOutput
= self
.OutputPath
+ \
747 self
.__ExtendMacro
__(Rule
.NameGuid
) + \
750 GenFdsGlobalVariable
.VerboseLogger(self
.__ExtendMacro
__(Rule
.NameGuid
))
752 SectionAlignments
= []
753 for InputFile
in InputFileList
:
754 InputSection
.append(InputFile
)
755 SectionAlignments
.append(Rule
.SectAlignment
)
757 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
758 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
759 if len(PcdValue
) == 0:
760 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
762 if PcdValue
.startswith('{'):
763 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
764 RegistryGuidStr
= PcdValue
765 if len(RegistryGuidStr
) == 0:
766 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
768 self
.ModuleGuid
= RegistryGuidStr
770 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputSection
,
771 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
772 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
773 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
774 SectionAlign
=SectionAlignments
778 ## __GenComplexFileSection__() method
780 # Generate section by sections in Rule
782 # @param self The object pointer
783 # @param Rule The rule object used to generate section
784 # @param FvChildAddr Array of the inside FvImage base address
785 # @param FvParentAddr Parent Fv base address
786 # @retval string File name of the generated section file
788 def __GenComplexFileSection__(self
, Rule
, FvChildAddr
, FvParentAddr
):
789 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
790 if Rule
.KeepReloc
!= None:
791 self
.KeepRelocFromRule
= Rule
.KeepReloc
795 HasGneratedFlag
= False
796 if self
.PcdIsDriver
== 'PEI_PCD_DRIVER':
797 if self
.IsBinaryModule
:
798 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "PEIPcdDataBase.raw")
800 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "PEIPcdDataBase.raw")
801 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "PEIPcdDataBaseSec.raw")
802 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
806 SectFiles
.append(PcdExDbSecName
)
807 SectAlignments
.append(None)
808 elif self
.PcdIsDriver
== 'DXE_PCD_DRIVER':
809 if self
.IsBinaryModule
:
810 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "DXEPcdDataBase.raw")
812 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "DXEPcdDataBase.raw")
813 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "DXEPcdDataBaseSec.raw")
814 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
818 SectFiles
.append(PcdExDbSecName
)
819 SectAlignments
.append(None)
820 for Sect
in Rule
.SectionList
:
821 SecIndex
= '%d' %Index
824 # Convert Fv Section Type for PI1.1 SMM driver.
826 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
827 if Sect
.SectionType
== 'DXE_DEPEX':
828 Sect
.SectionType
= 'SMM_DEPEX'
830 # Framework SMM Driver has no SMM_DEPEX section type
832 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
833 if Sect
.SectionType
== 'SMM_DEPEX':
834 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
836 # process the inside FvImage from FvSection or GuidSection
838 if FvChildAddr
!= []:
839 if isinstance(Sect
, FvImageSection
):
840 Sect
.FvAddr
= FvChildAddr
.pop(0)
841 elif isinstance(Sect
, GuidSection
):
842 Sect
.FvAddr
= FvChildAddr
843 if FvParentAddr
!= None and isinstance(Sect
, GuidSection
):
844 Sect
.FvParentAddr
= FvParentAddr
846 if Rule
.KeyStringList
!= []:
847 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, Rule
.KeyStringList
, self
)
849 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, self
.KeyStringList
, self
)
851 if not HasGneratedFlag
:
852 UniVfrOffsetFileSection
= ""
853 ModuleFileName
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
)
854 InfData
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClass(ModuleFileName
), self
.CurrentArch
]
856 # Search the source list in InfData to find if there are .vfr file exist.
859 VfrUniOffsetList
= []
860 for SourceFile
in InfData
.Sources
:
861 if SourceFile
.Type
.upper() == ".VFR" :
863 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
865 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
866 if SourceFile
.Type
.upper() == ".UNI" :
868 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
870 VfrUniBaseName
["UniOffsetName"] = (self
.BaseName
+ "Strings")
873 if len(VfrUniBaseName
) > 0:
874 VfrUniOffsetList
= self
.__GetBuildOutputMapFileVfrUniInfo
(VfrUniBaseName
)
876 # Generate the Raw data of raw section
878 os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
879 UniVfrOffsetFileName
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
880 UniVfrOffsetFileSection
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ 'Offset' + '.raw')
882 self
.__GenUniVfrOffsetFile
(VfrUniOffsetList
, UniVfrOffsetFileName
)
884 UniVfrOffsetFileNameList
= []
885 UniVfrOffsetFileNameList
.append(UniVfrOffsetFileName
)
886 """Call GenSection"""
887 GenFdsGlobalVariable
.GenerateSection(UniVfrOffsetFileSection
,
888 UniVfrOffsetFileNameList
,
891 os
.remove(UniVfrOffsetFileName
)
892 SectList
.append(UniVfrOffsetFileSection
)
893 HasGneratedFlag
= True
895 for SecName
in SectList
:
896 SectFiles
.append(SecName
)
897 SectAlignments
.append(Align
)
899 return SectFiles
, SectAlignments
901 ## __GenComplexFileFfs__() method
905 # @param self The object pointer
906 # @param Rule The rule object used to generate section
907 # @param InputFileList The output file list from GenSection
908 # @retval string Generated FFS file name
910 def __GenComplexFileFfs__(self
, Rule
, InputFile
, Alignments
):
912 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
913 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
914 if len(PcdValue
) == 0:
915 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
917 if PcdValue
.startswith('{'):
918 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
919 RegistryGuidStr
= PcdValue
920 if len(RegistryGuidStr
) == 0:
921 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
923 self
.ModuleGuid
= RegistryGuidStr
925 FfsOutput
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
926 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputFile
,
927 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
928 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
929 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
930 SectionAlign
=Alignments
934 ## __GetGenFfsCmdParameter__() method
936 # Create parameter string for GenFfs
938 # @param self The object pointer
939 # @param Rule The rule object used to generate section
940 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
942 def __GetGenFfsCmdParameter__(self
, Rule
):
944 result
+= ('-t', Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
])
945 if Rule
.Fixed
!= False:
947 if Rule
.CheckSum
!= False:
950 if Rule
.Alignment
!= None and Rule
.Alignment
!= '':
951 result
+= ('-a', Rule
.Alignment
)
955 ## __GetBuildOutputMapFileVfrUniInfo() method
957 # Find the offset of UNI/INF object offset in the EFI image file.
959 # @param self The object pointer
960 # @param VfrUniBaseName A name list contain the UNI/INF object name.
961 # @retval RetValue A list contain offset of UNI/INF object.
963 def __GetBuildOutputMapFileVfrUniInfo(self
, VfrUniBaseName
):
967 MapFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".map")
969 fInputfile
= open(MapFileName
, "r", 0)
971 FileLinesList
= fInputfile
.readlines()
973 EdkLogger
.error("GenFds", FILE_READ_FAILURE
, "File read failed for %s" %MapFileName
,None)
977 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %MapFileName
,None)
980 for eachLine
in FileLinesList
:
981 for eachName
in VfrUniBaseName
.values():
982 if eachLine
.find(eachName
) != -1:
983 eachLine
= eachLine
.strip()
984 Element
= eachLine
.split()
986 # MSFT/ICC/EBC map file
988 if (len(Element
) == 4):
996 RetValue
.append((eachName
, Element
[2]))
1001 elif (len(Element
) == 2) and Element
[0].startswith("0x"):
1002 RetValue
.append((eachName
, Element
[0]))
1006 ## __GenUniVfrOffsetFile() method
1008 # Generate the offset file for the module which contain VFR or UNI file.
1010 # @param self The object pointer
1011 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
1012 # @param UniVfrOffsetFileName The output offset file name.
1014 def __GenUniVfrOffsetFile(self
, VfrUniOffsetList
, UniVfrOffsetFileName
):
1017 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
1019 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %UniVfrOffsetFileName
,None)
1021 # Use a instance of StringIO to cache data
1022 fStringIO
= StringIO
.StringIO('')
1024 for Item
in VfrUniOffsetList
:
1025 if (Item
[0].find("Strings") != -1):
1027 # UNI offset in image.
1029 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1031 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
1032 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
1033 fStringIO
.write(''.join(UniGuid
))
1034 UniValue
= pack ('Q', int (Item
[1], 16))
1035 fStringIO
.write (UniValue
)
1038 # VFR binary offset in image.
1040 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1042 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
1043 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
1044 fStringIO
.write(''.join(VfrGuid
))
1046 VfrValue
= pack ('Q', int (Item
[1], 16))
1047 fStringIO
.write (VfrValue
)
1050 # write data into file.
1053 fInputfile
.write (fStringIO
.getvalue())
1055 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)