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
= ''
73 ## GetFinalTargetSuffixMap() method
75 # Get final build target list
76 def GetFinalTargetSuffixMap(self
):
77 if not self
.InfModule
or not self
.CurrentArch
:
79 if not self
.FinalTargetSuffixMap
:
80 FinalBuildTargetList
= GenFdsGlobalVariable
.GetModuleCodaTargetList(self
.InfModule
, self
.CurrentArch
)
81 for File
in FinalBuildTargetList
:
82 self
.FinalTargetSuffixMap
.setdefault(os
.path
.splitext(File
)[1], []).append(File
)
84 # Check if current INF module has DEPEX
85 if '.depex' not in self
.FinalTargetSuffixMap
and self
.InfModule
.ModuleType
!= "USER_DEFINED" \
86 and not self
.InfModule
.DxsFile
and not self
.InfModule
.LibraryClass
:
87 ModuleType
= self
.InfModule
.ModuleType
88 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
90 if ModuleType
!= DataType
.SUP_MODULE_USER_DEFINED
:
91 for LibraryClass
in PlatformDataBase
.LibraryClasses
.GetKeys():
92 if LibraryClass
.startswith("NULL") and PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]:
93 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformDataBase
.LibraryClasses
[LibraryClass
, ModuleType
]
95 StrModule
= str(self
.InfModule
)
97 if StrModule
in PlatformDataBase
.Modules
:
98 PlatformModule
= PlatformDataBase
.Modules
[StrModule
]
99 for LibraryClass
in PlatformModule
.LibraryClasses
:
100 if LibraryClass
.startswith("NULL"):
101 self
.InfModule
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
103 DependencyList
= [self
.InfModule
]
106 while len(DependencyList
) > 0:
107 Module
= DependencyList
.pop(0)
110 for Dep
in Module
.Depex
[self
.CurrentArch
, ModuleType
]:
112 DepexList
.append('AND')
113 DepexList
.append('(')
114 DepexList
.extend(Dep
)
115 if DepexList
[-1] == 'END': # no need of a END at this time
117 DepexList
.append(')')
118 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
120 for LibName
in Module
.LibraryClasses
:
121 if LibName
in LibraryInstance
:
123 if PlatformModule
and LibName
in PlatformModule
.LibraryClasses
:
124 LibraryPath
= PlatformModule
.LibraryClasses
[LibName
]
126 LibraryPath
= PlatformDataBase
.LibraryClasses
[LibName
, ModuleType
]
128 LibraryPath
= Module
.LibraryClasses
[LibName
]
131 LibraryModule
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[LibraryPath
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
132 LibraryInstance
[LibName
] = LibraryModule
133 DependencyList
.append(LibraryModule
)
135 Dpx
= DependencyExpression(DepexList
, ModuleType
, True)
136 if len(Dpx
.PostfixNotation
) != 0:
137 # It means this module has DEPEX
138 self
.FinalTargetSuffixMap
['.depex'] = [os
.path
.join(self
.EfiOutputPath
, self
.BaseName
) + '.depex']
139 return self
.FinalTargetSuffixMap
141 ## __InfParse() method
143 # Parse inf file to get module information
145 # @param self The object pointer
146 # @param Dict dictionary contains macro and value pair
148 def __InfParse__(self
, Dict
= {}):
150 GenFdsGlobalVariable
.VerboseLogger( " Begine parsing INf file : %s" %self
.InfFileName
)
152 self
.InfFileName
= self
.InfFileName
.replace('$(WORKSPACE)', '')
153 if len(self
.InfFileName
) > 1 and self
.InfFileName
[0] == '\\' and self
.InfFileName
[1] == '\\':
155 elif self
.InfFileName
[0] == '\\' or self
.InfFileName
[0] == '/' :
156 self
.InfFileName
= self
.InfFileName
[1:]
158 if self
.InfFileName
.find('$') == -1:
159 InfPath
= NormPath(self
.InfFileName
)
160 if not os
.path
.exists(InfPath
):
161 InfPath
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(InfPath
)
162 if not os
.path
.exists(InfPath
):
163 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Non-existant Module %s !" % (self
.InfFileName
))
165 self
.CurrentArch
= self
.GetCurrentArch()
167 # Get the InfClass object
170 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
171 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
173 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
175 if self
.OverrideGuid
:
176 PathClassObj
= ProcessDuplicatedInf(PathClassObj
, self
.OverrideGuid
, GenFdsGlobalVariable
.WorkSpaceDir
)
177 if self
.CurrentArch
!= None:
179 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
181 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
183 self
.BaseName
= Inf
.BaseName
184 self
.ModuleGuid
= Inf
.Guid
185 self
.ModuleType
= Inf
.ModuleType
186 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
187 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
188 if Inf
.AutoGenVersion
< 0x00010005:
189 self
.ModuleType
= Inf
.ComponentType
190 self
.VersionString
= Inf
.Version
191 self
.BinFileList
= Inf
.Binaries
192 self
.SourceFileList
= Inf
.Sources
193 if self
.KeepReloc
== None and Inf
.Shadow
:
194 self
.ShadowFromInfFile
= Inf
.Shadow
197 Inf
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClassObj
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
198 self
.BaseName
= Inf
.BaseName
199 self
.ModuleGuid
= Inf
.Guid
200 self
.ModuleType
= Inf
.ModuleType
201 if Inf
.Specification
!= None and 'PI_SPECIFICATION_VERSION' in Inf
.Specification
:
202 self
.PiSpecVersion
= Inf
.Specification
['PI_SPECIFICATION_VERSION']
203 self
.VersionString
= Inf
.Version
204 self
.BinFileList
= Inf
.Binaries
205 self
.SourceFileList
= Inf
.Sources
206 if self
.BinFileList
== []:
207 EdkLogger
.error("GenFds", GENFDS_ERROR
,
208 "INF %s specified in FDF could not be found in build ARCH %s!" \
209 % (self
.InfFileName
, GenFdsGlobalVariable
.ArchList
))
211 if self
.OverrideGuid
:
212 self
.ModuleGuid
= self
.OverrideGuid
214 if len(self
.SourceFileList
) != 0 and not self
.InDsc
:
215 EdkLogger
.warn("GenFds", GENFDS_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % (self
.InfFileName
))
217 if self
.ModuleType
== 'SMM_CORE' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
218 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
)
220 if Inf
._Defs
!= None and len(Inf
._Defs
) > 0:
221 self
.OptRomDefs
.update(Inf
._Defs
)
225 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, self
.CurrentArch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
226 FdfPcdDict
= GenFdsGlobalVariable
.FdfParser
.Profile
.PcdDict
228 # Workaround here: both build and GenFds tool convert the workspace path to lower case
229 # But INF file path in FDF and DSC file may have real case characters.
230 # Try to convert the path to lower case to see if PCDs value are override by DSC.
232 for DscModule
in Platform
.Modules
:
233 DscModules
[str(DscModule
).lower()] = Platform
.Modules
[DscModule
]
234 for PcdKey
in InfPcds
:
235 Pcd
= InfPcds
[PcdKey
]
236 if not hasattr(Pcd
, 'Offset'):
238 if Pcd
.Type
!= 'PatchableInModule':
240 # Override Patchable PCD value by the value from DSC
242 InfLowerPath
= str(PathClassObj
).lower()
243 if InfLowerPath
in DscModules
and PcdKey
in DscModules
[InfLowerPath
].Pcds
:
244 PatchPcd
= DscModules
[InfLowerPath
].Pcds
[PcdKey
]
245 elif PcdKey
in Platform
.Pcds
:
246 PatchPcd
= Platform
.Pcds
[PcdKey
]
248 if PatchPcd
and Pcd
.Type
== PatchPcd
.Type
:
249 DefaultValue
= PatchPcd
.DefaultValue
252 # Override Patchable PCD value by the value from FDF
254 if PcdKey
in FdfPcdDict
:
255 DefaultValue
= FdfPcdDict
[PcdKey
]
258 if not DscOverride
and not FdfOverride
:
260 # Check value, if value are equal, no need to patch
261 if Pcd
.DatumType
== "VOID*":
262 if Pcd
.DefaultValue
== DefaultValue
or DefaultValue
in [None, '']:
264 # Get the string size from FDF or DSC
265 if DefaultValue
[0] == 'L':
266 # Remove L"", but the '\0' must be appended
267 MaxDatumSize
= str((len(DefaultValue
) - 2) * 2)
268 elif DefaultValue
[0] == '{':
269 MaxDatumSize
= str(len(DefaultValue
.split(',')))
271 MaxDatumSize
= str(len(DefaultValue
) - 1)
273 Pcd
.MaxDatumSize
= PatchPcd
.MaxDatumSize
274 # If no defined the maximum size in DSC, try to get current size from INF
275 if Pcd
.MaxDatumSize
in ['', None]:
276 Pcd
.MaxDatumSize
= str(len(Pcd
.DefaultValue
.split(',')))
279 if Pcd
.DefaultValue
.upper().startswith('0X'):
281 if DefaultValue
.upper().startswith('0X'):
284 PcdValueInImg
= int(Pcd
.DefaultValue
, Base1
)
285 PcdValueInDscOrFdf
= int(DefaultValue
, Base2
)
286 if PcdValueInImg
== PcdValueInDscOrFdf
:
290 # Check the Pcd size and data type
291 if Pcd
.DatumType
== "VOID*":
292 if int(MaxDatumSize
) > int(Pcd
.MaxDatumSize
):
293 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
294 % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, int(MaxDatumSize
) - int(Pcd
.MaxDatumSize
)))
296 if PcdValueInDscOrFdf
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
] \
297 or PcdValueInImg
> FfsInfStatement
._MAX
_SIZE
_TYPE
[Pcd
.DatumType
]:
298 EdkLogger
.error("GenFds", GENFDS_ERROR
, "The size of %s type PCD '%s.%s' doesn't match its data type." \
299 % (Pcd
.DatumType
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
300 self
.PatchPcds
.append((Pcd
, DefaultValue
))
303 self
.PcdIsDriver
= Inf
.PcdIsDriver
304 self
.IsBinaryModule
= Inf
.IsBinaryModule
305 GenFdsGlobalVariable
.VerboseLogger("BaseName : %s" % self
.BaseName
)
306 GenFdsGlobalVariable
.VerboseLogger("ModuleGuid : %s" % self
.ModuleGuid
)
307 GenFdsGlobalVariable
.VerboseLogger("ModuleType : %s" % self
.ModuleType
)
308 GenFdsGlobalVariable
.VerboseLogger("VersionString : %s" % self
.VersionString
)
309 GenFdsGlobalVariable
.VerboseLogger("InfFileName :%s" % self
.InfFileName
)
312 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
315 self
.OutputPath
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, \
316 self
.ModuleGuid
+ self
.BaseName
)
317 if not os
.path
.exists(self
.OutputPath
) :
318 os
.makedirs(self
.OutputPath
)
320 self
.EfiOutputPath
= self
.__GetEFIOutPutPath
__()
321 GenFdsGlobalVariable
.VerboseLogger( "ModuelEFIPath: " + self
.EfiOutputPath
)
325 # Patch EFI file with patch PCD
327 # @param EfiFile: EFI file needs to be patched.
328 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
329 # If passed in file does not end with efi, return as is
331 def PatchEfiFile(self
, EfiFile
, FileType
):
332 if not self
.PatchPcds
:
334 if FileType
!= 'PE32' and self
.ModuleType
!= "USER_DEFINED":
336 if self
.PatchedBinFile
:
337 EdkLogger
.error("GenFds", GENFDS_ERROR
,
338 'Only one binary file can be patched:\n'
339 ' a binary file has been patched: %s\n'
340 ' current file: %s' % (self
.PatchedBinFile
, EfiFile
),
341 File
=self
.InfFileName
)
342 Basename
= os
.path
.basename(EfiFile
)
343 Output
= os
.path
.join(self
.OutputPath
, Basename
)
344 CopyLongFilePath(EfiFile
, Output
)
345 for Pcd
, Value
in self
.PatchPcds
:
346 RetVal
, RetStr
= PatchBinaryFile(Output
, int(Pcd
.Offset
, 0), Pcd
.DatumType
, Value
, Pcd
.MaxDatumSize
)
348 EdkLogger
.error("GenFds", GENFDS_ERROR
, RetStr
, File
=self
.InfFileName
)
349 self
.PatchedBinFile
= os
.path
.normpath(EfiFile
)
355 # @param self The object pointer
356 # @param Dict dictionary contains macro and value pair
357 # @param FvChildAddr Array of the inside FvImage base address
358 # @param FvParentAddr Parent Fv base address
359 # @retval string Generated FFS file name
361 def GenFfs(self
, Dict
= {}, FvChildAddr
= [], FvParentAddr
=None):
363 # Parse Inf file get Module related information
366 self
.__InfParse
__(Dict
)
367 SrcFile
= os
.path
.join( GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
);
368 DestFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
371 SrcPath
= os
.path
.dirname(SrcFile
)
372 SrcFileName
= os
.path
.basename(SrcFile
)
373 SrcFileBase
, SrcFileExt
= os
.path
.splitext(SrcFileName
)
374 DestPath
= os
.path
.dirname(DestFile
)
375 DestFileName
= os
.path
.basename(DestFile
)
376 DestFileBase
, DestFileExt
= os
.path
.splitext(DestFileName
)
380 "${s_path}" : SrcPath
,
381 "${s_dir}" : SrcFileDir
,
382 "${s_name}" : SrcFileName
,
383 "${s_base}" : SrcFileBase
,
384 "${s_ext}" : SrcFileExt
,
387 "${d_path}" : DestPath
,
388 "${d_name}" : DestFileName
,
389 "${d_base}" : DestFileBase
,
390 "${d_ext}" : DestFileExt
393 # Allow binary type module not specify override rule in FDF file.
395 if len(self
.BinFileList
) > 0:
396 if self
.Rule
== None or self
.Rule
== "":
400 # Get the rule of how to generate Ffs file
402 Rule
= self
.__GetRule
__()
403 GenFdsGlobalVariable
.VerboseLogger( "Packing binaries from inf file : %s" %self
.InfFileName
)
405 # Convert Fv File Type for PI1.1 SMM driver.
407 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
408 if Rule
.FvFileType
== 'DRIVER':
409 Rule
.FvFileType
= 'SMM'
411 # Framework SMM Driver has no SMM FV file type
413 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
414 if Rule
.FvFileType
== 'SMM' or Rule
.FvFileType
== 'SMM_CORE':
415 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File
=self
.InfFileName
)
417 # For the rule only has simpleFile
419 if isinstance (Rule
, RuleSimpleFile
.RuleSimpleFile
) :
420 SectionOutputList
= self
.__GenSimpleFileSection
__(Rule
)
421 FfsOutput
= self
.__GenSimpleFileFfs
__(Rule
, SectionOutputList
)
424 # For Rule has ComplexFile
426 elif isinstance(Rule
, RuleComplexFile
.RuleComplexFile
):
427 InputSectList
, InputSectAlignments
= self
.__GenComplexFileSection
__(Rule
, FvChildAddr
, FvParentAddr
)
428 FfsOutput
= self
.__GenComplexFileFfs
__(Rule
, InputSectList
, InputSectAlignments
)
432 ## __ExtendMacro__() method
434 # Replace macro with its value
436 # @param self The object pointer
437 # @param String The string to be replaced
438 # @retval string Macro replaced string
440 def __ExtendMacro__ (self
, String
):
442 '$(INF_OUTPUT)' : self
.EfiOutputPath
,
443 '$(MODULE_NAME)' : self
.BaseName
,
444 '$(BUILD_NUMBER)': self
.BuildNum
,
445 '$(INF_VERSION)' : self
.VersionString
,
446 '$(NAMED_GUID)' : self
.ModuleGuid
448 String
= GenFdsGlobalVariable
.MacroExtend(String
, MacroDict
)
449 String
= GenFdsGlobalVariable
.MacroExtend(String
, self
.MacroDict
)
452 ## __GetRule__() method
454 # Get correct rule for generating FFS for this INF
456 # @param self The object pointer
457 # @retval Rule Rule object
459 def __GetRule__ (self
) :
461 if self
.CurrentArch
== None:
462 CurrentArchList
= ['common']
464 CurrentArchList
.append(self
.CurrentArch
)
466 for CurrentArch
in CurrentArchList
:
467 RuleName
= 'RULE' + \
469 CurrentArch
.upper() + \
471 self
.ModuleType
.upper()
472 if self
.Rule
!= None:
473 RuleName
= RuleName
+ \
477 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
479 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
482 RuleName
= 'RULE' + \
486 self
.ModuleType
.upper()
488 if self
.Rule
!= None:
489 RuleName
= RuleName
+ \
493 GenFdsGlobalVariable
.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName
, self
.InfFileName
))
495 Rule
= GenFdsGlobalVariable
.FdfParser
.Profile
.RuleDict
.get(RuleName
)
497 GenFdsGlobalVariable
.VerboseLogger ("Want To Find Rule Name is : " + RuleName
)
501 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'Don\'t Find common rule %s for INF %s' \
502 % (RuleName
, self
.InfFileName
))
504 ## __GetPlatformArchList__() method
506 # Get Arch list this INF built under
508 # @param self The object pointer
509 # @retval list Arch list
511 def __GetPlatformArchList__(self
):
513 InfFileKey
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
))
515 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IA32', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
516 if PlatformDataBase
!= None:
517 if InfFileKey
in PlatformDataBase
.Modules
:
518 DscArchList
.append ('IA32')
520 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'X64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
521 if PlatformDataBase
!= None:
522 if InfFileKey
in PlatformDataBase
.Modules
:
523 DscArchList
.append ('X64')
525 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IPF', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
526 if PlatformDataBase
!= None:
527 if InfFileKey
in (PlatformDataBase
.Modules
):
528 DscArchList
.append ('IPF')
530 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'ARM', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
531 if PlatformDataBase
!= None:
532 if InfFileKey
in (PlatformDataBase
.Modules
):
533 DscArchList
.append ('ARM')
535 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'EBC', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
536 if PlatformDataBase
!= None:
537 if InfFileKey
in (PlatformDataBase
.Modules
):
538 DscArchList
.append ('EBC')
540 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'AARCH64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
541 if PlatformDataBase
!= None:
542 if InfFileKey
in (PlatformDataBase
.Modules
):
543 DscArchList
.append ('AARCH64')
547 ## GetCurrentArch() method
549 # Get Arch list of the module from this INF is to be placed into flash
551 # @param self The object pointer
552 # @retval list Arch list
554 def GetCurrentArch(self
) :
556 TargetArchList
= GenFdsGlobalVariable
.ArchList
558 PlatformArchList
= self
.__GetPlatformArchList
__()
560 CurArchList
= TargetArchList
561 if PlatformArchList
!= []:
562 CurArchList
= list(set (TargetArchList
) & set (PlatformArchList
))
563 GenFdsGlobalVariable
.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList
))
566 if self
.KeyStringList
!= []:
567 for Key
in self
.KeyStringList
:
568 Key
= GenFdsGlobalVariable
.MacroExtend(Key
)
569 Target
, Tag
, Arch
= Key
.split('_')
570 if Arch
in CurArchList
:
571 ArchList
.append(Arch
)
572 if Target
not in self
.TargetOverrideList
:
573 self
.TargetOverrideList
.append(Target
)
575 ArchList
= CurArchList
577 UseArchList
= TargetArchList
578 if self
.UseArch
!= None:
580 UseArchList
.append(self
.UseArch
)
581 ArchList
= list(set (UseArchList
) & set (ArchList
))
583 self
.InfFileName
= NormPath(self
.InfFileName
)
584 if len(PlatformArchList
) == 0:
586 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
587 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
589 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
590 if len(ArchList
) == 1:
593 elif len(ArchList
) > 1:
594 if len(PlatformArchList
) == 0:
595 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
))
597 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
))
599 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." \
600 % (self
.InfFileName
, str(PlatformArchList
), GenFdsGlobalVariable
.ActivePlatform
, str(set (UseArchList
) & set (TargetArchList
))))
602 ## __GetEFIOutPutPath__() method
604 # Get the output path for generated files
606 # @param self The object pointer
607 # @retval string Path that output files from this INF go to
609 def __GetEFIOutPutPath__(self
):
612 (ModulePath
, FileName
) = os
.path
.split(self
.InfFileName
)
613 Index
= FileName
.rfind('.')
614 FileName
= FileName
[0:Index
]
615 if self
.OverrideGuid
:
616 FileName
= self
.OverrideGuid
618 if self
.CurrentArch
!= None:
619 Arch
= self
.CurrentArch
621 OutputPath
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
],
627 OutputPath
= os
.path
.realpath(OutputPath
)
630 ## __GenSimpleFileSection__() method
632 # Generate section by specified file name or a list of files with file extension
634 # @param self The object pointer
635 # @param Rule The rule object used to generate section
636 # @retval string File name of the generated section file
638 def __GenSimpleFileSection__(self
, Rule
):
640 # Prepare the parameter of GenSection
644 GenSecInputFile
= None
645 if Rule
.FileName
!= None:
646 GenSecInputFile
= self
.__ExtendMacro
__(Rule
.FileName
)
647 if os
.path
.isabs(GenSecInputFile
):
648 GenSecInputFile
= os
.path
.normpath(GenSecInputFile
)
650 GenSecInputFile
= os
.path
.normpath(os
.path
.join(self
.EfiOutputPath
, GenSecInputFile
))
652 FileList
, IsSect
= Section
.Section
.GetFileList(self
, '', Rule
.FileExtension
)
655 SectionType
= Rule
.SectionType
657 # Convert Fv Section Type for PI1.1 SMM driver.
659 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
660 if SectionType
== 'DXE_DEPEX':
661 SectionType
= 'SMM_DEPEX'
663 # Framework SMM Driver has no SMM_DEPEX section type
665 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
666 if SectionType
== 'SMM_DEPEX':
667 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
669 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
670 if self
.KeepReloc
!= None:
671 NoStrip
= self
.KeepReloc
672 elif Rule
.KeepReloc
!= None:
673 NoStrip
= Rule
.KeepReloc
674 elif self
.ShadowFromInfFile
!= None:
675 NoStrip
= self
.ShadowFromInfFile
678 for File
in FileList
:
681 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
682 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
684 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
685 File
= GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)
687 #Get PE Section alignment when align is set to AUTO
688 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
689 ImageObj
= PeImageClass (File
)
690 if ImageObj
.SectionAlignment
< 0x400:
691 self
.Alignment
= str (ImageObj
.SectionAlignment
)
693 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
696 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
697 if not os
.path
.exists(FileBeforeStrip
) or \
698 (os
.path
.getmtime(File
) > os
.path
.getmtime(FileBeforeStrip
)):
699 CopyLongFilePath(File
, FileBeforeStrip
)
700 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
701 GenFdsGlobalVariable
.GenerateFirmwareImage(
708 if SectionType
== 'TE':
709 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
710 GenFdsGlobalVariable
.GenerateFirmwareImage(
717 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [File
], Section
.Section
.SectionType
[SectionType
])
718 OutputFileList
.append(OutputFile
)
721 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
722 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
723 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
724 GenSecInputFile
= GenFdsGlobalVariable
.MacroExtend(GenSecInputFile
, Dict
, self
.CurrentArch
)
726 #Get PE Section alignment when align is set to AUTO
727 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
728 ImageObj
= PeImageClass (GenSecInputFile
)
729 if ImageObj
.SectionAlignment
< 0x400:
730 self
.Alignment
= str (ImageObj
.SectionAlignment
)
732 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
735 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
736 if not os
.path
.exists(FileBeforeStrip
) or \
737 (os
.path
.getmtime(GenSecInputFile
) > os
.path
.getmtime(FileBeforeStrip
)):
738 CopyLongFilePath(GenSecInputFile
, FileBeforeStrip
)
740 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
741 GenFdsGlobalVariable
.GenerateFirmwareImage(
746 GenSecInputFile
= StrippedFile
748 if SectionType
== 'TE':
749 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
750 GenFdsGlobalVariable
.GenerateFirmwareImage(
755 GenSecInputFile
= TeFile
757 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [GenSecInputFile
], Section
.Section
.SectionType
[SectionType
])
758 OutputFileList
.append(OutputFile
)
760 return OutputFileList
762 ## __GenSimpleFileFfs__() method
766 # @param self The object pointer
767 # @param Rule The rule object used to generate section
768 # @param InputFileList The output file list from GenSection
769 # @retval string Generated FFS file name
771 def __GenSimpleFileFfs__(self
, Rule
, InputFileList
):
772 FfsOutput
= self
.OutputPath
+ \
774 self
.__ExtendMacro
__(Rule
.NameGuid
) + \
777 GenFdsGlobalVariable
.VerboseLogger(self
.__ExtendMacro
__(Rule
.NameGuid
))
779 SectionAlignments
= []
780 for InputFile
in InputFileList
:
781 InputSection
.append(InputFile
)
782 SectionAlignments
.append(Rule
.SectAlignment
)
784 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
785 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
786 if len(PcdValue
) == 0:
787 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
789 if PcdValue
.startswith('{'):
790 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
791 RegistryGuidStr
= PcdValue
792 if len(RegistryGuidStr
) == 0:
793 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
795 self
.ModuleGuid
= RegistryGuidStr
797 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputSection
,
798 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
799 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
800 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
801 SectionAlign
=SectionAlignments
805 ## __GenComplexFileSection__() method
807 # Generate section by sections in Rule
809 # @param self The object pointer
810 # @param Rule The rule object used to generate section
811 # @param FvChildAddr Array of the inside FvImage base address
812 # @param FvParentAddr Parent Fv base address
813 # @retval string File name of the generated section file
815 def __GenComplexFileSection__(self
, Rule
, FvChildAddr
, FvParentAddr
):
816 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
817 if Rule
.KeepReloc
!= None:
818 self
.KeepRelocFromRule
= Rule
.KeepReloc
822 HasGneratedFlag
= False
823 if self
.PcdIsDriver
== 'PEI_PCD_DRIVER':
824 if self
.IsBinaryModule
:
825 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "PEIPcdDataBase.raw")
827 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "PEIPcdDataBase.raw")
828 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "PEIPcdDataBaseSec.raw")
829 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
833 SectFiles
.append(PcdExDbSecName
)
834 SectAlignments
.append(None)
835 elif self
.PcdIsDriver
== 'DXE_PCD_DRIVER':
836 if self
.IsBinaryModule
:
837 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "DXEPcdDataBase.raw")
839 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "DXEPcdDataBase.raw")
840 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "DXEPcdDataBaseSec.raw")
841 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
845 SectFiles
.append(PcdExDbSecName
)
846 SectAlignments
.append(None)
847 for Sect
in Rule
.SectionList
:
848 SecIndex
= '%d' %Index
851 # Convert Fv Section Type for PI1.1 SMM driver.
853 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
854 if Sect
.SectionType
== 'DXE_DEPEX':
855 Sect
.SectionType
= 'SMM_DEPEX'
857 # Framework SMM Driver has no SMM_DEPEX section type
859 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
860 if Sect
.SectionType
== 'SMM_DEPEX':
861 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
863 # process the inside FvImage from FvSection or GuidSection
865 if FvChildAddr
!= []:
866 if isinstance(Sect
, FvImageSection
):
867 Sect
.FvAddr
= FvChildAddr
.pop(0)
868 elif isinstance(Sect
, GuidSection
):
869 Sect
.FvAddr
= FvChildAddr
870 if FvParentAddr
!= None and isinstance(Sect
, GuidSection
):
871 Sect
.FvParentAddr
= FvParentAddr
873 if Rule
.KeyStringList
!= []:
874 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, Rule
.KeyStringList
, self
)
876 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, self
.KeyStringList
, self
)
878 if not HasGneratedFlag
:
879 UniVfrOffsetFileSection
= ""
880 ModuleFileName
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
)
881 InfData
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClass(ModuleFileName
), self
.CurrentArch
]
883 # Search the source list in InfData to find if there are .vfr file exist.
886 VfrUniOffsetList
= []
887 for SourceFile
in InfData
.Sources
:
888 if SourceFile
.Type
.upper() == ".VFR" :
890 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
892 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
893 if SourceFile
.Type
.upper() == ".UNI" :
895 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
897 VfrUniBaseName
["UniOffsetName"] = (self
.BaseName
+ "Strings")
900 if len(VfrUniBaseName
) > 0:
901 VfrUniOffsetList
= self
.__GetBuildOutputMapFileVfrUniInfo
(VfrUniBaseName
)
903 # Generate the Raw data of raw section
905 os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
906 UniVfrOffsetFileName
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
907 UniVfrOffsetFileSection
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ 'Offset' + '.raw')
909 self
.__GenUniVfrOffsetFile
(VfrUniOffsetList
, UniVfrOffsetFileName
)
911 UniVfrOffsetFileNameList
= []
912 UniVfrOffsetFileNameList
.append(UniVfrOffsetFileName
)
913 """Call GenSection"""
914 GenFdsGlobalVariable
.GenerateSection(UniVfrOffsetFileSection
,
915 UniVfrOffsetFileNameList
,
918 os
.remove(UniVfrOffsetFileName
)
919 SectList
.append(UniVfrOffsetFileSection
)
920 HasGneratedFlag
= True
922 for SecName
in SectList
:
923 SectFiles
.append(SecName
)
924 SectAlignments
.append(Align
)
926 return SectFiles
, SectAlignments
928 ## __GenComplexFileFfs__() method
932 # @param self The object pointer
933 # @param Rule The rule object used to generate section
934 # @param InputFileList The output file list from GenSection
935 # @retval string Generated FFS file name
937 def __GenComplexFileFfs__(self
, Rule
, InputFile
, Alignments
):
939 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
940 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
941 if len(PcdValue
) == 0:
942 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
944 if PcdValue
.startswith('{'):
945 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
946 RegistryGuidStr
= PcdValue
947 if len(RegistryGuidStr
) == 0:
948 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
950 self
.ModuleGuid
= RegistryGuidStr
952 FfsOutput
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
953 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputFile
,
954 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
955 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
956 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
957 SectionAlign
=Alignments
961 ## __GetGenFfsCmdParameter__() method
963 # Create parameter string for GenFfs
965 # @param self The object pointer
966 # @param Rule The rule object used to generate section
967 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
969 def __GetGenFfsCmdParameter__(self
, Rule
):
971 result
+= ('-t', Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
])
972 if Rule
.Fixed
!= False:
974 if Rule
.CheckSum
!= False:
977 if Rule
.Alignment
!= None and Rule
.Alignment
!= '':
978 result
+= ('-a', Rule
.Alignment
)
982 ## __GetBuildOutputMapFileVfrUniInfo() method
984 # Find the offset of UNI/INF object offset in the EFI image file.
986 # @param self The object pointer
987 # @param VfrUniBaseName A name list contain the UNI/INF object name.
988 # @retval RetValue A list contain offset of UNI/INF object.
990 def __GetBuildOutputMapFileVfrUniInfo(self
, VfrUniBaseName
):
994 MapFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".map")
996 fInputfile
= open(MapFileName
, "r", 0)
998 FileLinesList
= fInputfile
.readlines()
1000 EdkLogger
.error("GenFds", FILE_READ_FAILURE
, "File read failed for %s" %MapFileName
,None)
1004 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %MapFileName
,None)
1007 for eachLine
in FileLinesList
:
1008 for eachName
in VfrUniBaseName
.values():
1009 if eachLine
.find(eachName
) != -1:
1010 eachLine
= eachLine
.strip()
1011 Element
= eachLine
.split()
1013 # MSFT/ICC/EBC map file
1015 if (len(Element
) == 4):
1017 int (Element
[2], 16)
1023 RetValue
.append((eachName
, Element
[2]))
1028 elif (len(Element
) == 2) and Element
[0].startswith("0x"):
1029 RetValue
.append((eachName
, Element
[0]))
1033 ## __GenUniVfrOffsetFile() method
1035 # Generate the offset file for the module which contain VFR or UNI file.
1037 # @param self The object pointer
1038 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
1039 # @param UniVfrOffsetFileName The output offset file name.
1041 def __GenUniVfrOffsetFile(self
, VfrUniOffsetList
, UniVfrOffsetFileName
):
1044 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
1046 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %UniVfrOffsetFileName
,None)
1048 # Use a instance of StringIO to cache data
1049 fStringIO
= StringIO
.StringIO('')
1051 for Item
in VfrUniOffsetList
:
1052 if (Item
[0].find("Strings") != -1):
1054 # UNI offset in image.
1056 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1058 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
1059 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
1060 fStringIO
.write(''.join(UniGuid
))
1061 UniValue
= pack ('Q', int (Item
[1], 16))
1062 fStringIO
.write (UniValue
)
1065 # VFR binary offset in image.
1067 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1069 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
1070 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
1071 fStringIO
.write(''.join(VfrGuid
))
1073 VfrValue
= pack ('Q', int (Item
[1], 16))
1074 fStringIO
.write (VfrValue
)
1077 # write data into file.
1080 fInputfile
.write (fStringIO
.getvalue())
1082 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)