2 # process FFS generation from INF statement
4 # Copyright (c) 2007 - 2015, 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
.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 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IA32', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
559 if PlatformDataBase
!= None:
560 if InfFileKey
in PlatformDataBase
.Modules
:
561 DscArchList
.append ('IA32')
563 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'X64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
564 if PlatformDataBase
!= None:
565 if InfFileKey
in PlatformDataBase
.Modules
:
566 DscArchList
.append ('X64')
568 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'IPF', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
569 if PlatformDataBase
!= None:
570 if InfFileKey
in (PlatformDataBase
.Modules
):
571 DscArchList
.append ('IPF')
573 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'ARM', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
574 if PlatformDataBase
!= None:
575 if InfFileKey
in (PlatformDataBase
.Modules
):
576 DscArchList
.append ('ARM')
578 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'EBC', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
579 if PlatformDataBase
!= None:
580 if InfFileKey
in (PlatformDataBase
.Modules
):
581 DscArchList
.append ('EBC')
583 PlatformDataBase
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'AARCH64', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
584 if PlatformDataBase
!= None:
585 if InfFileKey
in (PlatformDataBase
.Modules
):
586 DscArchList
.append ('AARCH64')
590 ## GetCurrentArch() method
592 # Get Arch list of the module from this INF is to be placed into flash
594 # @param self The object pointer
595 # @retval list Arch list
597 def GetCurrentArch(self
) :
599 TargetArchList
= GenFdsGlobalVariable
.ArchList
601 PlatformArchList
= self
.__GetPlatformArchList
__()
603 CurArchList
= TargetArchList
604 if PlatformArchList
!= []:
605 CurArchList
= list(set (TargetArchList
) & set (PlatformArchList
))
606 GenFdsGlobalVariable
.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList
))
609 if self
.KeyStringList
!= []:
610 for Key
in self
.KeyStringList
:
611 Key
= GenFdsGlobalVariable
.MacroExtend(Key
)
612 Target
, Tag
, Arch
= Key
.split('_')
613 if Arch
in CurArchList
:
614 ArchList
.append(Arch
)
615 if Target
not in self
.TargetOverrideList
:
616 self
.TargetOverrideList
.append(Target
)
618 ArchList
= CurArchList
620 UseArchList
= TargetArchList
621 if self
.UseArch
!= None:
623 UseArchList
.append(self
.UseArch
)
624 ArchList
= list(set (UseArchList
) & set (ArchList
))
626 self
.InfFileName
= NormPath(self
.InfFileName
)
627 if len(PlatformArchList
) == 0:
629 PathClassObj
= PathClass(self
.InfFileName
, GenFdsGlobalVariable
.WorkSpaceDir
)
630 ErrorCode
, ErrorInfo
= PathClassObj
.Validate(".inf")
632 EdkLogger
.error("GenFds", ErrorCode
, ExtraData
=ErrorInfo
)
633 if len(ArchList
) == 1:
636 elif len(ArchList
) > 1:
637 if len(PlatformArchList
) == 0:
638 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
))
640 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
))
642 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." \
643 % (self
.InfFileName
, str(PlatformArchList
), GenFdsGlobalVariable
.ActivePlatform
, str(set (UseArchList
) & set (TargetArchList
))))
645 ## __GetEFIOutPutPath__() method
647 # Get the output path for generated files
649 # @param self The object pointer
650 # @retval string Path that output files from this INF go to
652 def __GetEFIOutPutPath__(self
):
655 (ModulePath
, FileName
) = os
.path
.split(self
.InfFileName
)
656 Index
= FileName
.rfind('.')
657 FileName
= FileName
[0:Index
]
658 if self
.OverrideGuid
:
659 FileName
= self
.OverrideGuid
661 if self
.CurrentArch
!= None:
662 Arch
= self
.CurrentArch
664 OutputPath
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
],
670 OutputPath
= os
.path
.realpath(OutputPath
)
673 ## __GenSimpleFileSection__() method
675 # Generate section by specified file name or a list of files with file extension
677 # @param self The object pointer
678 # @param Rule The rule object used to generate section
679 # @retval string File name of the generated section file
681 def __GenSimpleFileSection__(self
, Rule
):
683 # Prepare the parameter of GenSection
687 GenSecInputFile
= None
688 if Rule
.FileName
!= None:
689 GenSecInputFile
= self
.__ExtendMacro
__(Rule
.FileName
)
690 if os
.path
.isabs(GenSecInputFile
):
691 GenSecInputFile
= os
.path
.normpath(GenSecInputFile
)
693 GenSecInputFile
= os
.path
.normpath(os
.path
.join(self
.EfiOutputPath
, GenSecInputFile
))
695 FileList
, IsSect
= Section
.Section
.GetFileList(self
, '', Rule
.FileExtension
)
698 SectionType
= Rule
.SectionType
700 # Convert Fv Section Type for PI1.1 SMM driver.
702 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
703 if SectionType
== 'DXE_DEPEX':
704 SectionType
= 'SMM_DEPEX'
706 # Framework SMM Driver has no SMM_DEPEX section type
708 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
709 if SectionType
== 'SMM_DEPEX':
710 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
712 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
713 if self
.KeepReloc
!= None:
714 NoStrip
= self
.KeepReloc
715 elif Rule
.KeepReloc
!= None:
716 NoStrip
= Rule
.KeepReloc
717 elif self
.ShadowFromInfFile
!= None:
718 NoStrip
= self
.ShadowFromInfFile
721 for File
in FileList
:
724 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
725 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
727 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
728 File
= GenFdsGlobalVariable
.MacroExtend(File
, Dict
, self
.CurrentArch
)
730 #Get PE Section alignment when align is set to AUTO
731 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
732 ImageObj
= PeImageClass (File
)
733 if ImageObj
.SectionAlignment
< 0x400:
734 self
.Alignment
= str (ImageObj
.SectionAlignment
)
736 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
739 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
740 if not os
.path
.exists(FileBeforeStrip
) or \
741 (os
.path
.getmtime(File
) > os
.path
.getmtime(FileBeforeStrip
)):
742 CopyLongFilePath(File
, FileBeforeStrip
)
743 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
744 GenFdsGlobalVariable
.GenerateFirmwareImage(
751 if SectionType
== 'TE':
752 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
753 GenFdsGlobalVariable
.GenerateFirmwareImage(
760 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [File
], Section
.Section
.SectionType
[SectionType
])
761 OutputFileList
.append(OutputFile
)
764 GenSecOutputFile
= self
.__ExtendMacro
__(Rule
.NameGuid
) + \
765 Ffs
.Ffs
.SectionSuffix
[SectionType
] + 'SEC' + SecNum
766 OutputFile
= os
.path
.join(self
.OutputPath
, GenSecOutputFile
)
767 GenSecInputFile
= GenFdsGlobalVariable
.MacroExtend(GenSecInputFile
, Dict
, self
.CurrentArch
)
769 #Get PE Section alignment when align is set to AUTO
770 if self
.Alignment
== 'Auto' and (SectionType
== 'PE32' or SectionType
== 'TE'):
771 ImageObj
= PeImageClass (GenSecInputFile
)
772 if ImageObj
.SectionAlignment
< 0x400:
773 self
.Alignment
= str (ImageObj
.SectionAlignment
)
775 self
.Alignment
= str (ImageObj
.SectionAlignment
/ 0x400) + 'K'
778 FileBeforeStrip
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.reloc')
779 if not os
.path
.exists(FileBeforeStrip
) or \
780 (os
.path
.getmtime(GenSecInputFile
) > os
.path
.getmtime(FileBeforeStrip
)):
781 CopyLongFilePath(GenSecInputFile
, FileBeforeStrip
)
783 StrippedFile
= os
.path
.join(self
.OutputPath
, ModuleName
+ '.stipped')
784 GenFdsGlobalVariable
.GenerateFirmwareImage(
789 GenSecInputFile
= StrippedFile
791 if SectionType
== 'TE':
792 TeFile
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ 'Te.raw')
793 GenFdsGlobalVariable
.GenerateFirmwareImage(
798 GenSecInputFile
= TeFile
800 GenFdsGlobalVariable
.GenerateSection(OutputFile
, [GenSecInputFile
], Section
.Section
.SectionType
[SectionType
])
801 OutputFileList
.append(OutputFile
)
803 return OutputFileList
805 ## __GenSimpleFileFfs__() method
809 # @param self The object pointer
810 # @param Rule The rule object used to generate section
811 # @param InputFileList The output file list from GenSection
812 # @retval string Generated FFS file name
814 def __GenSimpleFileFfs__(self
, Rule
, InputFileList
):
815 FfsOutput
= self
.OutputPath
+ \
817 self
.__ExtendMacro
__(Rule
.NameGuid
) + \
820 GenFdsGlobalVariable
.VerboseLogger(self
.__ExtendMacro
__(Rule
.NameGuid
))
822 SectionAlignments
= []
823 for InputFile
in InputFileList
:
824 InputSection
.append(InputFile
)
825 SectionAlignments
.append(Rule
.SectAlignment
)
827 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
828 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
829 if len(PcdValue
) == 0:
830 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
832 if PcdValue
.startswith('{'):
833 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
834 RegistryGuidStr
= PcdValue
835 if len(RegistryGuidStr
) == 0:
836 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
838 self
.ModuleGuid
= RegistryGuidStr
840 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputSection
,
841 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
842 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
843 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
844 SectionAlign
=SectionAlignments
848 ## __GenComplexFileSection__() method
850 # Generate section by sections in Rule
852 # @param self The object pointer
853 # @param Rule The rule object used to generate section
854 # @param FvChildAddr Array of the inside FvImage base address
855 # @param FvParentAddr Parent Fv base address
856 # @retval string File name of the generated section file
858 def __GenComplexFileSection__(self
, Rule
, FvChildAddr
, FvParentAddr
):
859 if self
.ModuleType
in ('SEC', 'PEI_CORE', 'PEIM'):
860 if Rule
.KeepReloc
!= None:
861 self
.KeepRelocFromRule
= Rule
.KeepReloc
865 HasGneratedFlag
= False
866 if self
.PcdIsDriver
== 'PEI_PCD_DRIVER':
867 if self
.IsBinaryModule
:
868 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "PEIPcdDataBase.raw")
870 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "PEIPcdDataBase.raw")
871 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "PEIPcdDataBaseSec.raw")
872 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
876 SectFiles
.append(PcdExDbSecName
)
877 SectAlignments
.append(None)
878 elif self
.PcdIsDriver
== 'DXE_PCD_DRIVER':
879 if self
.IsBinaryModule
:
880 PcdExDbFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "DXEPcdDataBase.raw")
882 PcdExDbFileName
= os
.path
.join(self
.EfiOutputPath
, "DXEPcdDataBase.raw")
883 PcdExDbSecName
= os
.path
.join(self
.OutputPath
, "DXEPcdDataBaseSec.raw")
884 GenFdsGlobalVariable
.GenerateSection(PcdExDbSecName
,
888 SectFiles
.append(PcdExDbSecName
)
889 SectAlignments
.append(None)
890 for Sect
in Rule
.SectionList
:
891 SecIndex
= '%d' %Index
894 # Convert Fv Section Type for PI1.1 SMM driver.
896 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) >= 0x0001000A:
897 if Sect
.SectionType
== 'DXE_DEPEX':
898 Sect
.SectionType
= 'SMM_DEPEX'
900 # Framework SMM Driver has no SMM_DEPEX section type
902 if self
.ModuleType
== 'DXE_SMM_DRIVER' and int(self
.PiSpecVersion
, 16) < 0x0001000A:
903 if Sect
.SectionType
== 'SMM_DEPEX':
904 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Framework SMM module doesn't support SMM_DEPEX section type", File
=self
.InfFileName
)
906 # process the inside FvImage from FvSection or GuidSection
908 if FvChildAddr
!= []:
909 if isinstance(Sect
, FvImageSection
):
910 Sect
.FvAddr
= FvChildAddr
.pop(0)
911 elif isinstance(Sect
, GuidSection
):
912 Sect
.FvAddr
= FvChildAddr
913 if FvParentAddr
!= None and isinstance(Sect
, GuidSection
):
914 Sect
.FvParentAddr
= FvParentAddr
916 if Rule
.KeyStringList
!= []:
917 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, Rule
.KeyStringList
, self
)
919 SectList
, Align
= Sect
.GenSection(self
.OutputPath
, self
.ModuleGuid
, SecIndex
, self
.KeyStringList
, self
)
921 if not HasGneratedFlag
:
922 UniVfrOffsetFileSection
= ""
923 ModuleFileName
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.InfFileName
)
924 InfData
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[PathClass(ModuleFileName
), self
.CurrentArch
]
926 # Search the source list in InfData to find if there are .vfr file exist.
929 VfrUniOffsetList
= []
930 for SourceFile
in InfData
.Sources
:
931 if SourceFile
.Type
.upper() == ".VFR" :
933 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
935 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
936 if SourceFile
.Type
.upper() == ".UNI" :
938 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
940 VfrUniBaseName
["UniOffsetName"] = (self
.BaseName
+ "Strings")
943 if len(VfrUniBaseName
) > 0:
944 VfrUniOffsetList
= self
.__GetBuildOutputMapFileVfrUniInfo
(VfrUniBaseName
)
946 # Generate the Raw data of raw section
948 os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
949 UniVfrOffsetFileName
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ '.offset')
950 UniVfrOffsetFileSection
= os
.path
.join( self
.OutputPath
, self
.BaseName
+ 'Offset' + '.raw')
952 self
.__GenUniVfrOffsetFile
(VfrUniOffsetList
, UniVfrOffsetFileName
)
954 UniVfrOffsetFileNameList
= []
955 UniVfrOffsetFileNameList
.append(UniVfrOffsetFileName
)
956 """Call GenSection"""
957 GenFdsGlobalVariable
.GenerateSection(UniVfrOffsetFileSection
,
958 UniVfrOffsetFileNameList
,
961 os
.remove(UniVfrOffsetFileName
)
962 SectList
.append(UniVfrOffsetFileSection
)
963 HasGneratedFlag
= True
965 for SecName
in SectList
:
966 SectFiles
.append(SecName
)
967 SectAlignments
.append(Align
)
969 return SectFiles
, SectAlignments
971 ## __GenComplexFileFfs__() method
975 # @param self The object pointer
976 # @param Rule The rule object used to generate section
977 # @param InputFileList The output file list from GenSection
978 # @retval string Generated FFS file name
980 def __GenComplexFileFfs__(self
, Rule
, InputFile
, Alignments
):
982 if Rule
.NameGuid
!= None and Rule
.NameGuid
.startswith('PCD('):
983 PcdValue
= GenFdsGlobalVariable
.GetPcdValue(Rule
.NameGuid
)
984 if len(PcdValue
) == 0:
985 EdkLogger
.error("GenFds", GENFDS_ERROR
, '%s NOT defined.' \
987 if PcdValue
.startswith('{'):
988 PcdValue
= GuidStructureByteArrayToGuidString(PcdValue
)
989 RegistryGuidStr
= PcdValue
990 if len(RegistryGuidStr
) == 0:
991 EdkLogger
.error("GenFds", GENFDS_ERROR
, 'GUID value for %s in wrong format.' \
993 self
.ModuleGuid
= RegistryGuidStr
995 FfsOutput
= os
.path
.join( self
.OutputPath
, self
.ModuleGuid
+ '.ffs')
996 GenFdsGlobalVariable
.GenerateFfs(FfsOutput
, InputFile
,
997 Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
],
998 self
.ModuleGuid
, Fixed
=Rule
.Fixed
,
999 CheckSum
=Rule
.CheckSum
, Align
=Rule
.Alignment
,
1000 SectionAlign
=Alignments
1004 ## __GetGenFfsCmdParameter__() method
1006 # Create parameter string for GenFfs
1008 # @param self The object pointer
1009 # @param Rule The rule object used to generate section
1010 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
1012 def __GetGenFfsCmdParameter__(self
, Rule
):
1014 result
+= ('-t', Ffs
.Ffs
.FdfFvFileTypeToFileType
[Rule
.FvFileType
])
1015 if Rule
.Fixed
!= False:
1017 if Rule
.CheckSum
!= False:
1020 if Rule
.Alignment
!= None and Rule
.Alignment
!= '':
1021 result
+= ('-a', Rule
.Alignment
)
1025 ## __GetBuildOutputMapFileVfrUniInfo() method
1027 # Find the offset of UNI/INF object offset in the EFI image file.
1029 # @param self The object pointer
1030 # @param VfrUniBaseName A name list contain the UNI/INF object name.
1031 # @retval RetValue A list contain offset of UNI/INF object.
1033 def __GetBuildOutputMapFileVfrUniInfo(self
, VfrUniBaseName
):
1034 MapFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".map")
1035 EfiFileName
= os
.path
.join(self
.EfiOutputPath
, self
.BaseName
+ ".efi")
1036 return GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
1038 ## __GenUniVfrOffsetFile() method
1040 # Generate the offset file for the module which contain VFR or UNI file.
1042 # @param self The object pointer
1043 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
1044 # @param UniVfrOffsetFileName The output offset file name.
1046 def __GenUniVfrOffsetFile(self
, VfrUniOffsetList
, UniVfrOffsetFileName
):
1049 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
1051 EdkLogger
.error("GenFds", FILE_OPEN_FAILURE
, "File open failed for %s" %UniVfrOffsetFileName
,None)
1053 # Use a instance of StringIO to cache data
1054 fStringIO
= StringIO
.StringIO('')
1056 for Item
in VfrUniOffsetList
:
1057 if (Item
[0].find("Strings") != -1):
1059 # UNI offset in image.
1061 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1063 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
1064 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
1065 fStringIO
.write(''.join(UniGuid
))
1066 UniValue
= pack ('Q', int (Item
[1], 16))
1067 fStringIO
.write (UniValue
)
1070 # VFR binary offset in image.
1072 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1074 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
1075 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
1076 fStringIO
.write(''.join(VfrGuid
))
1078 VfrValue
= pack ('Q', int (Item
[1], 16))
1079 fStringIO
.write (VfrValue
)
1082 # write data into file.
1085 fInputfile
.write (fStringIO
.getvalue())
1087 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)