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