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
import EdkLogger
34 from Common
.BuildToolError
import *
35 from GuidSection
import GuidSection
36 from FvImageSection
import FvImageSection
37 from Common
.Misc
import PeImageClass
38 from AutoGen
.GenDepex
import DependencyExpression
39 from PatchPcdValue
.PatchPcdValue
import PatchBinaryFile
40 from Common
.LongFilePathSupport
import CopyLongFilePath
41 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
43 ## generate FFS from INF
46 class FfsInfStatement(FfsInfStatementClassObject
):
47 ## The mapping dictionary from datum type to its maximum number.
48 _MAX_SIZE_TYPE
= {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}
51 # @param self The object pointer
54 FfsInfStatementClassObject
.__init
__(self
)
55 self
.TargetOverrideList
= []
56 self
.ShadowFromInfFile
= None
57 self
.KeepRelocFromRule
= None
60 self
.PiSpecVersion
= '0x00000000'
62 self
.FinalTargetSuffixMap
= {}
63 self
.CurrentLineNum
= None
64 self
.CurrentLineContent
= None
66 self
.InfFileName
= None
68 ## GetFinalTargetSuffixMap() method
70 # Get final build target list
71 def GetFinalTargetSuffixMap(self
):
72 if not self
.InfModule
or not self
.CurrentArch
:
74 if not self
.FinalTargetSuffixMap
:
75 FinalBuildTargetList
= GenFdsGlobalVariable
.GetModuleCodaTargetList(self
.InfModule
, self
.CurrentArch
)
76 for File
in FinalBuildTargetList
:
77 self
.FinalTargetSuffixMap
.setdefault(os
.path
.splitext(File
)[1], []).append(File
)
79 # Check if current INF module has DEPEX
80 if '.depex' not in self
.FinalTargetSuffixMap
and self
.InfModule
.ModuleType
!= "USER_DEFINED" \
81 and not self
.InfModule
.DxsFile
and not self
.InfModule
.LibraryClass
:
82 ModuleType
= self
.InfModule
.ModuleType
83 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
85 if ModuleType
!= DataType
.SUP_MODULE_USER_DEFINED
:
86 for LibraryClass
in PlatformDataBase
.LibraryClasses
.GetKeys():
87 if LibraryClass
.startswith("NULL") and PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]:
88 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]
90 StrModule
= str(self
.InfModule
)
92 if StrModule
in PlatformDataBase
.Modules
:
93 PlatformModule
= PlatformDataBase
.Modules
[StrModule
]
94 for LibraryClass
in PlatformModule
.LibraryClasses
:
95 if LibraryClass
.startswith("NULL"):
96 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
98 DependencyList
= [self
.InfModule
]
101 while len(DependencyList
) > 0:
102 Module
= DependencyList
.pop(0)
105 for Dep
in Module
.Depex
[self
.CurrentArch
, ModuleType
]:
107 DepexList
.append('AND')
108 DepexList
.append('(')
109 DepexList
.extend(Dep
)
110 if DepexList
[-1] == 'END': # no need of a END at this time
112 DepexList
.append(')')
113 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
115 for LibName
in Module
.LibraryClasses
:
116 if LibName
in LibraryInstance
:
118 if PlatformModule
and LibName
in PlatformModule
.LibraryClasses
:
119 LibraryPath
= PlatformModule
.LibraryClasses
[LibName
]
121 LibraryPath
= PlatformDataBase
.LibraryClasses
[LibName
, ModuleType
]
123 LibraryPath
= Module
.LibraryClasses
[LibName
]
126 LibraryModule
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[LibraryPath
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
127 LibraryInstance
[LibName
] = LibraryModule
128 DependencyList
.append(LibraryModule
)
130 Dpx
= DependencyExpression(DepexList
, ModuleType
, True)
131 if len(Dpx
.PostfixNotation
) != 0:
132 # It means this module has DEPEX
133 self
.FinalTargetSuffixMap
['.depex'] = [os
.path
.join(self
.EfiOutputPath
, self
.BaseName
) + '.depex']
134 return self
.FinalTargetSuffixMap
136 ## __InfParse() method
138 # Parse inf file to get module information
140 # @param self The object pointer
141 # @param Dict dictionary contains macro and value pair
143 def __InfParse__(self
, Dict
= {}):
145 GenFdsGlobalVariable
.VerboseLogger( " Begine parsing INf file : %s" %self
.InfFileName
)
147 self
.InfFileName
= self
.InfFileName
.replace('$(WORKSPACE)', '')
148 if self
.InfFileName
[0] == '\\' or self
.InfFileName
[0] == '/' :
149 self
.InfFileName
= self
.InfFileName
[1:]
151 if self
.InfFileName
.find('$') == -1:
152 InfPath
= NormPath(self
.InfFileName
)
153 if not os
.path
.exists(InfPath
):
154 InfPath
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(InfPath
)
155 if not os
.path
.exists(InfPath
):
156 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Non-existant Module %s !" % (self
.InfFileName
))
158 self
.CurrentArch
= self
.GetCurrentArch()
160 # Get the InfClass object
163 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
164 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
166 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
168 if self
.CurrentArch
!= None:
170 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
172 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
174 self
.BaseName
= Inf
.BaseName
175 self
.ModuleGuid
= Inf
.Guid
176 self
.ModuleType
= Inf
.ModuleType
177 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
178 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
179 if Inf
.AutoGenVersion
< 0x00010005:
180 self
.ModuleType
= Inf
.ComponentType
181 self
.VersionString
= Inf
.Version
182 self
.BinFileList
= Inf
.Binaries
183 self
.SourceFileList
= Inf
.Sources
184 if self
.KeepReloc
== None and Inf
.Shadow
:
185 self
.ShadowFromInfFile
= Inf
.Shadow
188 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
189 self
.BaseName
= Inf
.BaseName
190 self
.ModuleGuid
= Inf
.Guid
191 self
.ModuleType
= Inf
.ModuleType
192 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
193 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
194 self
.VersionString
= Inf
.Version
195 self
.BinFileList
= Inf
.Binaries
196 self
.SourceFileList
= Inf
.Sources
197 if self
.BinFileList
== []:
198 EdkLogger
.error("GenFds", GENFDS_ERROR
,
199 "INF %s specified in FDF could not be found in build ARCH %s!" \
200 % (self
.InfFileName
, GenFdsGlobalVariable
.ArchList
))
202 if len(self
.SourceFileList
) != 0 and not self
.InDsc
:
203 EdkLogger
.warn("GenFds", GENFDS_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % (self
.InfFileName
))
205 if self
.ModuleType
== 'SMM_CORE' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
206 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
)
208 if Inf
._Defs
!= None and len(Inf
._Defs
) > 0:
209 self
.OptRomDefs
.update(Inf
._Defs
)
213 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
214 FdfPcdDict
= GenFdsGlobalVariable
.FdfParser
.Profile
.PcdDict
216 # Workaround here: both build and GenFds tool convert the workspace path to lower case
217 # But INF file path in FDF and DSC file may have real case characters.
218 # Try to convert the path to lower case to see if PCDs value are override by DSC.
220 for DscModule
in Platform
.Modules
:
221 DscModules
[str(DscModule
).lower()] = Platform
.Modules
[DscModule
]
222 for PcdKey
in InfPcds
:
223 Pcd
= InfPcds
[PcdKey
]
224 if not hasattr(Pcd
, 'Offset'):
226 if Pcd
.Type
!= 'PatchableInModule':
228 # Override Patchable PCD value by the value from DSC
230 InfLowerPath
= str(PathClassObj
).lower()
231 if InfLowerPath
in DscModules
and PcdKey
in DscModules
[InfLowerPath
].Pcds
:
232 PatchPcd
= DscModules
[InfLowerPath
].Pcds
[PcdKey
]
233 elif PcdKey
in Platform
.Pcds
:
234 PatchPcd
= Platform
.Pcds
[PcdKey
]
236 if PatchPcd
and Pcd
.Type
== PatchPcd
.Type
:
237 DefaultValue
= PatchPcd
.DefaultValue
240 # Override Patchable PCD value by the value from FDF
242 if PcdKey
in FdfPcdDict
:
243 DefaultValue
= FdfPcdDict
[PcdKey
]
246 if not DscOverride
and not FdfOverride
:
248 # Check value, if value are equal, no need to patch
249 if Pcd
.DatumType
== "VOID*":
250 if Pcd
.DefaultValue
== DefaultValue
or DefaultValue
in [None, '']:
252 # Get the string size from FDF or DSC
253 if DefaultValue
[0] == 'L':
254 # Remove L"", but the '\0' must be appended
255 MaxDatumSize
= str((len(DefaultValue
) - 2) * 2)
256 elif DefaultValue
[0] == '{':
257 MaxDatumSize
= str(len(DefaultValue
.split(',')))
259 MaxDatumSize
= str(len(DefaultValue
) - 1)
261 Pcd
.MaxDatumSize
= PatchPcd
.MaxDatumSize
262 # If no defined the maximum size in DSC, try to get current size from INF
263 if Pcd
.MaxDatumSize
in ['', None]:
264 Pcd
.MaxDatumSize
= str(len(Pcd
.DefaultValue
.split(',')))
267 if Pcd
.DefaultValue
.upper().startswith('0X'):
269 if DefaultValue
.upper().startswith('0X'):
272 PcdValueInImg
= int(Pcd
.DefaultValue
, Base1
)
273 PcdValueInDscOrFdf
= int(DefaultValue
, Base2
)
274 if PcdValueInImg
== PcdValueInDscOrFdf
:
278 # Check the Pcd size and data type
279 if Pcd
.DatumType
== "VOID*":
280 if int(MaxDatumSize
) > int(Pcd
.MaxDatumSize
):
281 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
282 % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, int(MaxDatumSize
) - int(Pcd
.MaxDatumSize
)))
284 if PcdValueInDscOrFdf
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
] \
285 or PcdValueInImg
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
]:
286 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of %s type PCD '%s.%s' doesn't match its data type." \
287 % (Pcd
.DatumType
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
288 Pcd
.DefaultValue
= DefaultValue
289 self
.PatchPcds
.append(Pcd
)
291 self
.PcdIsDriver
= Inf
.PcdIsDriver
292 self
.IsBinaryModule
= Inf
.IsBinaryModule
293 GenFdsGlobalVariable
.VerboseLogger("BaseName : %s" % self
.BaseName
)
294 GenFdsGlobalVariable
.VerboseLogger("ModuleGuid : %s" % self
.ModuleGuid
)
295 GenFdsGlobalVariable
.VerboseLogger("ModuleType : %s" % self
.ModuleType
)
296 GenFdsGlobalVariable
.VerboseLogger("VersionString : %s" % self
.VersionString
)
297 GenFdsGlobalVariable
.VerboseLogger("InfFileName :%s" % self
.InfFileName
)
300 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
303 self
.OutputPath
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, \
304 self
.ModuleGuid
+ self
.BaseName
)
305 if not os
.path
.exists(self
.OutputPath
) :
306 os
.makedirs(self
.OutputPath
)
308 self
.EfiOutputPath
= self
.__GetEFIOutPutPath
__()
309 GenFdsGlobalVariable
.VerboseLogger( "ModuelEFIPath: " + self
.EfiOutputPath
)
313 # Patch EFI file with patch PCD
315 # @param EfiFile: EFI file needs to be patched.
316 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
317 # If passed in file does not end with efi, return as is
319 def PatchEfiFile(self
, EfiFile
):
320 if os
.path
.splitext(EfiFile
)[1].lower() != '.efi':
322 if not self
.PatchPcds
:
324 Basename
= os
.path
.basename(EfiFile
)
325 Output
= os
.path
.join(self
.OutputPath
, Basename
)
326 CopyLongFilePath(EfiFile
, Output
)
327 for Pcd
in self
.PatchPcds
:
328 RetVal
, RetStr
= PatchBinaryFile(Output
, int(Pcd
.Offset
, 0), Pcd
.DatumType
, Pcd
.DefaultValue
, Pcd
.MaxDatumSize
)
330 EdkLogger
.error("GenFds", GENFDS_ERROR
, RetStr
, File
=self
.InfFileName
)
336 # @param self The object pointer
337 # @param Dict dictionary contains macro and value pair
338 # @param FvChildAddr Array of the inside FvImage base address
339 # @param FvParentAddr Parent Fv base address
340 # @retval string Generated FFS file name
342 def GenFfs(self
, Dict
= {}, FvChildAddr
= [], FvParentAddr
=None):
344 # Parse Inf file get Module related information
347 self
.__InfParse
__(Dict
)
350 # Allow binary type module not specify override rule in FDF file.
352 if len(self
.BinFileList
) >0 and not self
.InDsc
:
353 if self
.Rule
== None or self
.Rule
== "":
357 # Get the rule of how to generate Ffs file
359 Rule
= self
.__GetRule
__()
360 GenFdsGlobalVariable
.VerboseLogger( "Packing binaries from inf file : %s" %self
.InfFileName
)
362 # Convert Fv File Type for PI1.1 SMM driver.
364 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
365 if Rule
.FvFileType
== 'DRIVER':
366 Rule
.FvFileType
= 'SMM'
368 # Framework SMM Driver has no SMM FV file type
370 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
371 if Rule
.FvFileType
== 'SMM' or Rule
.FvFileType
== 'SMM_CORE':
372 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File
=self
.InfFileName
)
374 # For the rule only has simpleFile
376 if isinstance (Rule
, RuleSimpleFile
.RuleSimpleFile
) :
377 SectionOutputList
= self
.__GenSimpleFileSection
__(Rule
)
378 FfsOutput
= self
.__GenSimpleFileFfs
__(Rule
, SectionOutputList
)
381 # For Rule has ComplexFile
383 elif isinstance(Rule
, RuleComplexFile
.RuleComplexFile
):
384 InputSectList
, InputSectAlignments
= self
.__GenComplexFileSection
__(Rule
, FvChildAddr
, FvParentAddr
)
385 FfsOutput
= self
.__GenComplexFileFfs
__(Rule
, InputSectList
, InputSectAlignments
)
389 ## __ExtendMacro__() method
391 # Replace macro with its value
393 # @param self The object pointer
394 # @param String The string to be replaced
395 # @retval string Macro replaced string
397 def __ExtendMacro__ (self
, String
):
399 '$(INF_OUTPUT)' : self
.EfiOutputPath
,
400 '$(MODULE_NAME)' : self
.BaseName
,
401 '$(BUILD_NUMBER)': self
.BuildNum
,
402 '$(INF_VERSION)' : self
.VersionString
,
403 '$(NAMED_GUID)' : self
.ModuleGuid
405 String
= GenFdsGlobalVariable
.MacroExtend(String
, MacroDict
)
408 ## __GetRule__() method
410 # Get correct rule for generating FFS for this INF
412 # @param self The object pointer
413 # @retval Rule Rule object
415 def __GetRule__ (self
) :
417 if self
.CurrentArch
== None:
418 CurrentArchList
= ['common']
420 CurrentArchList
.append(self
.CurrentArch
)
422 for CurrentArch
in CurrentArchList
:
423 RuleName
= 'RULE' + \
425 CurrentArch
.upper() + \
427 self
.ModuleType
.upper()
428 if self
.Rule
!= None:
429 RuleName
= RuleName
+ \
433 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
435 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
438 RuleName
= 'RULE' + \
442 self
.ModuleType
.upper()
444 if self
.Rule
!= None:
445 RuleName
= RuleName
+ \
449 GenFdsGlobalVariable
.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName
, self
.InfFileName
))
451 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
453 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
457 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'Don\'t Find common rule %s for INF %s' \
458 % (RuleName
, self
.InfFileName
))
460 ## __GetPlatformArchList__() method
462 # Get Arch list this INF built under
464 # @param self The object pointer
465 # @retval list Arch list
467 def __GetPlatformArchList__(self
):
469 InfFileKey
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
))
471 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IA32', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
472 if PlatformDataBase
!= None:
473 if InfFileKey
in PlatformDataBase
.Modules
:
474 DscArchList
.append ('IA32')
476 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'X64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
477 if PlatformDataBase
!= None:
478 if InfFileKey
in PlatformDataBase
.Modules
:
479 DscArchList
.append ('X64')
481 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IPF', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
482 if PlatformDataBase
!= None:
483 if InfFileKey
in (PlatformDataBase
.Modules
):
484 DscArchList
.append ('IPF')
486 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'ARM', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
487 if PlatformDataBase
!= None:
488 if InfFileKey
in (PlatformDataBase
.Modules
):
489 DscArchList
.append ('ARM')
491 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'EBC', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
492 if PlatformDataBase
!= None:
493 if InfFileKey
in (PlatformDataBase
.Modules
):
494 DscArchList
.append ('EBC')
496 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'AARCH64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
497 if PlatformDataBase
!= None:
498 if InfFileKey
in (PlatformDataBase
.Modules
):
499 DscArchList
.append ('AARCH64')
503 ## GetCurrentArch() method
505 # Get Arch list of the module from this INF is to be placed into flash
507 # @param self The object pointer
508 # @retval list Arch list
510 def GetCurrentArch(self
) :
512 TargetArchList
= GenFdsGlobalVariable
.ArchList
514 PlatformArchList
= self
.__GetPlatformArchList
__()
516 CurArchList
= TargetArchList
517 if PlatformArchList
!= []:
518 CurArchList
= list(set (TargetArchList
) & set (PlatformArchList
))
519 GenFdsGlobalVariable
.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList
))
522 if self
.KeyStringList
!= []:
523 for Key
in self
.KeyStringList
:
524 Key
= GenFdsGlobalVariable
.MacroExtend(Key
)
525 Target
, Tag
, Arch
= Key
.split('_')
526 if Arch
in CurArchList
:
527 ArchList
.append(Arch
)
528 if Target
not in self
.TargetOverrideList
:
529 self
.TargetOverrideList
.append(Target
)
531 ArchList
= CurArchList
533 UseArchList
= TargetArchList
534 if self
.UseArch
!= None:
536 UseArchList
.append(self
.UseArch
)
537 ArchList
= list(set (UseArchList
) & set (ArchList
))
539 self
.InfFileName
= NormPath(self
.InfFileName
)
540 if len(PlatformArchList
) == 0:
542 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
543 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
545 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
546 if len(ArchList
) == 1:
549 elif len(ArchList
) > 1:
550 if len(PlatformArchList
) == 0:
551 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
))
553 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
))
555 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." \
556 % (self
.InfFileName
, str(PlatformArchList
), GenFdsGlobalVariable
.ActivePlatform
, str(set (UseArchList
) & set (TargetArchList
))))
558 ## __GetEFIOutPutPath__() method
560 # Get the output path for generated files
562 # @param self The object pointer
563 # @retval string Path that output files from this INF go to
565 def __GetEFIOutPutPath__(self
):
568 (ModulePath
, FileName
) = os
.path
.split(self
.InfFileName
)
569 Index
= FileName
.rfind('.')
570 FileName
= FileName
[0:Index
]
572 if self
.CurrentArch
!= None:
573 Arch
= self
.CurrentArch
575 OutputPath
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
],
581 OutputPath
= os
.path
.realpath(OutputPath
)
584 ## __GenSimpleFileSection__() method
586 # Generate section by specified file name or a list of files with file extension
588 # @param self The object pointer
589 # @param Rule The rule object used to generate section
590 # @retval string File name of the generated section file
592 def __GenSimpleFileSection__(self
, Rule
):
594 # Prepare the parameter of GenSection
598 GenSecInputFile
= None
599 if Rule
.FileName
!= None:
600 GenSecInputFile
= self
.__ExtendMacro
__(Rule
.FileName
)
601 if os
.path
.isabs(GenSecInputFile
):
602 GenSecInputFile
= os
.path
.normpath(GenSecInputFile
)
604 GenSecInputFile
= os
.path
.normpath(os
.path
.join(self
.EfiOutputPath
, GenSecInputFile
))
606 FileList
, IsSect
= Section
.Section
.GetFileList(self
, '', Rule
.FileExtension
)
609 SectionType
= Rule
.SectionType
611 # Convert Fv Section Type for PI1.1 SMM driver.
613 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
614 if SectionType
== 'DXE_DEPEX':
615 SectionType
= 'SMM_DEPEX'
617 # Framework SMM Driver has no SMM_DEPEX section type
619 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
620 if SectionType
== 'SMM_DEPEX':
621 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
623 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
624 if self
.KeepReloc
!= None:
625 NoStrip
= self
.KeepReloc
626 elif Rule
.KeepReloc
!= None:
627 NoStrip
= Rule
.KeepReloc
628 elif self
.ShadowFromInfFile
!= None:
629 NoStrip
= self
.ShadowFromInfFile
632 for File
in FileList
:
635 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
636 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
638 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
639 File
= GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)
641 #Get PE Section alignment when align is set to AUTO
642 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
643 ImageObj
= PeImageClass (File
)
644 if ImageObj
.SectionAlignment
< 0x400:
645 self
.Alignment
= str (ImageObj
.SectionAlignment
)
647 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
650 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
651 if not os
.path
.exists(FileBeforeStrip
) or \
652 (os
.path
.getmtime(File
) > os
.path
.getmtime(FileBeforeStrip
)):
653 CopyLongFilePath(File
, FileBeforeStrip
)
654 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
655 GenFdsGlobalVariable
.GenerateFirmwareImage(
662 if SectionType
== 'TE':
663 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
664 GenFdsGlobalVariable
.GenerateFirmwareImage(
671 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [File
], Section
.Section
.SectionType
[SectionType
])
672 OutputFileList
.append(OutputFile
)
675 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
676 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
677 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
678 GenSecInputFile
= GenFdsGlobalVariable
.MacroExtend(GenSecInputFile
, Dict
, self
.CurrentArch
)
680 #Get PE Section alignment when align is set to AUTO
681 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
682 ImageObj
= PeImageClass (GenSecInputFile
)
683 if ImageObj
.SectionAlignment
< 0x400:
684 self
.Alignment
= str (ImageObj
.SectionAlignment
)
686 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
689 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
690 if not os
.path
.exists(FileBeforeStrip
) or \
691 (os
.path
.getmtime(GenSecInputFile
) > os
.path
.getmtime(FileBeforeStrip
)):
692 CopyLongFilePath(GenSecInputFile
, FileBeforeStrip
)
694 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
695 GenFdsGlobalVariable
.GenerateFirmwareImage(
700 GenSecInputFile
= StrippedFile
702 if SectionType
== 'TE':
703 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
704 GenFdsGlobalVariable
.GenerateFirmwareImage(
709 GenSecInputFile
= TeFile
711 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [GenSecInputFile
], Section
.Section
.SectionType
[SectionType
])
712 OutputFileList
.append(OutputFile
)
714 return OutputFileList
716 ## __GenSimpleFileFfs__() method
720 # @param self The object pointer
721 # @param Rule The rule object used to generate section
722 # @param InputFileList The output file list from GenSection
723 # @retval string Generated FFS file name
725 def __GenSimpleFileFfs__(self
, Rule
, InputFileList
):
726 FfsOutput
= self
.OutputPath
+ \
728 self
.__ExtendMacro
__(Rule
.NameGuid
) + \
731 GenFdsGlobalVariable
.VerboseLogger(self
.__ExtendMacro
__(Rule
.NameGuid
))
733 SectionAlignments
= []
734 for InputFile
in InputFileList
:
735 InputSection
.append(InputFile
)
736 SectionAlignments
.append(Rule
.SectAlignment
)
738 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
739 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
740 if len(PcdValue
) == 0:
741 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
743 if PcdValue
.startswith('{'):
744 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
745 RegistryGuidStr
= PcdValue
746 if len(RegistryGuidStr
) == 0:
747 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
749 self
.ModuleGuid
= RegistryGuidStr
751 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputSection
,
752 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
753 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
754 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
755 SectionAlign
=SectionAlignments
759 ## __GenComplexFileSection__() method
761 # Generate section by sections in Rule
763 # @param self The object pointer
764 # @param Rule The rule object used to generate section
765 # @param FvChildAddr Array of the inside FvImage base address
766 # @param FvParentAddr Parent Fv base address
767 # @retval string File name of the generated section file
769 def __GenComplexFileSection__(self
, Rule
, FvChildAddr
, FvParentAddr
):
770 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
771 if Rule
.KeepReloc
!= None:
772 self
.KeepRelocFromRule
= Rule
.KeepReloc
776 HasGneratedFlag
= False
777 if self
.PcdIsDriver
== 'PEI_PCD_DRIVER':
778 if self
.IsBinaryModule
:
779 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "PEIPcdDataBase.raw")
781 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "PEIPcdDataBase.raw")
782 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "PEIPcdDataBaseSec.raw")
783 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
787 SectFiles
.append(PcdExDbSecName
)
788 SectAlignments
.append(None)
789 elif self
.PcdIsDriver
== 'DXE_PCD_DRIVER':
790 if self
.IsBinaryModule
:
791 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "DXEPcdDataBase.raw")
793 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "DXEPcdDataBase.raw")
794 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "DXEPcdDataBaseSec.raw")
795 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
799 SectFiles
.append(PcdExDbSecName
)
800 SectAlignments
.append(None)
801 for Sect
in Rule
.SectionList
:
802 SecIndex
= '%d' %Index
805 # Convert Fv Section Type for PI1.1 SMM driver.
807 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
808 if Sect
.SectionType
== 'DXE_DEPEX':
809 Sect
.SectionType
= 'SMM_DEPEX'
811 # Framework SMM Driver has no SMM_DEPEX section type
813 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
814 if Sect
.SectionType
== 'SMM_DEPEX':
815 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
817 # process the inside FvImage from FvSection or GuidSection
819 if FvChildAddr
!= []:
820 if isinstance(Sect
, FvImageSection
):
821 Sect
.FvAddr
= FvChildAddr
.pop(0)
822 elif isinstance(Sect
, GuidSection
):
823 Sect
.FvAddr
= FvChildAddr
824 if FvParentAddr
!= None and isinstance(Sect
, GuidSection
):
825 Sect
.FvParentAddr
= FvParentAddr
827 if Rule
.KeyStringList
!= []:
828 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, Rule
.KeyStringList
, self
)
830 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, self
.KeyStringList
, self
)
832 if not HasGneratedFlag
:
833 UniVfrOffsetFileSection
= ""
834 ModuleFileName
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
)
835 InfData
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClass(ModuleFileName
), self
.CurrentArch
]
837 # Search the source list in InfData to find if there are .vfr file exist.
840 VfrUniOffsetList
= []
841 for SourceFile
in InfData
.Sources
:
842 if SourceFile
.Type
.upper() == ".VFR" :
844 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
846 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
847 if SourceFile
.Type
.upper() == ".UNI" :
849 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
851 VfrUniBaseName
["UniOffsetName"] = (self
.BaseName
+ "Strings")
854 if len(VfrUniBaseName
) > 0:
855 VfrUniOffsetList
= self
.__GetBuildOutputMapFileVfrUniInfo
(VfrUniBaseName
)
857 # Generate the Raw data of raw section
859 os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
860 UniVfrOffsetFileName
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
861 UniVfrOffsetFileSection
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ 'Offset' + '.raw')
863 self
.__GenUniVfrOffsetFile
(VfrUniOffsetList
, UniVfrOffsetFileName
)
865 UniVfrOffsetFileNameList
= []
866 UniVfrOffsetFileNameList
.append(UniVfrOffsetFileName
)
867 """Call GenSection"""
868 GenFdsGlobalVariable
.GenerateSection(UniVfrOffsetFileSection
,
869 UniVfrOffsetFileNameList
,
872 os
.remove(UniVfrOffsetFileName
)
873 SectList
.append(UniVfrOffsetFileSection
)
874 HasGneratedFlag
= True
876 for SecName
in SectList
:
877 SectFiles
.append(SecName
)
878 SectAlignments
.append(Align
)
880 return SectFiles
, SectAlignments
882 ## __GenComplexFileFfs__() method
886 # @param self The object pointer
887 # @param Rule The rule object used to generate section
888 # @param InputFileList The output file list from GenSection
889 # @retval string Generated FFS file name
891 def __GenComplexFileFfs__(self
, Rule
, InputFile
, Alignments
):
893 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
894 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
895 if len(PcdValue
) == 0:
896 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
898 if PcdValue
.startswith('{'):
899 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
900 RegistryGuidStr
= PcdValue
901 if len(RegistryGuidStr
) == 0:
902 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
904 self
.ModuleGuid
= RegistryGuidStr
906 FfsOutput
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
907 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputFile
,
908 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
909 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
910 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
911 SectionAlign
=Alignments
915 ## __GetGenFfsCmdParameter__() method
917 # Create parameter string for GenFfs
919 # @param self The object pointer
920 # @param Rule The rule object used to generate section
921 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
923 def __GetGenFfsCmdParameter__(self
, Rule
):
925 result
+= ('-t', Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
])
926 if Rule
.Fixed
!= False:
928 if Rule
.CheckSum
!= False:
931 if Rule
.Alignment
!= None and Rule
.Alignment
!= '':
932 result
+= ('-a', Rule
.Alignment
)
936 ## __GetBuildOutputMapFileVfrUniInfo() method
938 # Find the offset of UNI/INF object offset in the EFI image file.
940 # @param self The object pointer
941 # @param VfrUniBaseName A name list contain the UNI/INF object name.
942 # @retval RetValue A list contain offset of UNI/INF object.
944 def __GetBuildOutputMapFileVfrUniInfo(self
, VfrUniBaseName
):
948 MapFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".map")
950 fInputfile
= open(MapFileName
, "r", 0)
952 FileLinesList
= fInputfile
.readlines()
954 EdkLogger
.error("GenFds", FILE_READ_FAILURE
, "File read failed for %s" %MapFileName
,None)
958 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %MapFileName
,None)
961 for eachLine
in FileLinesList
:
962 for eachName
in VfrUniBaseName
.values():
963 if eachLine
.find(eachName
) != -1:
964 eachLine
= eachLine
.strip()
965 Element
= eachLine
.split()
967 # MSFT/ICC/EBC map file
969 if (len(Element
) == 4):
977 RetValue
.append((eachName
, Element
[2]))
982 elif (len(Element
) == 2) and Element
[0].startswith("0x"):
983 RetValue
.append((eachName
, Element
[0]))
987 ## __GenUniVfrOffsetFile() method
989 # Generate the offset file for the module which contain VFR or UNI file.
991 # @param self The object pointer
992 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
993 # @param UniVfrOffsetFileName The output offset file name.
995 def __GenUniVfrOffsetFile(self
, VfrUniOffsetList
, UniVfrOffsetFileName
):
998 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
1000 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %UniVfrOffsetFileName
,None)
1002 # Use a instance of StringIO to cache data
1003 fStringIO
= StringIO
.StringIO('')
1005 for Item
in VfrUniOffsetList
:
1006 if (Item
[0].find("Strings") != -1):
1008 # UNI offset in image.
1010 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1012 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
1013 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
1014 fStringIO
.write(''.join(UniGuid
))
1015 UniValue
= pack ('Q', int (Item
[1], 16))
1016 fStringIO
.write (UniValue
)
1019 # VFR binary offset in image.
1021 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1023 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
1024 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
1025 fStringIO
.write(''.join(VfrGuid
))
1027 VfrValue
= pack ('Q', int (Item
[1], 16))
1028 fStringIO
.write (VfrValue
)
1031 # write data into file.
1034 fInputfile
.write (fStringIO
.getvalue())
1036 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)