2 # process FFS generation from INF statement
4 # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2014 Hewlett-Packard Development Company, L.P.<BR>
7 # This program and the accompanying materials
8 # are licensed and made available under the terms and conditions of the BSD License
9 # which accompanies this distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 import Common
.LongFilePathOs
as os
23 from GenFdsGlobalVariable
import GenFdsGlobalVariable
29 import RuleComplexFile
30 from CommonDataClass
.FdfClass
import FfsInfStatementClassObject
31 from Common
.String
import *
32 from Common
.Misc
import PathClass
33 from Common
.Misc
import GuidStructureByteArrayToGuidString
34 from Common
.Misc
import ProcessDuplicatedInf
35 from Common
import EdkLogger
36 from Common
.BuildToolError
import *
37 from GuidSection
import GuidSection
38 from FvImageSection
import FvImageSection
39 from Common
.Misc
import PeImageClass
40 from AutoGen
.GenDepex
import DependencyExpression
41 from PatchPcdValue
.PatchPcdValue
import PatchBinaryFile
42 from Common
.LongFilePathSupport
import CopyLongFilePath
43 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
45 ## generate FFS from INF
48 class FfsInfStatement(FfsInfStatementClassObject
):
49 ## The mapping dictionary from datum type to its maximum number.
50 _MAX_SIZE_TYPE
= {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}
53 # @param self The object pointer
56 FfsInfStatementClassObject
.__init
__(self
)
57 self
.TargetOverrideList
= []
58 self
.ShadowFromInfFile
= None
59 self
.KeepRelocFromRule
= None
62 self
.PiSpecVersion
= '0x00000000'
64 self
.FinalTargetSuffixMap
= {}
65 self
.CurrentLineNum
= None
66 self
.CurrentLineContent
= None
68 self
.InfFileName
= None
69 self
.OverrideGuid
= None
70 self
.PatchedBinFile
= ''
72 ## GetFinalTargetSuffixMap() method
74 # Get final build target list
75 def GetFinalTargetSuffixMap(self
):
76 if not self
.InfModule
or not self
.CurrentArch
:
78 if not self
.FinalTargetSuffixMap
:
79 FinalBuildTargetList
= GenFdsGlobalVariable
.GetModuleCodaTargetList(self
.InfModule
, self
.CurrentArch
)
80 for File
in FinalBuildTargetList
:
81 self
.FinalTargetSuffixMap
.setdefault(os
.path
.splitext(File
)[1], []).append(File
)
83 # Check if current INF module has DEPEX
84 if '.depex' not in self
.FinalTargetSuffixMap
and self
.InfModule
.ModuleType
!= "USER_DEFINED" \
85 and not self
.InfModule
.DxsFile
and not self
.InfModule
.LibraryClass
:
86 ModuleType
= self
.InfModule
.ModuleType
87 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
89 if ModuleType
!= DataType
.SUP_MODULE_USER_DEFINED
:
90 for LibraryClass
in PlatformDataBase
.LibraryClasses
.GetKeys():
91 if LibraryClass
.startswith("NULL") and PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]:
92 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]
94 StrModule
= str(self
.InfModule
)
96 if StrModule
in PlatformDataBase
.Modules
:
97 PlatformModule
= PlatformDataBase
.Modules
[StrModule
]
98 for LibraryClass
in PlatformModule
.LibraryClasses
:
99 if LibraryClass
.startswith("NULL"):
100 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
102 DependencyList
= [self
.InfModule
]
105 while len(DependencyList
) > 0:
106 Module
= DependencyList
.pop(0)
109 for Dep
in Module
.Depex
[self
.CurrentArch
, ModuleType
]:
111 DepexList
.append('AND')
112 DepexList
.append('(')
113 DepexList
.extend(Dep
)
114 if DepexList
[-1] == 'END': # no need of a END at this time
116 DepexList
.append(')')
117 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
119 for LibName
in Module
.LibraryClasses
:
120 if LibName
in LibraryInstance
:
122 if PlatformModule
and LibName
in PlatformModule
.LibraryClasses
:
123 LibraryPath
= PlatformModule
.LibraryClasses
[LibName
]
125 LibraryPath
= PlatformDataBase
.LibraryClasses
[LibName
, ModuleType
]
127 LibraryPath
= Module
.LibraryClasses
[LibName
]
130 LibraryModule
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[LibraryPath
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
131 LibraryInstance
[LibName
] = LibraryModule
132 DependencyList
.append(LibraryModule
)
134 Dpx
= DependencyExpression(DepexList
, ModuleType
, True)
135 if len(Dpx
.PostfixNotation
) != 0:
136 # It means this module has DEPEX
137 self
.FinalTargetSuffixMap
['.depex'] = [os
.path
.join(self
.EfiOutputPath
, self
.BaseName
) + '.depex']
138 return self
.FinalTargetSuffixMap
140 ## __InfParse() method
142 # Parse inf file to get module information
144 # @param self The object pointer
145 # @param Dict dictionary contains macro and value pair
147 def __InfParse__(self
, Dict
= {}):
149 GenFdsGlobalVariable
.VerboseLogger( " Begine parsing INf file : %s" %self
.InfFileName
)
151 self
.InfFileName
= self
.InfFileName
.replace('$(WORKSPACE)', '')
152 if len(self
.InfFileName
) > 1 and self
.InfFileName
[0] == '\\' and self
.InfFileName
[1] == '\\':
154 elif self
.InfFileName
[0] == '\\' or self
.InfFileName
[0] == '/' :
155 self
.InfFileName
= self
.InfFileName
[1:]
157 if self
.InfFileName
.find('$') == -1:
158 InfPath
= NormPath(self
.InfFileName
)
159 if not os
.path
.exists(InfPath
):
160 InfPath
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(InfPath
)
161 if not os
.path
.exists(InfPath
):
162 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Non-existant Module %s !" % (self
.InfFileName
))
164 self
.CurrentArch
= self
.GetCurrentArch()
166 # Get the InfClass object
169 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
170 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
172 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
174 if self
.OverrideGuid
:
175 PathClassObj
= ProcessDuplicatedInf(PathClassObj
, self
.OverrideGuid
, GenFdsGlobalVariable
.WorkSpaceDir
)
176 if self
.CurrentArch
!= None:
178 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
180 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
182 self
.BaseName
= Inf
.BaseName
183 self
.ModuleGuid
= Inf
.Guid
184 self
.ModuleType
= Inf
.ModuleType
185 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
186 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
187 if Inf
.AutoGenVersion
< 0x00010005:
188 self
.ModuleType
= Inf
.ComponentType
189 self
.VersionString
= Inf
.Version
190 self
.BinFileList
= Inf
.Binaries
191 self
.SourceFileList
= Inf
.Sources
192 if self
.KeepReloc
== None and Inf
.Shadow
:
193 self
.ShadowFromInfFile
= Inf
.Shadow
196 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
197 self
.BaseName
= Inf
.BaseName
198 self
.ModuleGuid
= Inf
.Guid
199 self
.ModuleType
= Inf
.ModuleType
200 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
201 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
202 self
.VersionString
= Inf
.Version
203 self
.BinFileList
= Inf
.Binaries
204 self
.SourceFileList
= Inf
.Sources
205 if self
.BinFileList
== []:
206 EdkLogger
.error("GenFds", GENFDS_ERROR
,
207 "INF %s specified in FDF could not be found in build ARCH %s!" \
208 % (self
.InfFileName
, GenFdsGlobalVariable
.ArchList
))
210 if self
.OverrideGuid
:
211 self
.ModuleGuid
= self
.OverrideGuid
213 if len(self
.SourceFileList
) != 0 and not self
.InDsc
:
214 EdkLogger
.warn("GenFds", GENFDS_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % (self
.InfFileName
))
216 if self
.ModuleType
== 'SMM_CORE' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
217 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
)
219 if Inf
._Defs
!= None and len(Inf
._Defs
) > 0:
220 self
.OptRomDefs
.update(Inf
._Defs
)
224 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
225 FdfPcdDict
= GenFdsGlobalVariable
.FdfParser
.Profile
.PcdDict
227 # Workaround here: both build and GenFds tool convert the workspace path to lower case
228 # But INF file path in FDF and DSC file may have real case characters.
229 # Try to convert the path to lower case to see if PCDs value are override by DSC.
231 for DscModule
in Platform
.Modules
:
232 DscModules
[str(DscModule
).lower()] = Platform
.Modules
[DscModule
]
233 for PcdKey
in InfPcds
:
234 Pcd
= InfPcds
[PcdKey
]
235 if not hasattr(Pcd
, 'Offset'):
237 if Pcd
.Type
!= 'PatchableInModule':
239 # Override Patchable PCD value by the value from DSC
241 InfLowerPath
= str(PathClassObj
).lower()
242 if InfLowerPath
in DscModules
and PcdKey
in DscModules
[InfLowerPath
].Pcds
:
243 PatchPcd
= DscModules
[InfLowerPath
].Pcds
[PcdKey
]
244 elif PcdKey
in Platform
.Pcds
:
245 PatchPcd
= Platform
.Pcds
[PcdKey
]
247 if PatchPcd
and Pcd
.Type
== PatchPcd
.Type
:
248 DefaultValue
= PatchPcd
.DefaultValue
251 # Override Patchable PCD value by the value from FDF
253 if PcdKey
in FdfPcdDict
:
254 DefaultValue
= FdfPcdDict
[PcdKey
]
257 if not DscOverride
and not FdfOverride
:
259 # Check value, if value are equal, no need to patch
260 if Pcd
.DatumType
== "VOID*":
261 if Pcd
.DefaultValue
== DefaultValue
or DefaultValue
in [None, '']:
263 # Get the string size from FDF or DSC
264 if DefaultValue
[0] == 'L':
265 # Remove L"", but the '\0' must be appended
266 MaxDatumSize
= str((len(DefaultValue
) - 2) * 2)
267 elif DefaultValue
[0] == '{':
268 MaxDatumSize
= str(len(DefaultValue
.split(',')))
270 MaxDatumSize
= str(len(DefaultValue
) - 1)
272 Pcd
.MaxDatumSize
= PatchPcd
.MaxDatumSize
273 # If no defined the maximum size in DSC, try to get current size from INF
274 if Pcd
.MaxDatumSize
in ['', None]:
275 Pcd
.MaxDatumSize
= str(len(Pcd
.DefaultValue
.split(',')))
278 if Pcd
.DefaultValue
.upper().startswith('0X'):
280 if DefaultValue
.upper().startswith('0X'):
283 PcdValueInImg
= int(Pcd
.DefaultValue
, Base1
)
284 PcdValueInDscOrFdf
= int(DefaultValue
, Base2
)
285 if PcdValueInImg
== PcdValueInDscOrFdf
:
289 # Check the Pcd size and data type
290 if Pcd
.DatumType
== "VOID*":
291 if int(MaxDatumSize
) > int(Pcd
.MaxDatumSize
):
292 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
293 % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, int(MaxDatumSize
) - int(Pcd
.MaxDatumSize
)))
295 if PcdValueInDscOrFdf
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
] \
296 or PcdValueInImg
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
]:
297 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of %s type PCD '%s.%s' doesn't match its data type." \
298 % (Pcd
.DatumType
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
299 self
.PatchPcds
.append((Pcd
, DefaultValue
))
302 self
.PcdIsDriver
= Inf
.PcdIsDriver
303 self
.IsBinaryModule
= Inf
.IsBinaryModule
304 GenFdsGlobalVariable
.VerboseLogger("BaseName : %s" % self
.BaseName
)
305 GenFdsGlobalVariable
.VerboseLogger("ModuleGuid : %s" % self
.ModuleGuid
)
306 GenFdsGlobalVariable
.VerboseLogger("ModuleType : %s" % self
.ModuleType
)
307 GenFdsGlobalVariable
.VerboseLogger("VersionString : %s" % self
.VersionString
)
308 GenFdsGlobalVariable
.VerboseLogger("InfFileName :%s" % self
.InfFileName
)
311 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
314 self
.OutputPath
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, \
315 self
.ModuleGuid
+ self
.BaseName
)
316 if not os
.path
.exists(self
.OutputPath
) :
317 os
.makedirs(self
.OutputPath
)
319 self
.EfiOutputPath
= self
.__GetEFIOutPutPath
__()
320 GenFdsGlobalVariable
.VerboseLogger( "ModuelEFIPath: " + self
.EfiOutputPath
)
324 # Patch EFI file with patch PCD
326 # @param EfiFile: EFI file needs to be patched.
327 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
328 # If passed in file does not end with efi, return as is
330 def PatchEfiFile(self
, EfiFile
, FileType
):
331 if not self
.PatchPcds
:
333 if FileType
!= 'PE32' and self
.ModuleType
!= "USER_DEFINED":
335 if self
.PatchedBinFile
:
336 EdkLogger
.error("GenFds", GENFDS_ERROR
,
337 'Only one binary file can be patched:\n'
338 ' a binary file has been patched: %s\n'
339 ' current file: %s' % (self
.PatchedBinFile
, EfiFile
),
340 File
=self
.InfFileName
)
341 Basename
= os
.path
.basename(EfiFile
)
342 Output
= os
.path
.join(self
.OutputPath
, Basename
)
343 CopyLongFilePath(EfiFile
, Output
)
344 for Pcd
, Value
in self
.PatchPcds
:
345 RetVal
, RetStr
= PatchBinaryFile(Output
, int(Pcd
.Offset
, 0), Pcd
.DatumType
, Value
, Pcd
.MaxDatumSize
)
347 EdkLogger
.error("GenFds", GENFDS_ERROR
, RetStr
, File
=self
.InfFileName
)
348 self
.PatchedBinFile
= os
.path
.normpath(EfiFile
)
354 # @param self The object pointer
355 # @param Dict dictionary contains macro and value pair
356 # @param FvChildAddr Array of the inside FvImage base address
357 # @param FvParentAddr Parent Fv base address
358 # @retval string Generated FFS file name
360 def GenFfs(self
, Dict
= {}, FvChildAddr
= [], FvParentAddr
=None):
362 # Parse Inf file get Module related information
365 self
.__InfParse
__(Dict
)
366 SrcFile
= os
.path
.join( GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
);
367 DestFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
370 SrcPath
= os
.path
.dirname(SrcFile
)
371 SrcFileName
= os
.path
.basename(SrcFile
)
372 SrcFileBase
, SrcFileExt
= os
.path
.splitext(SrcFileName
)
373 DestPath
= os
.path
.dirname(DestFile
)
374 DestFileName
= os
.path
.basename(DestFile
)
375 DestFileBase
, DestFileExt
= os
.path
.splitext(DestFileName
)
379 "${s_path}" : SrcPath
,
380 "${s_dir}" : SrcFileDir
,
381 "${s_name}" : SrcFileName
,
382 "${s_base}" : SrcFileBase
,
383 "${s_ext}" : SrcFileExt
,
386 "${d_path}" : DestPath
,
387 "${d_name}" : DestFileName
,
388 "${d_base}" : DestFileBase
,
389 "${d_ext}" : DestFileExt
392 # Allow binary type module not specify override rule in FDF file.
394 if len(self
.BinFileList
) > 0:
395 if self
.Rule
== None or self
.Rule
== "":
399 # Get the rule of how to generate Ffs file
401 Rule
= self
.__GetRule
__()
402 GenFdsGlobalVariable
.VerboseLogger( "Packing binaries from inf file : %s" %self
.InfFileName
)
404 # Convert Fv File Type for PI1.1 SMM driver.
406 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
407 if Rule
.FvFileType
== 'DRIVER':
408 Rule
.FvFileType
= 'SMM'
410 # Framework SMM Driver has no SMM FV file type
412 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
413 if Rule
.FvFileType
== 'SMM' or Rule
.FvFileType
== 'SMM_CORE':
414 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File
=self
.InfFileName
)
416 # For the rule only has simpleFile
418 if isinstance (Rule
, RuleSimpleFile
.RuleSimpleFile
) :
419 SectionOutputList
= self
.__GenSimpleFileSection
__(Rule
)
420 FfsOutput
= self
.__GenSimpleFileFfs
__(Rule
, SectionOutputList
)
423 # For Rule has ComplexFile
425 elif isinstance(Rule
, RuleComplexFile
.RuleComplexFile
):
426 InputSectList
, InputSectAlignments
= self
.__GenComplexFileSection
__(Rule
, FvChildAddr
, FvParentAddr
)
427 FfsOutput
= self
.__GenComplexFileFfs
__(Rule
, InputSectList
, InputSectAlignments
)
431 ## __ExtendMacro__() method
433 # Replace macro with its value
435 # @param self The object pointer
436 # @param String The string to be replaced
437 # @retval string Macro replaced string
439 def __ExtendMacro__ (self
, String
):
441 '$(INF_OUTPUT)' : self
.EfiOutputPath
,
442 '$(MODULE_NAME)' : self
.BaseName
,
443 '$(BUILD_NUMBER)': self
.BuildNum
,
444 '$(INF_VERSION)' : self
.VersionString
,
445 '$(NAMED_GUID)' : self
.ModuleGuid
447 String
= GenFdsGlobalVariable
.MacroExtend(String
, MacroDict
)
448 String
= GenFdsGlobalVariable
.MacroExtend(String
, self
.MacroDict
)
451 ## __GetRule__() method
453 # Get correct rule for generating FFS for this INF
455 # @param self The object pointer
456 # @retval Rule Rule object
458 def __GetRule__ (self
) :
460 if self
.CurrentArch
== None:
461 CurrentArchList
= ['common']
463 CurrentArchList
.append(self
.CurrentArch
)
465 for CurrentArch
in CurrentArchList
:
466 RuleName
= 'RULE' + \
468 CurrentArch
.upper() + \
470 self
.ModuleType
.upper()
471 if self
.Rule
!= None:
472 RuleName
= RuleName
+ \
476 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
478 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
481 RuleName
= 'RULE' + \
485 self
.ModuleType
.upper()
487 if self
.Rule
!= None:
488 RuleName
= RuleName
+ \
492 GenFdsGlobalVariable
.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName
, self
.InfFileName
))
494 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
496 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
500 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'Don\'t Find common rule %s for INF %s' \
501 % (RuleName
, self
.InfFileName
))
503 ## __GetPlatformArchList__() method
505 # Get Arch list this INF built under
507 # @param self The object pointer
508 # @retval list Arch list
510 def __GetPlatformArchList__(self
):
512 InfFileKey
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
))
514 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IA32', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
515 if PlatformDataBase
!= None:
516 if InfFileKey
in PlatformDataBase
.Modules
:
517 DscArchList
.append ('IA32')
519 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'X64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
520 if PlatformDataBase
!= None:
521 if InfFileKey
in PlatformDataBase
.Modules
:
522 DscArchList
.append ('X64')
524 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IPF', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
525 if PlatformDataBase
!= None:
526 if InfFileKey
in (PlatformDataBase
.Modules
):
527 DscArchList
.append ('IPF')
529 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'ARM', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
530 if PlatformDataBase
!= None:
531 if InfFileKey
in (PlatformDataBase
.Modules
):
532 DscArchList
.append ('ARM')
534 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'EBC', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
535 if PlatformDataBase
!= None:
536 if InfFileKey
in (PlatformDataBase
.Modules
):
537 DscArchList
.append ('EBC')
539 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'AARCH64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
540 if PlatformDataBase
!= None:
541 if InfFileKey
in (PlatformDataBase
.Modules
):
542 DscArchList
.append ('AARCH64')
546 ## GetCurrentArch() method
548 # Get Arch list of the module from this INF is to be placed into flash
550 # @param self The object pointer
551 # @retval list Arch list
553 def GetCurrentArch(self
) :
555 TargetArchList
= GenFdsGlobalVariable
.ArchList
557 PlatformArchList
= self
.__GetPlatformArchList
__()
559 CurArchList
= TargetArchList
560 if PlatformArchList
!= []:
561 CurArchList
= list(set (TargetArchList
) & set (PlatformArchList
))
562 GenFdsGlobalVariable
.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList
))
565 if self
.KeyStringList
!= []:
566 for Key
in self
.KeyStringList
:
567 Key
= GenFdsGlobalVariable
.MacroExtend(Key
)
568 Target
, Tag
, Arch
= Key
.split('_')
569 if Arch
in CurArchList
:
570 ArchList
.append(Arch
)
571 if Target
not in self
.TargetOverrideList
:
572 self
.TargetOverrideList
.append(Target
)
574 ArchList
= CurArchList
576 UseArchList
= TargetArchList
577 if self
.UseArch
!= None:
579 UseArchList
.append(self
.UseArch
)
580 ArchList
= list(set (UseArchList
) & set (ArchList
))
582 self
.InfFileName
= NormPath(self
.InfFileName
)
583 if len(PlatformArchList
) == 0:
585 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
586 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
588 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
589 if len(ArchList
) == 1:
592 elif len(ArchList
) > 1:
593 if len(PlatformArchList
) == 0:
594 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
))
596 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
))
598 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." \
599 % (self
.InfFileName
, str(PlatformArchList
), GenFdsGlobalVariable
.ActivePlatform
, str(set (UseArchList
) & set (TargetArchList
))))
601 ## __GetEFIOutPutPath__() method
603 # Get the output path for generated files
605 # @param self The object pointer
606 # @retval string Path that output files from this INF go to
608 def __GetEFIOutPutPath__(self
):
611 (ModulePath
, FileName
) = os
.path
.split(self
.InfFileName
)
612 Index
= FileName
.rfind('.')
613 FileName
= FileName
[0:Index
]
614 if self
.OverrideGuid
:
615 FileName
= self
.OverrideGuid
617 if self
.CurrentArch
!= None:
618 Arch
= self
.CurrentArch
620 OutputPath
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
],
626 OutputPath
= os
.path
.realpath(OutputPath
)
629 ## __GenSimpleFileSection__() method
631 # Generate section by specified file name or a list of files with file extension
633 # @param self The object pointer
634 # @param Rule The rule object used to generate section
635 # @retval string File name of the generated section file
637 def __GenSimpleFileSection__(self
, Rule
):
639 # Prepare the parameter of GenSection
643 GenSecInputFile
= None
644 if Rule
.FileName
!= None:
645 GenSecInputFile
= self
.__ExtendMacro
__(Rule
.FileName
)
646 if os
.path
.isabs(GenSecInputFile
):
647 GenSecInputFile
= os
.path
.normpath(GenSecInputFile
)
649 GenSecInputFile
= os
.path
.normpath(os
.path
.join(self
.EfiOutputPath
, GenSecInputFile
))
651 FileList
, IsSect
= Section
.Section
.GetFileList(self
, '', Rule
.FileExtension
)
654 SectionType
= Rule
.SectionType
656 # Convert Fv Section Type for PI1.1 SMM driver.
658 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
659 if SectionType
== 'DXE_DEPEX':
660 SectionType
= 'SMM_DEPEX'
662 # Framework SMM Driver has no SMM_DEPEX section type
664 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
665 if SectionType
== 'SMM_DEPEX':
666 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
668 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
669 if self
.KeepReloc
!= None:
670 NoStrip
= self
.KeepReloc
671 elif Rule
.KeepReloc
!= None:
672 NoStrip
= Rule
.KeepReloc
673 elif self
.ShadowFromInfFile
!= None:
674 NoStrip
= self
.ShadowFromInfFile
677 for File
in FileList
:
680 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
681 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
683 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
684 File
= GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)
686 #Get PE Section alignment when align is set to AUTO
687 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
688 ImageObj
= PeImageClass (File
)
689 if ImageObj
.SectionAlignment
< 0x400:
690 self
.Alignment
= str (ImageObj
.SectionAlignment
)
692 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
695 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
696 if not os
.path
.exists(FileBeforeStrip
) or \
697 (os
.path
.getmtime(File
) > os
.path
.getmtime(FileBeforeStrip
)):
698 CopyLongFilePath(File
, FileBeforeStrip
)
699 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
700 GenFdsGlobalVariable
.GenerateFirmwareImage(
707 if SectionType
== 'TE':
708 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
709 GenFdsGlobalVariable
.GenerateFirmwareImage(
716 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [File
], Section
.Section
.SectionType
[SectionType
])
717 OutputFileList
.append(OutputFile
)
720 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
721 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
722 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
723 GenSecInputFile
= GenFdsGlobalVariable
.MacroExtend(GenSecInputFile
, Dict
, self
.CurrentArch
)
725 #Get PE Section alignment when align is set to AUTO
726 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
727 ImageObj
= PeImageClass (GenSecInputFile
)
728 if ImageObj
.SectionAlignment
< 0x400:
729 self
.Alignment
= str (ImageObj
.SectionAlignment
)
731 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
734 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
735 if not os
.path
.exists(FileBeforeStrip
) or \
736 (os
.path
.getmtime(GenSecInputFile
) > os
.path
.getmtime(FileBeforeStrip
)):
737 CopyLongFilePath(GenSecInputFile
, FileBeforeStrip
)
739 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
740 GenFdsGlobalVariable
.GenerateFirmwareImage(
745 GenSecInputFile
= StrippedFile
747 if SectionType
== 'TE':
748 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
749 GenFdsGlobalVariable
.GenerateFirmwareImage(
754 GenSecInputFile
= TeFile
756 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [GenSecInputFile
], Section
.Section
.SectionType
[SectionType
])
757 OutputFileList
.append(OutputFile
)
759 return OutputFileList
761 ## __GenSimpleFileFfs__() method
765 # @param self The object pointer
766 # @param Rule The rule object used to generate section
767 # @param InputFileList The output file list from GenSection
768 # @retval string Generated FFS file name
770 def __GenSimpleFileFfs__(self
, Rule
, InputFileList
):
771 FfsOutput
= self
.OutputPath
+ \
773 self
.__ExtendMacro
__(Rule
.NameGuid
) + \
776 GenFdsGlobalVariable
.VerboseLogger(self
.__ExtendMacro
__(Rule
.NameGuid
))
778 SectionAlignments
= []
779 for InputFile
in InputFileList
:
780 InputSection
.append(InputFile
)
781 SectionAlignments
.append(Rule
.SectAlignment
)
783 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
784 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
785 if len(PcdValue
) == 0:
786 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
788 if PcdValue
.startswith('{'):
789 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
790 RegistryGuidStr
= PcdValue
791 if len(RegistryGuidStr
) == 0:
792 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
794 self
.ModuleGuid
= RegistryGuidStr
796 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputSection
,
797 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
798 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
799 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
800 SectionAlign
=SectionAlignments
804 ## __GenComplexFileSection__() method
806 # Generate section by sections in Rule
808 # @param self The object pointer
809 # @param Rule The rule object used to generate section
810 # @param FvChildAddr Array of the inside FvImage base address
811 # @param FvParentAddr Parent Fv base address
812 # @retval string File name of the generated section file
814 def __GenComplexFileSection__(self
, Rule
, FvChildAddr
, FvParentAddr
):
815 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
816 if Rule
.KeepReloc
!= None:
817 self
.KeepRelocFromRule
= Rule
.KeepReloc
821 HasGneratedFlag
= False
822 if self
.PcdIsDriver
== 'PEI_PCD_DRIVER':
823 if self
.IsBinaryModule
:
824 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "PEIPcdDataBase.raw")
826 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "PEIPcdDataBase.raw")
827 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "PEIPcdDataBaseSec.raw")
828 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
832 SectFiles
.append(PcdExDbSecName
)
833 SectAlignments
.append(None)
834 elif self
.PcdIsDriver
== 'DXE_PCD_DRIVER':
835 if self
.IsBinaryModule
:
836 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "DXEPcdDataBase.raw")
838 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "DXEPcdDataBase.raw")
839 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "DXEPcdDataBaseSec.raw")
840 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
844 SectFiles
.append(PcdExDbSecName
)
845 SectAlignments
.append(None)
846 for Sect
in Rule
.SectionList
:
847 SecIndex
= '%d' %Index
850 # Convert Fv Section Type for PI1.1 SMM driver.
852 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
853 if Sect
.SectionType
== 'DXE_DEPEX':
854 Sect
.SectionType
= 'SMM_DEPEX'
856 # Framework SMM Driver has no SMM_DEPEX section type
858 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
859 if Sect
.SectionType
== 'SMM_DEPEX':
860 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
862 # process the inside FvImage from FvSection or GuidSection
864 if FvChildAddr
!= []:
865 if isinstance(Sect
, FvImageSection
):
866 Sect
.FvAddr
= FvChildAddr
.pop(0)
867 elif isinstance(Sect
, GuidSection
):
868 Sect
.FvAddr
= FvChildAddr
869 if FvParentAddr
!= None and isinstance(Sect
, GuidSection
):
870 Sect
.FvParentAddr
= FvParentAddr
872 if Rule
.KeyStringList
!= []:
873 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, Rule
.KeyStringList
, self
)
875 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, self
.KeyStringList
, self
)
877 if not HasGneratedFlag
:
878 UniVfrOffsetFileSection
= ""
879 ModuleFileName
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
)
880 InfData
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClass(ModuleFileName
), self
.CurrentArch
]
882 # Search the source list in InfData to find if there are .vfr file exist.
885 VfrUniOffsetList
= []
886 for SourceFile
in InfData
.Sources
:
887 if SourceFile
.Type
.upper() == ".VFR" :
889 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
891 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
892 if SourceFile
.Type
.upper() == ".UNI" :
894 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
896 VfrUniBaseName
["UniOffsetName"] = (self
.BaseName
+ "Strings")
899 if len(VfrUniBaseName
) > 0:
900 VfrUniOffsetList
= self
.__GetBuildOutputMapFileVfrUniInfo
(VfrUniBaseName
)
902 # Generate the Raw data of raw section
904 os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
905 UniVfrOffsetFileName
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
906 UniVfrOffsetFileSection
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ 'Offset' + '.raw')
908 self
.__GenUniVfrOffsetFile
(VfrUniOffsetList
, UniVfrOffsetFileName
)
910 UniVfrOffsetFileNameList
= []
911 UniVfrOffsetFileNameList
.append(UniVfrOffsetFileName
)
912 """Call GenSection"""
913 GenFdsGlobalVariable
.GenerateSection(UniVfrOffsetFileSection
,
914 UniVfrOffsetFileNameList
,
917 os
.remove(UniVfrOffsetFileName
)
918 SectList
.append(UniVfrOffsetFileSection
)
919 HasGneratedFlag
= True
921 for SecName
in SectList
:
922 SectFiles
.append(SecName
)
923 SectAlignments
.append(Align
)
925 return SectFiles
, SectAlignments
927 ## __GenComplexFileFfs__() method
931 # @param self The object pointer
932 # @param Rule The rule object used to generate section
933 # @param InputFileList The output file list from GenSection
934 # @retval string Generated FFS file name
936 def __GenComplexFileFfs__(self
, Rule
, InputFile
, Alignments
):
938 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
939 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
940 if len(PcdValue
) == 0:
941 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
943 if PcdValue
.startswith('{'):
944 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
945 RegistryGuidStr
= PcdValue
946 if len(RegistryGuidStr
) == 0:
947 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
949 self
.ModuleGuid
= RegistryGuidStr
951 FfsOutput
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
952 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputFile
,
953 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
954 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
955 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
956 SectionAlign
=Alignments
960 ## __GetGenFfsCmdParameter__() method
962 # Create parameter string for GenFfs
964 # @param self The object pointer
965 # @param Rule The rule object used to generate section
966 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
968 def __GetGenFfsCmdParameter__(self
, Rule
):
970 result
+= ('-t', Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
])
971 if Rule
.Fixed
!= False:
973 if Rule
.CheckSum
!= False:
976 if Rule
.Alignment
!= None and Rule
.Alignment
!= '':
977 result
+= ('-a', Rule
.Alignment
)
981 ## __GetBuildOutputMapFileVfrUniInfo() method
983 # Find the offset of UNI/INF object offset in the EFI image file.
985 # @param self The object pointer
986 # @param VfrUniBaseName A name list contain the UNI/INF object name.
987 # @retval RetValue A list contain offset of UNI/INF object.
989 def __GetBuildOutputMapFileVfrUniInfo(self
, VfrUniBaseName
):
993 MapFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".map")
995 fInputfile
= open(MapFileName
, "r", 0)
997 FileLinesList
= fInputfile
.readlines()
999 EdkLogger
.error("GenFds", FILE_READ_FAILURE
, "File read failed for %s" %MapFileName
,None)
1003 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %MapFileName
,None)
1006 for eachLine
in FileLinesList
:
1007 for eachName
in VfrUniBaseName
.values():
1008 if eachLine
.find(eachName
) != -1:
1009 eachLine
= eachLine
.strip()
1010 Element
= eachLine
.split()
1012 # MSFT/ICC/EBC map file
1014 if (len(Element
) == 4):
1016 int (Element
[2], 16)
1022 RetValue
.append((eachName
, Element
[2]))
1027 elif (len(Element
) == 2) and Element
[0].startswith("0x"):
1028 RetValue
.append((eachName
, Element
[0]))
1032 ## __GenUniVfrOffsetFile() method
1034 # Generate the offset file for the module which contain VFR or UNI file.
1036 # @param self The object pointer
1037 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
1038 # @param UniVfrOffsetFileName The output offset file name.
1040 def __GenUniVfrOffsetFile(self
, VfrUniOffsetList
, UniVfrOffsetFileName
):
1043 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
1045 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %UniVfrOffsetFileName
,None)
1047 # Use a instance of StringIO to cache data
1048 fStringIO
= StringIO
.StringIO('')
1050 for Item
in VfrUniOffsetList
:
1051 if (Item
[0].find("Strings") != -1):
1053 # UNI offset in image.
1055 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1057 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
1058 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
1059 fStringIO
.write(''.join(UniGuid
))
1060 UniValue
= pack ('Q', int (Item
[1], 16))
1061 fStringIO
.write (UniValue
)
1064 # VFR binary offset in image.
1066 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1068 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
1069 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
1070 fStringIO
.write(''.join(VfrGuid
))
1072 VfrValue
= pack ('Q', int (Item
[1], 16))
1073 fStringIO
.write (VfrValue
)
1076 # write data into file.
1079 fInputfile
.write (fStringIO
.getvalue())
1081 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)