ffb7604df347e71749971544042378de27716e37
[efi/basetools/.git] / Source / Python / GenFds / GenFds.py
1 ## @file
2 # generate flash image
3 #
4 #  Copyright (c) 2007 - 2010, Intel Corporation
5 #
6 #  All rights reserved. This program and the accompanying materials
7 #  are licensed and made available under the terms and conditions of the BSD License
8 #  which accompanies this distribution.  The full text of the license may be found at
9 #  http://opensource.org/licenses/bsd-license.php
10 #
11 #  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 #
14
15 ##
16 # Import Modules
17 #
18 from optparse import OptionParser
19 import sys
20 import os
21 import linecache
22 import FdfParser
23 import Common.BuildToolError as BuildToolError
24 from GenFdsGlobalVariable import GenFdsGlobalVariable
25 from Workspace.WorkspaceDatabase import WorkspaceDatabase
26 from Workspace.BuildClassObject import PcdClassObject
27 from Workspace.BuildClassObject import ModuleBuildClassObject
28 import RuleComplexFile
29 from EfiSection import EfiSection
30 import StringIO
31 import Common.TargetTxtClassObject as TargetTxtClassObject
32 import Common.ToolDefClassObject as ToolDefClassObject
33 import Common.DataType
34 import Common.GlobalData as GlobalData
35 from Common import EdkLogger
36 from Common.String import *
37 from Common.Misc import DirCache,PathClass
38
39 ## Version and Copyright
40 versionNumber = "1.0"
41 __version__ = "%prog Version " + versionNumber
42 __copyright__ = "Copyright (c) 2007 - 2010, Intel Corporation  All rights reserved."
43
44 ## Tool entrance method
45 #
46 # This method mainly dispatch specific methods per the command line options.
47 # If no error found, return zero value so the caller of this tool can know
48 # if it's executed successfully or not.
49 #
50 #   @retval 0     Tool was successful
51 #   @retval 1     Tool failed
52 #
53 def main():
54     global Options
55     Options = myOptionParser()
56
57     global Workspace
58     Workspace = ""
59     ArchList = None
60     ReturnCode = 0
61
62     EdkLogger.Initialize()
63     try:
64         if Options.verbose != None:
65             EdkLogger.SetLevel(EdkLogger.VERBOSE)
66             GenFdsGlobalVariable.VerboseMode = True
67             
68         if Options.FixedAddress != None:
69             GenFdsGlobalVariable.FixedLoadAddress = True
70             
71         if Options.quiet != None:
72             EdkLogger.SetLevel(EdkLogger.QUIET)
73         if Options.debug != None:
74             EdkLogger.SetLevel(Options.debug + 1)
75             GenFdsGlobalVariable.DebugLevel = Options.debug
76         else:
77             EdkLogger.SetLevel(EdkLogger.INFO)
78
79         if (Options.Workspace == None):
80             EdkLogger.error("GenFds", OPTION_MISSING, "WORKSPACE not defined",
81                             ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
82         elif not os.path.exists(Options.Workspace):
83             EdkLogger.error("GenFds", PARAMETER_INVALID, "WORKSPACE is invalid",
84                             ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
85         else:
86             Workspace = os.path.normcase(Options.Workspace)
87             GenFdsGlobalVariable.WorkSpaceDir = Workspace
88             if 'EDK_SOURCE' in os.environ.keys():
89                 GenFdsGlobalVariable.EdkSourceDir = os.path.normcase(os.environ['EDK_SOURCE'])
90             if (Options.debug):
91                 GenFdsGlobalVariable.VerboseLogger( "Using Workspace:" + Workspace)
92         os.chdir(GenFdsGlobalVariable.WorkSpaceDir)
93
94         if (Options.filename):
95             FdfFilename = Options.filename
96             FdfFilename = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename)
97
98             if FdfFilename[0:2] == '..':
99                 FdfFilename = os.path.realpath(FdfFilename)
100             if not os.path.isabs (FdfFilename):
101                 FdfFilename = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, FdfFilename)
102             if not os.path.exists(FdfFilename):
103                 EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=FdfFilename)
104             if os.path.normcase (FdfFilename).find(Workspace) != 0:
105                 EdkLogger.error("GenFds", FILE_NOT_FOUND, "FdfFile doesn't exist in Workspace!")
106
107             GenFdsGlobalVariable.FdfFile = FdfFilename
108             GenFdsGlobalVariable.FdfFileTimeStamp = os.path.getmtime(FdfFilename)
109         else:
110             EdkLogger.error("GenFds", OPTION_MISSING, "Missing FDF filename")
111
112         if (Options.BuildTarget):
113             GenFdsGlobalVariable.TargetName = Options.BuildTarget
114         else:
115             EdkLogger.error("GenFds", OPTION_MISSING, "Missing build target")
116
117         if (Options.ToolChain):
118             GenFdsGlobalVariable.ToolChainTag = Options.ToolChain
119         else:
120             EdkLogger.error("GenFds", OPTION_MISSING, "Missing tool chain tag")
121
122         if (Options.activePlatform):
123             ActivePlatform = Options.activePlatform
124             ActivePlatform = GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform)
125
126             if ActivePlatform[0:2] == '..':
127                 ActivePlatform = os.path.realpath(ActivePlatform)
128
129             if not os.path.isabs (ActivePlatform):
130                 ActivePlatform = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, ActivePlatform)
131
132             if not os.path.exists(ActivePlatform)  :
133                 EdkLogger.error("GenFds", FILE_NOT_FOUND, "ActivePlatform doesn't exist!")
134
135             if os.path.normcase (ActivePlatform).find(Workspace) != 0:
136                 EdkLogger.error("GenFds", FILE_NOT_FOUND, "ActivePlatform doesn't exist in Workspace!")
137
138             ActivePlatform = ActivePlatform[len(Workspace):]
139             if len(ActivePlatform) > 0 :
140                 if ActivePlatform[0] == '\\' or ActivePlatform[0] == '/':
141                     ActivePlatform = ActivePlatform[1:]
142             else:
143                 EdkLogger.error("GenFds", FILE_NOT_FOUND, "ActivePlatform doesn't exist!")
144         else:
145             EdkLogger.error("GenFds", OPTION_MISSING, "Missing active platform")
146
147         GenFdsGlobalVariable.ActivePlatform = PathClass(NormPath(ActivePlatform), Workspace)
148
149         BuildConfigurationFile = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, "Conf/target.txt"))
150         if os.path.isfile(BuildConfigurationFile) == True:
151             TargetTxtClassObject.TargetTxtClassObject(BuildConfigurationFile)
152         else:
153             EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile)
154
155         if Options.Macros:
156             for Pair in Options.Macros:
157                 Pair.strip('"')
158                 List = Pair.split('=')
159                 if len(List) == 2:
160                     if List[0].strip() == "EFI_SOURCE":
161                         GlobalData.gEfiSource = List[1].strip()
162                         continue
163                     elif List[0].strip() == "EDK_SOURCE":
164                         GlobalData.gEdkSource = List[1].strip()
165                         continue
166                     else:
167                         GlobalData.gEdkGlobal[List[0].strip()] = List[1].strip()
168                         FdfParser.InputMacroDict[List[0].strip()] = List[1].strip()
169                 else:
170                     FdfParser.InputMacroDict[List[0].strip()] = ""
171
172         """call Workspace build create database"""
173         os.environ["WORKSPACE"] = Workspace
174         BuildWorkSpace = WorkspaceDatabase(':memory:', FdfParser.InputMacroDict)
175         BuildWorkSpace.InitDatabase()
176         
177         #
178         # Get files real name in workspace dir
179         #
180         GlobalData.gAllFiles = DirCache(Workspace)
181         GlobalData.gWorkspace = Workspace
182
183         if (Options.archList) :
184             ArchList = Options.archList.split(',')
185         else:
186 #            EdkLogger.error("GenFds", OPTION_MISSING, "Missing build ARCH")
187             ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON'].SupArchList
188
189         TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON'].SupArchList) & set(ArchList)
190         if len(TargetArchList) == 0:
191             EdkLogger.error("GenFds", GENFDS_ERROR, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList), str(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON'].SupArchList)))
192         
193         for Arch in ArchList:
194             GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].OutputDirectory)
195
196         if (Options.outputDir):
197             OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(Options.outputDir)
198             if not os.path.isabs (Options.outputDir):
199                 Options.outputDir = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, Options.outputDir)
200             if os.path.normcase (Options.outputDir).find(Workspace) != 0:
201                 EdkLogger.error("GenFds", FILE_NOT_FOUND, "OutputDir doesn't exist in Workspace!")
202             for Arch in ArchList:
203                 GenFdsGlobalVariable.OutputDirDict[Arch] = OutputDirFromCommandLine
204         else:
205             for Arch in ArchList:
206                 GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.join(GenFdsGlobalVariable.OutputDirFromDscDict[Arch], GenFdsGlobalVariable.TargetName + '_' + GenFdsGlobalVariable.ToolChainTag)
207
208         for Key in GenFdsGlobalVariable.OutputDirDict:
209             OutputDir = GenFdsGlobalVariable.OutputDirDict[Key]
210             if OutputDir[0:2] == '..':
211                 OutputDir = os.path.realpath(OutputDir)
212
213             if OutputDir[1] != ':':
214                 OutputDir = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, OutputDir)
215
216             if not os.path.exists(OutputDir):
217                 EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=OutputDir)
218             GenFdsGlobalVariable.OutputDirDict[Key] = OutputDir
219
220         """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
221         FdfParserObj = FdfParser.FdfParser(FdfFilename)
222         FdfParserObj.ParseFile()
223
224         if FdfParserObj.CycleReferenceCheck():
225             EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Cycle Reference Detected in FDF file")
226
227         if (Options.uiFdName) :
228             if Options.uiFdName.upper() in FdfParserObj.Profile.FdDict.keys():
229                 GenFds.OnlyGenerateThisFd = Options.uiFdName
230             else:
231                 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
232                                 "No such an FD in FDF file: %s" % Options.uiFdName)
233
234         if (Options.uiFvName) :
235             if Options.uiFvName.upper() in FdfParserObj.Profile.FvDict.keys():
236                 GenFds.OnlyGenerateThisFv = Options.uiFvName
237             else:
238                 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
239                                 "No such an FV in FDF file: %s" % Options.uiFvName)
240
241         """Modify images from build output if the feature of loading driver at fixed address is on."""
242         if GenFdsGlobalVariable.FixedLoadAddress:
243             GenFds.PreprocessImage(BuildWorkSpace, GenFdsGlobalVariable.ActivePlatform)
244         """Call GenFds"""
245         GenFds.GenFd('', FdfParserObj, BuildWorkSpace, ArchList)
246
247         """Generate GUID cross reference file"""
248         GenFds.GenerateGuidXRefFile(BuildWorkSpace, ArchList)
249
250         """Display FV space info."""
251         GenFds.DisplayFvSpaceInfo(FdfParserObj)
252
253     except FdfParser.Warning, X:
254         EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError = False)
255         ReturnCode = FORMAT_INVALID
256     except FatalError, X:
257         if Options.debug != None:
258             import traceback
259             EdkLogger.quiet(traceback.format_exc())
260         ReturnCode = X.args[0]
261     except:
262         import traceback
263         EdkLogger.error(
264                     "\nPython",
265                     CODE_ERROR,
266                     "Tools code failure",
267                     ExtraData="Please submit bug report in www.TianoCore.org, attaching following call stack trace!\n",
268                     RaiseError=False
269                     )
270         EdkLogger.quiet(traceback.format_exc())
271         ReturnCode = CODE_ERROR
272     return ReturnCode
273
274 gParamCheck = []
275 def SingleCheckCallback(option, opt_str, value, parser):
276     if option not in gParamCheck:
277         setattr(parser.values, option.dest, value)
278         gParamCheck.append(option)
279     else:
280         parser.error("Option %s only allows one instance in command line!" % option)
281         
282 ## Parse command line options
283 #
284 # Using standard Python module optparse to parse command line option of this tool.
285 #
286 #   @retval Opt   A optparse.Values object containing the parsed options
287 #   @retval Args  Target of build command
288 #
289 def myOptionParser():
290     usage = "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""
291     Parser = OptionParser(usage=usage,description=__copyright__,version="%prog " + str(versionNumber))
292     Parser.add_option("-f", "--file", dest="filename", type="string", help="Name of FDF file to convert", action="callback", callback=SingleCheckCallback)
293     Parser.add_option("-a", "--arch", dest="archList", help="comma separated list containing one or more of: IA32, X64, IPF, ARM or EBC which should be built, overrides target.txt?s TARGET_ARCH")
294     Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
295     Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed.")
296     Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")
297     Parser.add_option("-p", "--platform", type="string", dest="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",
298                       action="callback", callback=SingleCheckCallback)
299     Parser.add_option("-w", "--workspace", type="string", dest="Workspace", default=os.environ.get('WORKSPACE'), help="Set the WORKSPACE",
300                       action="callback", callback=SingleCheckCallback)
301     Parser.add_option("-o", "--outputDir", type="string", dest="outputDir", help="Name of Build Output directory",
302                       action="callback", callback=SingleCheckCallback)
303     Parser.add_option("-r", "--rom_image", dest="uiFdName", help="Build the image using the [FD] section named by FdUiName.")
304     Parser.add_option("-i", "--FvImage", dest="uiFvName", help="Buld the FV image using the [FV] section named by UiFvName")
305     Parser.add_option("-b", "--buildtarget", type="choice", choices=['DEBUG','RELEASE'], dest="BuildTarget", help="Build TARGET is one of list: DEBUG, RELEASE.",
306                       action="callback", callback=SingleCheckCallback)
307     Parser.add_option("-t", "--tagname", type="string", dest="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",
308                       action="callback", callback=SingleCheckCallback)
309     Parser.add_option("-D", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".")
310     Parser.add_option("-s", "--specifyaddress", dest="FixedAddress", action="store_true", type=None, help="Specify driver load address.")
311     (Options, args) = Parser.parse_args()
312     return Options
313
314 ## The class implementing the EDK2 flash image generation process
315 #
316 #   This process includes:
317 #       1. Collect workspace information, includes platform and module information
318 #       2. Call methods of Fd class to generate FD
319 #       3. Call methods of Fv class to generate FV that not belong to FD
320 #
321 class GenFds :
322     FdfParsef = None
323     # FvName, FdName, CapName in FDF, Image file name
324     ImageBinDict = {}
325     OnlyGenerateThisFd = None
326     OnlyGenerateThisFv = None
327
328     ## GenFd()
329     #
330     #   @param  OutputDir           Output directory
331     #   @param  FdfParser           FDF contents parser
332     #   @param  Workspace           The directory of workspace
333     #   @param  ArchList            The Arch list of platform
334     #
335     def GenFd (OutputDir, FdfParser, WorkSpace, ArchList):
336         GenFdsGlobalVariable.SetDir ('', FdfParser, WorkSpace, ArchList)
337
338         GenFdsGlobalVariable.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")
339         if GenFds.OnlyGenerateThisFd != None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():
340             FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict.get(GenFds.OnlyGenerateThisFd.upper())
341             if FdObj != None:
342                 FdObj.GenFd()
343         elif GenFds.OnlyGenerateThisFd == None:
344             for FdName in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():
345                 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[FdName]
346                 FdObj.GenFd()
347
348         GenFdsGlobalVariable.VerboseLogger("\n Generate other FV images! ")
349         if GenFds.OnlyGenerateThisFv != None and GenFds.OnlyGenerateThisFv.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys():
350             FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(GenFds.OnlyGenerateThisFv.upper())
351             if FvObj != None:
352                 Buffer = StringIO.StringIO()
353                 # Get FV base Address
354                 FvObj.AddToBuffer(Buffer, None, GenFds.GetFvBlockSize(FvObj))
355                 Buffer.close()
356                 return
357         elif GenFds.OnlyGenerateThisFv == None:
358             for FvName in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys():
359                 Buffer = StringIO.StringIO('')
360                 FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict[FvName]
361                 # Get FV base Address
362                 FvObj.AddToBuffer(Buffer, None, GenFds.GetFvBlockSize(FvObj))
363                 Buffer.close()
364         
365         if GenFds.OnlyGenerateThisFv == None and GenFds.OnlyGenerateThisFd == None:
366             if GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict != {}:
367                 GenFdsGlobalVariable.VerboseLogger("\n Generate other Capsule images!")
368                 for CapsuleName in GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict.keys():
369                     CapsuleObj = GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict[CapsuleName]
370                     CapsuleObj.GenCapsule()
371
372             if GenFdsGlobalVariable.FdfParser.Profile.OptRomDict != {}:
373                 GenFdsGlobalVariable.VerboseLogger("\n Generate all Option ROM!")
374                 for DriverName in GenFdsGlobalVariable.FdfParser.Profile.OptRomDict.keys():
375                     OptRomObj = GenFdsGlobalVariable.FdfParser.Profile.OptRomDict[DriverName]
376                     OptRomObj.AddToBuffer(None)
377
378     ## GetFvBlockSize()
379     #
380     #   @param  FvObj           Whose block size to get
381     #   @retval int             Block size value
382     #
383     def GetFvBlockSize(FvObj):
384         DefaultBlockSize = 0x1
385         FdObj = None
386         if GenFds.OnlyGenerateThisFd != None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():
387             FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[GenFds.OnlyGenerateThisFd.upper()]
388         if FdObj == None:
389             for ElementFd in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values():
390                 for ElementRegion in ElementFd.RegionList:
391                     if ElementRegion.RegionType == 'FV':
392                         for ElementRegionData in ElementRegion.RegionDataList:
393                             if ElementRegionData != None and ElementRegionData.upper() == FvObj.UiFvName:
394                                 if FvObj.BlockSizeList != []:
395                                     return FvObj.BlockSizeList[0][0]
396                                 else:
397                                     return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList)
398             if FvObj.BlockSizeList != []:
399                 return FvObj.BlockSizeList[0][0]
400             return DefaultBlockSize
401         else:
402             for ElementRegion in FdObj.RegionList:
403                     if ElementRegion.RegionType == 'FV':
404                         for ElementRegionData in ElementRegion.RegionDataList:
405                             if ElementRegionData != None and ElementRegionData.upper() == FvObj.UiFvName:
406                                 if FvObj.BlockSizeList != []:
407                                     return FvObj.BlockSizeList[0][0]
408                                 else:
409                                     return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList)
410             return DefaultBlockSize
411
412     ## DisplayFvSpaceInfo()
413     #
414     #   @param  FvObj           Whose block size to get
415     #   @retval None
416     #
417     def DisplayFvSpaceInfo(FdfParser):
418         
419         FvSpaceInfoList = []
420         MaxFvNameLength = 0
421         for FvName in FdfParser.Profile.FvDict:
422             if len(FvName) > MaxFvNameLength:
423                 MaxFvNameLength = len(FvName)
424             FvSpaceInfoFileName = os.path.join(GenFdsGlobalVariable.FvDir, FvName.upper() + '.Fv.map')
425             if os.path.exists(FvSpaceInfoFileName):
426                 FileLinesList = linecache.getlines(FvSpaceInfoFileName)
427                 TotalFound = False
428                 Total = ''
429                 UsedFound = False
430                 Used = ''
431                 FreeFound = False
432                 Free = ''
433                 for Line in FileLinesList:
434                     NameValue = Line.split('=')
435                     if len(NameValue) == 2:
436                         if NameValue[0].strip() == 'EFI_FV_TOTAL_SIZE':
437                             TotalFound = True
438                             Total = NameValue[1].strip()
439                         if NameValue[0].strip() == 'EFI_FV_TAKEN_SIZE':
440                             UsedFound = True
441                             Used = NameValue[1].strip()
442                         if NameValue[0].strip() == 'EFI_FV_SPACE_SIZE':
443                             FreeFound = True
444                             Free = NameValue[1].strip()
445                 
446                 if TotalFound and UsedFound and FreeFound:
447                     FvSpaceInfoList.append((FvName, Total, Used, Free))
448                 
449         GenFdsGlobalVariable.InfLogger('\nFV Space Information')
450         for FvSpaceInfo in FvSpaceInfoList:
451             Name = FvSpaceInfo[0]
452             TotalSizeValue = long(FvSpaceInfo[1], 0)
453             UsedSizeValue = long(FvSpaceInfo[2], 0)
454             FreeSizeValue = long(FvSpaceInfo[3], 0)
455             GenFdsGlobalVariable.InfLogger(Name + ' ' + '[' + str((UsedSizeValue+0.0)/TotalSizeValue)[0:4].lstrip('0.') + '%Full] ' + str(TotalSizeValue) + ' total, ' + str(UsedSizeValue) + ' used, ' + str(FreeSizeValue) + ' free')
456
457     ## PreprocessImage()
458     #
459     #   @param  BuildDb         Database from build meta data files
460     #   @param  DscFile         modules from dsc file will be preprocessed
461     #   @retval None
462     #
463     def PreprocessImage(BuildDb, DscFile):
464         PcdDict = BuildDb.BuildObject[DscFile, 'COMMON'].Pcds
465         PcdValue = ''
466         for Key in PcdDict:
467             PcdObj = PcdDict[Key]
468             if PcdObj.TokenCName == 'PcdBsBaseAddress':
469                 PcdValue = PcdObj.DefaultValue
470                 break
471         
472         if PcdValue == '':
473             return
474         
475         Int64PcdValue = long(PcdValue, 0)
476         if Int64PcdValue == 0 or Int64PcdValue < -1:    
477             return
478                 
479         TopAddress = 0
480         if Int64PcdValue > 0:
481             TopAddress = Int64PcdValue
482             
483         ModuleDict = BuildDb.BuildObject[DscFile, 'COMMON'].Modules
484         for Key in ModuleDict:
485             ModuleObj = BuildDb.BuildObject[Key, 'COMMON']
486             print ModuleObj.BaseName + ' ' + ModuleObj.ModuleType
487
488     def GenerateGuidXRefFile(BuildDb, ArchList):
489         GuidXRefFileName = os.path.join(GenFdsGlobalVariable.FvDir, "Guid.xref")
490         GuidXRefFile = open(GuidXRefFileName, "w+")
491         for Arch in ArchList:
492             PlatformDataBase = BuildDb.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch]
493             for ModuleFile in PlatformDataBase.Modules:
494                 Module = BuildDb.BuildObject[ModuleFile, Arch]
495                 GuidXRefFile.write("%s %s\n" % (Module.Guid, Module.BaseName))
496         GuidXRefFile.close()
497         GenFdsGlobalVariable.InfLogger("\nGUID cross reference file saved to %s" % GuidXRefFileName)
498         
499     ##Define GenFd as static function
500     GenFd = staticmethod(GenFd)
501     GetFvBlockSize = staticmethod(GetFvBlockSize)
502     DisplayFvSpaceInfo = staticmethod(DisplayFvSpaceInfo)
503     PreprocessImage = staticmethod(PreprocessImage)
504     GenerateGuidXRefFile = staticmethod(GenerateGuidXRefFile)
505
506 if __name__ == '__main__':
507     r = main()
508     ## 0-127 is a safe return range, and 1 is a standard default error
509     if r < 0 or r > 127: r = 1
510     sys.exit(r)
511