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