2 # process FFS generation from INF statement
4 # Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2014-2016 Hewlett-Packard Development Company, L.P.<BR>
7 # This program and the accompanying materials
8 # are licensed and made available under the terms and conditions of the BSD License
9 # which accompanies this distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 import Common
.LongFilePathOs
as os
23 from GenFdsGlobalVariable
import GenFdsGlobalVariable
29 import RuleComplexFile
30 from CommonDataClass
.FdfClass
import FfsInfStatementClassObject
31 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
32 from Common
.String
import *
33 from Common
.Misc
import PathClass
34 from Common
.Misc
import GuidStructureByteArrayToGuidString
35 from Common
.Misc
import ProcessDuplicatedInf
36 from Common
.Misc
import GetVariableOffset
37 from Common
import EdkLogger
38 from Common
.BuildToolError
import *
39 from GuidSection
import GuidSection
40 from FvImageSection
import FvImageSection
41 from Common
.Misc
import PeImageClass
42 from AutoGen
.GenDepex
import DependencyExpression
43 from PatchPcdValue
.PatchPcdValue
import PatchBinaryFile
44 from Common
.LongFilePathSupport
import CopyLongFilePath
45 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
47 ## generate FFS from INF
50 class FfsInfStatement(FfsInfStatementClassObject
):
51 ## The mapping dictionary from datum type to its maximum number.
52 _MAX_SIZE_TYPE
= {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}
55 # @param self The object pointer
58 FfsInfStatementClassObject
.__init
__(self
)
59 self
.TargetOverrideList
= []
60 self
.ShadowFromInfFile
= None
61 self
.KeepRelocFromRule
= None
64 self
.PiSpecVersion
= '0x00000000'
66 self
.FinalTargetSuffixMap
= {}
67 self
.CurrentLineNum
= None
68 self
.CurrentLineContent
= None
70 self
.InfFileName
= None
71 self
.OverrideGuid
= None
72 self
.PatchedBinFile
= ''
75 ## GetFinalTargetSuffixMap() method
77 # Get final build target list
78 def GetFinalTargetSuffixMap(self
):
79 if not self
.InfModule
or not self
.CurrentArch
:
81 if not self
.FinalTargetSuffixMap
:
82 FinalBuildTargetList
= GenFdsGlobalVariable
.GetModuleCodaTargetList(self
.InfModule
, self
.CurrentArch
)
83 for File
in FinalBuildTargetList
:
84 self
.FinalTargetSuffixMap
.setdefault(os
.path
.splitext(File
)[1], []).append(File
)
86 # Check if current INF module has DEPEX
87 if '.depex' not in self
.FinalTargetSuffixMap
and self
.InfModule
.ModuleType
!= "USER_DEFINED" \
88 and not self
.InfModule
.DxsFile
and not self
.InfModule
.LibraryClass
:
89 ModuleType
= self
.InfModule
.ModuleType
90 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
92 if ModuleType
!= DataType
.SUP_MODULE_USER_DEFINED
:
93 for LibraryClass
in PlatformDataBase
.LibraryClasses
.GetKeys():
94 if LibraryClass
.startswith("NULL") and PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]:
95 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]
97 StrModule
= str(self
.InfModule
)
99 if StrModule
in PlatformDataBase
.Modules
:
100 PlatformModule
= PlatformDataBase
.Modules
[StrModule
]
101 for LibraryClass
in PlatformModule
.LibraryClasses
:
102 if LibraryClass
.startswith("NULL"):
103 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
105 DependencyList
= [self
.InfModule
]
108 while len(DependencyList
) > 0:
109 Module
= DependencyList
.pop(0)
112 for Dep
in Module
.Depex
[self
.CurrentArch
, ModuleType
]:
114 DepexList
.append('AND')
115 DepexList
.append('(')
116 DepexList
.extend(Dep
)
117 if DepexList
[-1] == 'END': # no need of a END at this time
119 DepexList
.append(')')
120 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
122 for LibName
in Module
.LibraryClasses
:
123 if LibName
in LibraryInstance
:
125 if PlatformModule
and LibName
in PlatformModule
.LibraryClasses
:
126 LibraryPath
= PlatformModule
.LibraryClasses
[LibName
]
128 LibraryPath
= PlatformDataBase
.LibraryClasses
[LibName
, ModuleType
]
130 LibraryPath
= Module
.LibraryClasses
[LibName
]
133 LibraryModule
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[LibraryPath
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
134 LibraryInstance
[LibName
] = LibraryModule
135 DependencyList
.append(LibraryModule
)
137 Dpx
= DependencyExpression(DepexList
, ModuleType
, True)
138 if len(Dpx
.PostfixNotation
) != 0:
139 # It means this module has DEPEX
140 self
.FinalTargetSuffixMap
['.depex'] = [os
.path
.join(self
.EfiOutputPath
, self
.BaseName
) + '.depex']
141 return self
.FinalTargetSuffixMap
143 ## __InfParse() method
145 # Parse inf file to get module information
147 # @param self The object pointer
148 # @param Dict dictionary contains macro and value pair
150 def __InfParse__(self
, Dict
= {}):
152 GenFdsGlobalVariable
.VerboseLogger( " Begine parsing INf file : %s" %self
.InfFileName
)
154 self
.InfFileName
= self
.InfFileName
.replace('$(WORKSPACE)', '')
155 if len(self
.InfFileName
) > 1 and self
.InfFileName
[0] == '\\' and self
.InfFileName
[1] == '\\':
157 elif self
.InfFileName
[0] == '\\' or self
.InfFileName
[0] == '/' :
158 self
.InfFileName
= self
.InfFileName
[1:]
160 if self
.InfFileName
.find('$') == -1:
161 InfPath
= NormPath(self
.InfFileName
)
162 if not os
.path
.exists(InfPath
):
163 InfPath
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(InfPath
)
164 if not os
.path
.exists(InfPath
):
165 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Non-existant Module %s !" % (self
.InfFileName
))
167 self
.CurrentArch
= self
.GetCurrentArch()
169 # Get the InfClass object
172 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
173 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
175 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
178 # Cache lower case version of INF path before processing FILE_GUID override
180 InfLowerPath
= str(PathClassObj
).lower()
181 if self
.OverrideGuid
:
182 PathClassObj
= ProcessDuplicatedInf(PathClassObj
, self
.OverrideGuid
, GenFdsGlobalVariable
.WorkSpaceDir
)
183 if self
.CurrentArch
!= None:
185 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
187 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
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 if Inf
.AutoGenVersion
< 0x00010005:
195 self
.ModuleType
= Inf
.ComponentType
196 self
.VersionString
= Inf
.Version
197 self
.BinFileList
= Inf
.Binaries
198 self
.SourceFileList
= Inf
.Sources
199 if self
.KeepReloc
== None and Inf
.Shadow
:
200 self
.ShadowFromInfFile
= Inf
.Shadow
203 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
204 self
.BaseName
= Inf
.BaseName
205 self
.ModuleGuid
= Inf
.Guid
206 self
.ModuleType
= Inf
.ModuleType
207 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
208 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
209 self
.VersionString
= Inf
.Version
210 self
.BinFileList
= Inf
.Binaries
211 self
.SourceFileList
= Inf
.Sources
212 if self
.BinFileList
== []:
213 EdkLogger
.error("GenFds", GENFDS_ERROR
,
214 "INF %s specified in FDF could not be found in build ARCH %s!" \
215 % (self
.InfFileName
, GenFdsGlobalVariable
.ArchList
))
217 if self
.OverrideGuid
:
218 self
.ModuleGuid
= self
.OverrideGuid
220 if len(self
.SourceFileList
) != 0 and not self
.InDsc
:
221 EdkLogger
.warn("GenFds", GENFDS_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % (self
.InfFileName
))
223 if self
.ModuleType
== 'SMM_CORE' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
224 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
)
226 if Inf
._Defs
!= None and len(Inf
._Defs
) > 0:
227 self
.OptRomDefs
.update(Inf
._Defs
)
231 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
232 FdfPcdDict
= GenFdsGlobalVariable
.FdfParser
.Profile
.PcdDict
234 # Workaround here: both build and GenFds tool convert the workspace path to lower case
235 # But INF file path in FDF and DSC file may have real case characters.
236 # Try to convert the path to lower case to see if PCDs value are override by DSC.
238 for DscModule
in Platform
.Modules
:
239 DscModules
[str(DscModule
).lower()] = Platform
.Modules
[DscModule
]
240 for PcdKey
in InfPcds
:
241 Pcd
= InfPcds
[PcdKey
]
242 if not hasattr(Pcd
, 'Offset'):
244 if Pcd
.Type
!= 'PatchableInModule':
246 # Override Patchable PCD value by the value from DSC
248 if InfLowerPath
in DscModules
and PcdKey
in DscModules
[InfLowerPath
].Pcds
:
249 PatchPcd
= DscModules
[InfLowerPath
].Pcds
[PcdKey
]
250 elif PcdKey
in Platform
.Pcds
:
251 PatchPcd
= Platform
.Pcds
[PcdKey
]
253 if PatchPcd
and Pcd
.Type
== PatchPcd
.Type
:
254 DefaultValue
= PatchPcd
.DefaultValue
257 # Override Patchable PCD value by the value from FDF
259 if PcdKey
in FdfPcdDict
:
260 DefaultValue
= FdfPcdDict
[PcdKey
]
263 if not DscOverride
and not FdfOverride
:
265 # Check value, if value are equal, no need to patch
266 if Pcd
.DatumType
== "VOID*":
267 if Pcd
.DefaultValue
== DefaultValue
or DefaultValue
in [None, '']:
269 # Get the string size from FDF or DSC
270 if DefaultValue
[0] == 'L':
271 # Remove L"", but the '\0' must be appended
272 MaxDatumSize
= str((len(DefaultValue
) - 2) * 2)
273 elif DefaultValue
[0] == '{':
274 MaxDatumSize
= str(len(DefaultValue
.split(',')))
276 MaxDatumSize
= str(len(DefaultValue
) - 1)
278 Pcd
.MaxDatumSize
= PatchPcd
.MaxDatumSize
279 # If no defined the maximum size in DSC, try to get current size from INF
280 if Pcd
.MaxDatumSize
in ['', None]:
281 Pcd
.MaxDatumSize
= str(len(Pcd
.DefaultValue
.split(',')))
284 if Pcd
.DefaultValue
.upper().startswith('0X'):
286 if DefaultValue
.upper().startswith('0X'):
289 PcdValueInImg
= int(Pcd
.DefaultValue
, Base1
)
290 PcdValueInDscOrFdf
= int(DefaultValue
, Base2
)
291 if PcdValueInImg
== PcdValueInDscOrFdf
:
295 # Check the Pcd size and data type
296 if Pcd
.DatumType
== "VOID*":
297 if int(MaxDatumSize
) > int(Pcd
.MaxDatumSize
):
298 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
299 % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, int(MaxDatumSize
) - int(Pcd
.MaxDatumSize
)))
301 if PcdValueInDscOrFdf
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
] \
302 or PcdValueInImg
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
]:
303 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of %s type PCD '%s.%s' doesn't match its data type." \
304 % (Pcd
.DatumType
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
305 self
.PatchPcds
.append((Pcd
, DefaultValue
))
308 self
.PcdIsDriver
= Inf
.PcdIsDriver
309 self
.IsBinaryModule
= Inf
.IsBinaryModule
310 GenFdsGlobalVariable
.VerboseLogger("BaseName : %s" % self
.BaseName
)
311 GenFdsGlobalVariable
.VerboseLogger("ModuleGuid : %s" % self
.ModuleGuid
)
312 GenFdsGlobalVariable
.VerboseLogger("ModuleType : %s" % self
.ModuleType
)
313 GenFdsGlobalVariable
.VerboseLogger("VersionString : %s" % self
.VersionString
)
314 GenFdsGlobalVariable
.VerboseLogger("InfFileName :%s" % self
.InfFileName
)
317 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
320 self
.OutputPath
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, \
321 self
.ModuleGuid
+ self
.BaseName
)
322 if not os
.path
.exists(self
.OutputPath
) :
323 os
.makedirs(self
.OutputPath
)
325 self
.EfiOutputPath
= self
.__GetEFIOutPutPath
__()
326 GenFdsGlobalVariable
.VerboseLogger( "ModuelEFIPath: " + self
.EfiOutputPath
)
330 # Patch EFI file with patch PCD
332 # @param EfiFile: EFI file needs to be patched.
333 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
334 # If passed in file does not end with efi, return as is
336 def PatchEfiFile(self
, EfiFile
, FileType
):
338 # If the module does not have any patches, then return path to input file
340 if not self
.PatchPcds
:
344 # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED
346 if FileType
!= 'PE32' and self
.ModuleType
!= "USER_DEFINED":
350 # Generate path to patched output file
352 Basename
= os
.path
.basename(EfiFile
)
353 Output
= os
.path
.normpath (os
.path
.join(self
.OutputPath
, Basename
))
356 # If this file has already been patched, then return the path to the patched file
358 if self
.PatchedBinFile
== Output
:
362 # If a different file from the same module has already been patched, then generate an error
364 if self
.PatchedBinFile
:
365 EdkLogger
.error("GenFds", GENFDS_ERROR
,
366 'Only one binary file can be patched:\n'
367 ' a binary file has been patched: %s\n'
368 ' current file: %s' % (self
.PatchedBinFile
, EfiFile
),
369 File
=self
.InfFileName
)
372 # Copy unpatched file contents to output file location to perform patching
374 CopyLongFilePath(EfiFile
, Output
)
377 # Apply patches to patched output file
379 for Pcd
, Value
in self
.PatchPcds
:
380 RetVal
, RetStr
= PatchBinaryFile(Output
, int(Pcd
.Offset
, 0), Pcd
.DatumType
, Value
, Pcd
.MaxDatumSize
)
382 EdkLogger
.error("GenFds", GENFDS_ERROR
, RetStr
, File
=self
.InfFileName
)
385 # Save the path of the patched output file
387 self
.PatchedBinFile
= Output
390 # Return path to patched output file
398 # @param self The object pointer
399 # @param Dict dictionary contains macro and value pair
400 # @param FvChildAddr Array of the inside FvImage base address
401 # @param FvParentAddr Parent Fv base address
402 # @retval string Generated FFS file name
404 def GenFfs(self
, Dict
= {}, FvChildAddr
= [], FvParentAddr
=None):
406 # Parse Inf file get Module related information
409 self
.__InfParse
__(Dict
)
410 SrcFile
= mws
.join( GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
);
411 DestFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
414 SrcPath
= os
.path
.dirname(SrcFile
)
415 SrcFileName
= os
.path
.basename(SrcFile
)
416 SrcFileBase
, SrcFileExt
= os
.path
.splitext(SrcFileName
)
417 DestPath
= os
.path
.dirname(DestFile
)
418 DestFileName
= os
.path
.basename(DestFile
)
419 DestFileBase
, DestFileExt
= os
.path
.splitext(DestFileName
)
423 "${s_path}" : SrcPath
,
424 "${s_dir}" : SrcFileDir
,
425 "${s_name}" : SrcFileName
,
426 "${s_base}" : SrcFileBase
,
427 "${s_ext}" : SrcFileExt
,
430 "${d_path}" : DestPath
,
431 "${d_name}" : DestFileName
,
432 "${d_base}" : DestFileBase
,
433 "${d_ext}" : DestFileExt
436 # Allow binary type module not specify override rule in FDF file.
438 if len(self
.BinFileList
) > 0:
439 if self
.Rule
== None or self
.Rule
== "":
443 # Get the rule of how to generate Ffs file
445 Rule
= self
.__GetRule
__()
446 GenFdsGlobalVariable
.VerboseLogger( "Packing binaries from inf file : %s" %self
.InfFileName
)
448 # Convert Fv File Type for PI1.1 SMM driver.
450 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
451 if Rule
.FvFileType
== 'DRIVER':
452 Rule
.FvFileType
= 'SMM'
454 # Framework SMM Driver has no SMM FV file type
456 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
457 if Rule
.FvFileType
== 'SMM' or Rule
.FvFileType
== 'SMM_CORE':
458 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File
=self
.InfFileName
)
460 # For the rule only has simpleFile
462 if isinstance (Rule
, RuleSimpleFile
.RuleSimpleFile
) :
463 SectionOutputList
= self
.__GenSimpleFileSection
__(Rule
)
464 FfsOutput
= self
.__GenSimpleFileFfs
__(Rule
, SectionOutputList
)
467 # For Rule has ComplexFile
469 elif isinstance(Rule
, RuleComplexFile
.RuleComplexFile
):
470 InputSectList
, InputSectAlignments
= self
.__GenComplexFileSection
__(Rule
, FvChildAddr
, FvParentAddr
)
471 FfsOutput
= self
.__GenComplexFileFfs
__(Rule
, InputSectList
, InputSectAlignments
)
475 ## __ExtendMacro__() method
477 # Replace macro with its value
479 # @param self The object pointer
480 # @param String The string to be replaced
481 # @retval string Macro replaced string
483 def __ExtendMacro__ (self
, String
):
485 '$(INF_OUTPUT)' : self
.EfiOutputPath
,
486 '$(MODULE_NAME)' : self
.BaseName
,
487 '$(BUILD_NUMBER)': self
.BuildNum
,
488 '$(INF_VERSION)' : self
.VersionString
,
489 '$(NAMED_GUID)' : self
.ModuleGuid
491 String
= GenFdsGlobalVariable
.MacroExtend(String
, MacroDict
)
492 String
= GenFdsGlobalVariable
.MacroExtend(String
, self
.MacroDict
)
495 ## __GetRule__() method
497 # Get correct rule for generating FFS for this INF
499 # @param self The object pointer
500 # @retval Rule Rule object
502 def __GetRule__ (self
) :
504 if self
.CurrentArch
== None:
505 CurrentArchList
= ['common']
507 CurrentArchList
.append(self
.CurrentArch
)
509 for CurrentArch
in CurrentArchList
:
510 RuleName
= 'RULE' + \
512 CurrentArch
.upper() + \
514 self
.ModuleType
.upper()
515 if self
.Rule
!= None:
516 RuleName
= RuleName
+ \
520 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
522 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
525 RuleName
= 'RULE' + \
529 self
.ModuleType
.upper()
531 if self
.Rule
!= None:
532 RuleName
= RuleName
+ \
536 GenFdsGlobalVariable
.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName
, self
.InfFileName
))
538 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
540 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
544 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'Don\'t Find common rule %s for INF %s' \
545 % (RuleName
, self
.InfFileName
))
547 ## __GetPlatformArchList__() method
549 # Get Arch list this INF built under
551 # @param self The object pointer
552 # @retval list Arch list
554 def __GetPlatformArchList__(self
):
556 InfFileKey
= os
.path
.normpath(mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
))
558 for Arch
in GenFdsGlobalVariable
.ArchList
:
559 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
560 if PlatformDataBase
!= None:
561 if InfFileKey
in PlatformDataBase
.Modules
:
562 DscArchList
.append (Arch
)
566 ## GetCurrentArch() method
568 # Get Arch list of the module from this INF is to be placed into flash
570 # @param self The object pointer
571 # @retval list Arch list
573 def GetCurrentArch(self
) :
575 TargetArchList
= GenFdsGlobalVariable
.ArchList
577 PlatformArchList
= self
.__GetPlatformArchList
__()
579 CurArchList
= TargetArchList
580 if PlatformArchList
!= []:
581 CurArchList
= list(set (TargetArchList
) & set (PlatformArchList
))
582 GenFdsGlobalVariable
.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList
))
585 if self
.KeyStringList
!= []:
586 for Key
in self
.KeyStringList
:
587 Key
= GenFdsGlobalVariable
.MacroExtend(Key
)
588 Target
, Tag
, Arch
= Key
.split('_')
589 if Arch
in CurArchList
:
590 ArchList
.append(Arch
)
591 if Target
not in self
.TargetOverrideList
:
592 self
.TargetOverrideList
.append(Target
)
594 ArchList
= CurArchList
596 UseArchList
= TargetArchList
597 if self
.UseArch
!= None:
599 UseArchList
.append(self
.UseArch
)
600 ArchList
= list(set (UseArchList
) & set (ArchList
))
602 self
.InfFileName
= NormPath(self
.InfFileName
)
603 if len(PlatformArchList
) == 0:
605 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
606 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
608 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
609 if len(ArchList
) == 1:
612 elif len(ArchList
) > 1:
613 if len(PlatformArchList
) == 0:
614 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
))
616 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
))
618 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." \
619 % (self
.InfFileName
, str(PlatformArchList
), GenFdsGlobalVariable
.ActivePlatform
, str(set (UseArchList
) & set (TargetArchList
))))
621 ## __GetEFIOutPutPath__() method
623 # Get the output path for generated files
625 # @param self The object pointer
626 # @retval string Path that output files from this INF go to
628 def __GetEFIOutPutPath__(self
):
631 (ModulePath
, FileName
) = os
.path
.split(self
.InfFileName
)
632 Index
= FileName
.rfind('.')
633 FileName
= FileName
[0:Index
]
634 if self
.OverrideGuid
:
635 FileName
= self
.OverrideGuid
637 if self
.CurrentArch
!= None:
638 Arch
= self
.CurrentArch
640 OutputPath
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
],
646 OutputPath
= os
.path
.realpath(OutputPath
)
649 ## __GenSimpleFileSection__() method
651 # Generate section by specified file name or a list of files with file extension
653 # @param self The object pointer
654 # @param Rule The rule object used to generate section
655 # @retval string File name of the generated section file
657 def __GenSimpleFileSection__(self
, Rule
):
659 # Prepare the parameter of GenSection
663 GenSecInputFile
= None
664 if Rule
.FileName
!= None:
665 GenSecInputFile
= self
.__ExtendMacro
__(Rule
.FileName
)
666 if os
.path
.isabs(GenSecInputFile
):
667 GenSecInputFile
= os
.path
.normpath(GenSecInputFile
)
669 GenSecInputFile
= os
.path
.normpath(os
.path
.join(self
.EfiOutputPath
, GenSecInputFile
))
671 FileList
, IsSect
= Section
.Section
.GetFileList(self
, '', Rule
.FileExtension
)
674 SectionType
= Rule
.SectionType
676 # Convert Fv Section Type for PI1.1 SMM driver.
678 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
679 if SectionType
== 'DXE_DEPEX':
680 SectionType
= 'SMM_DEPEX'
682 # Framework SMM Driver has no SMM_DEPEX section type
684 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
685 if SectionType
== 'SMM_DEPEX':
686 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
688 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
689 if self
.KeepReloc
!= None:
690 NoStrip
= self
.KeepReloc
691 elif Rule
.KeepReloc
!= None:
692 NoStrip
= Rule
.KeepReloc
693 elif self
.ShadowFromInfFile
!= None:
694 NoStrip
= self
.ShadowFromInfFile
697 for File
in FileList
:
700 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
701 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
703 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
704 File
= GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)
706 #Get PE Section alignment when align is set to AUTO
707 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
708 ImageObj
= PeImageClass (File
)
709 if ImageObj
.SectionAlignment
< 0x400:
710 self
.Alignment
= str (ImageObj
.SectionAlignment
)
712 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
715 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
716 if not os
.path
.exists(FileBeforeStrip
) or \
717 (os
.path
.getmtime(File
) > os
.path
.getmtime(FileBeforeStrip
)):
718 CopyLongFilePath(File
, FileBeforeStrip
)
719 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
720 GenFdsGlobalVariable
.GenerateFirmwareImage(
727 if SectionType
== 'TE':
728 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
729 GenFdsGlobalVariable
.GenerateFirmwareImage(
736 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [File
], Section
.Section
.SectionType
[SectionType
])
737 OutputFileList
.append(OutputFile
)
740 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
741 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
742 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
743 GenSecInputFile
= GenFdsGlobalVariable
.MacroExtend(GenSecInputFile
, Dict
, self
.CurrentArch
)
745 #Get PE Section alignment when align is set to AUTO
746 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
747 ImageObj
= PeImageClass (GenSecInputFile
)
748 if ImageObj
.SectionAlignment
< 0x400:
749 self
.Alignment
= str (ImageObj
.SectionAlignment
)
751 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
754 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
755 if not os
.path
.exists(FileBeforeStrip
) or \
756 (os
.path
.getmtime(GenSecInputFile
) > os
.path
.getmtime(FileBeforeStrip
)):
757 CopyLongFilePath(GenSecInputFile
, FileBeforeStrip
)
759 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
760 GenFdsGlobalVariable
.GenerateFirmwareImage(
765 GenSecInputFile
= StrippedFile
767 if SectionType
== 'TE':
768 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
769 GenFdsGlobalVariable
.GenerateFirmwareImage(
774 GenSecInputFile
= TeFile
776 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [GenSecInputFile
], Section
.Section
.SectionType
[SectionType
])
777 OutputFileList
.append(OutputFile
)
779 return OutputFileList
781 ## __GenSimpleFileFfs__() method
785 # @param self The object pointer
786 # @param Rule The rule object used to generate section
787 # @param InputFileList The output file list from GenSection
788 # @retval string Generated FFS file name
790 def __GenSimpleFileFfs__(self
, Rule
, InputFileList
):
791 FfsOutput
= self
.OutputPath
+ \
793 self
.__ExtendMacro
__(Rule
.NameGuid
) + \
796 GenFdsGlobalVariable
.VerboseLogger(self
.__ExtendMacro
__(Rule
.NameGuid
))
798 SectionAlignments
= []
799 for InputFile
in InputFileList
:
800 InputSection
.append(InputFile
)
801 SectionAlignments
.append(Rule
.SectAlignment
)
803 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
804 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
805 if len(PcdValue
) == 0:
806 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
808 if PcdValue
.startswith('{'):
809 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
810 RegistryGuidStr
= PcdValue
811 if len(RegistryGuidStr
) == 0:
812 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
814 self
.ModuleGuid
= RegistryGuidStr
816 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputSection
,
817 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
818 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
819 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
820 SectionAlign
=SectionAlignments
824 ## __GenComplexFileSection__() method
826 # Generate section by sections in Rule
828 # @param self The object pointer
829 # @param Rule The rule object used to generate section
830 # @param FvChildAddr Array of the inside FvImage base address
831 # @param FvParentAddr Parent Fv base address
832 # @retval string File name of the generated section file
834 def __GenComplexFileSection__(self
, Rule
, FvChildAddr
, FvParentAddr
):
835 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
836 if Rule
.KeepReloc
!= None:
837 self
.KeepRelocFromRule
= Rule
.KeepReloc
841 HasGneratedFlag
= False
842 if self
.PcdIsDriver
== 'PEI_PCD_DRIVER':
843 if self
.IsBinaryModule
:
844 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "PEIPcdDataBase.raw")
846 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "PEIPcdDataBase.raw")
847 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "PEIPcdDataBaseSec.raw")
848 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
852 SectFiles
.append(PcdExDbSecName
)
853 SectAlignments
.append(None)
854 elif self
.PcdIsDriver
== 'DXE_PCD_DRIVER':
855 if self
.IsBinaryModule
:
856 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "DXEPcdDataBase.raw")
858 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "DXEPcdDataBase.raw")
859 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "DXEPcdDataBaseSec.raw")
860 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
864 SectFiles
.append(PcdExDbSecName
)
865 SectAlignments
.append(None)
866 for Sect
in Rule
.SectionList
:
867 SecIndex
= '%d' %Index
870 # Convert Fv Section Type for PI1.1 SMM driver.
872 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
873 if Sect
.SectionType
== 'DXE_DEPEX':
874 Sect
.SectionType
= 'SMM_DEPEX'
876 # Framework SMM Driver has no SMM_DEPEX section type
878 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
879 if Sect
.SectionType
== 'SMM_DEPEX':
880 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
882 # process the inside FvImage from FvSection or GuidSection
884 if FvChildAddr
!= []:
885 if isinstance(Sect
, FvImageSection
):
886 Sect
.FvAddr
= FvChildAddr
.pop(0)
887 elif isinstance(Sect
, GuidSection
):
888 Sect
.FvAddr
= FvChildAddr
889 if FvParentAddr
!= None and isinstance(Sect
, GuidSection
):
890 Sect
.FvParentAddr
= FvParentAddr
892 if Rule
.KeyStringList
!= []:
893 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, Rule
.KeyStringList
, self
)
895 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, self
.KeyStringList
, self
)
897 if not HasGneratedFlag
:
898 UniVfrOffsetFileSection
= ""
899 ModuleFileName
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
)
900 InfData
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClass(ModuleFileName
), self
.CurrentArch
]
902 # Search the source list in InfData to find if there are .vfr file exist.
905 VfrUniOffsetList
= []
906 for SourceFile
in InfData
.Sources
:
907 if SourceFile
.Type
.upper() == ".VFR" :
909 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
911 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
912 if SourceFile
.Type
.upper() == ".UNI" :
914 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
916 VfrUniBaseName
["UniOffsetName"] = (self
.BaseName
+ "Strings")
919 if len(VfrUniBaseName
) > 0:
920 VfrUniOffsetList
= self
.__GetBuildOutputMapFileVfrUniInfo
(VfrUniBaseName
)
922 # Generate the Raw data of raw section
924 os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
925 UniVfrOffsetFileName
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
926 UniVfrOffsetFileSection
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ 'Offset' + '.raw')
928 self
.__GenUniVfrOffsetFile
(VfrUniOffsetList
, UniVfrOffsetFileName
)
930 UniVfrOffsetFileNameList
= []
931 UniVfrOffsetFileNameList
.append(UniVfrOffsetFileName
)
932 """Call GenSection"""
933 GenFdsGlobalVariable
.GenerateSection(UniVfrOffsetFileSection
,
934 UniVfrOffsetFileNameList
,
937 os
.remove(UniVfrOffsetFileName
)
938 SectList
.append(UniVfrOffsetFileSection
)
939 HasGneratedFlag
= True
941 for SecName
in SectList
:
942 SectFiles
.append(SecName
)
943 SectAlignments
.append(Align
)
945 return SectFiles
, SectAlignments
947 ## __GenComplexFileFfs__() method
951 # @param self The object pointer
952 # @param Rule The rule object used to generate section
953 # @param InputFileList The output file list from GenSection
954 # @retval string Generated FFS file name
956 def __GenComplexFileFfs__(self
, Rule
, InputFile
, Alignments
):
958 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
959 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
960 if len(PcdValue
) == 0:
961 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
963 if PcdValue
.startswith('{'):
964 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
965 RegistryGuidStr
= PcdValue
966 if len(RegistryGuidStr
) == 0:
967 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
969 self
.ModuleGuid
= RegistryGuidStr
971 FfsOutput
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
972 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputFile
,
973 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
974 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
975 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
976 SectionAlign
=Alignments
980 ## __GetGenFfsCmdParameter__() method
982 # Create parameter string for GenFfs
984 # @param self The object pointer
985 # @param Rule The rule object used to generate section
986 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
988 def __GetGenFfsCmdParameter__(self
, Rule
):
990 result
+= ('-t', Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
])
991 if Rule
.Fixed
!= False:
993 if Rule
.CheckSum
!= False:
996 if Rule
.Alignment
!= None and Rule
.Alignment
!= '':
997 result
+= ('-a', Rule
.Alignment
)
1001 ## __GetBuildOutputMapFileVfrUniInfo() method
1003 # Find the offset of UNI/INF object offset in the EFI image file.
1005 # @param self The object pointer
1006 # @param VfrUniBaseName A name list contain the UNI/INF object name.
1007 # @retval RetValue A list contain offset of UNI/INF object.
1009 def __GetBuildOutputMapFileVfrUniInfo(self
, VfrUniBaseName
):
1010 MapFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".map")
1011 EfiFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".efi")
1012 return GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
1014 ## __GenUniVfrOffsetFile() method
1016 # Generate the offset file for the module which contain VFR or UNI file.
1018 # @param self The object pointer
1019 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
1020 # @param UniVfrOffsetFileName The output offset file name.
1022 def __GenUniVfrOffsetFile(self
, VfrUniOffsetList
, UniVfrOffsetFileName
):
1025 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
1027 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %UniVfrOffsetFileName
,None)
1029 # Use a instance of StringIO to cache data
1030 fStringIO
= StringIO
.StringIO('')
1032 for Item
in VfrUniOffsetList
:
1033 if (Item
[0].find("Strings") != -1):
1035 # UNI offset in image.
1037 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1039 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
1040 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
1041 fStringIO
.write(''.join(UniGuid
))
1042 UniValue
= pack ('Q', int (Item
[1], 16))
1043 fStringIO
.write (UniValue
)
1046 # VFR binary offset in image.
1048 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1050 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
1051 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
1052 fStringIO
.write(''.join(VfrGuid
))
1054 VfrValue
= pack ('Q', int (Item
[1], 16))
1055 fStringIO
.write (VfrValue
)
1058 # write data into file.
1061 fInputfile
.write (fStringIO
.getvalue())
1063 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)