1## @file
2# Global variables for GenFds
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#
18import Common.LongFilePathOs as os
19import sys
20import subprocess
21import struct
22import array
23
24from Common.BuildToolError import *
25from Common import EdkLogger
26from Common.Misc import SaveFileOnChange
27
28from Common.TargetTxtClassObject import TargetTxtClassObject
29from Common.ToolDefClassObject import ToolDefClassObject
30from AutoGen.BuildEngine import BuildRule
31import Common.DataType as DataType
32from Common.Misc import PathClass
33from Common.LongFilePathSupport import OpenLongFilePath as open
34from Common.MultipleWorkspace import MultipleWorkspace as mws
35
36## Global variables
37#
38#
39class GenFdsGlobalVariable:
40    FvDir = ''
41    OutputDirDict = {}
42    BinDir = ''
43    # will be FvDir + os.sep + 'Ffs'
44    FfsDir = ''
45    FdfParser = None
46    LibDir = ''
47    WorkSpace = None
48    WorkSpaceDir = ''
49    ConfDir = ''
50    EdkSourceDir = ''
51    OutputDirFromDscDict = {}
52    TargetName = ''
53    ToolChainTag = ''
54    RuleDict = {}
55    ArchList = None
56    VtfDict = {}
57    ActivePlatform = None
58    FvAddressFileName = ''
59    VerboseMode = False
60    DebugLevel = -1
61    SharpCounter = 0
62    SharpNumberPerLine = 40
63    FdfFile = ''
64    FdfFileTimeStamp = 0
65    FixedLoadAddress = False
66    PlatformName = ''
67
68    BuildRuleFamily = "MSFT"
69    ToolChainFamily = "MSFT"
70    __BuildRuleDatabase = None
71
72    #
73    # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
74    # At the beginning of each generation of FV, false flag is appended to the list,
75    # after the call to GenerateSection returns, check the size of the output file,
76    # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
77    # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
78    # At the end of generation of FV, pop the flag.
79    # List is used as a stack to handle nested FV generation.
80    #
81    LargeFileInFvFlags = []
82    EFI_FIRMWARE_FILE_SYSTEM3_GUID = '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
83    LARGE_FILE_SIZE = 0x1000000
84
85    SectionHeader = struct.Struct("3B 1B")
86
87    ## LoadBuildRule
88    #
89    @staticmethod
90    def __LoadBuildRule():
91        if GenFdsGlobalVariable.__BuildRuleDatabase:
92            return GenFdsGlobalVariable.__BuildRuleDatabase
93        BuildConfigurationFile = os.path.normpath(os.path.join(GenFdsGlobalVariable.ConfDir, "target.txt"))
94        TargetTxt = TargetTxtClassObject()
95        if os.path.isfile(BuildConfigurationFile) == True:
96            TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)
97            if DataType.TAB_TAT_DEFINES_BUILD_RULE_CONF in TargetTxt.TargetTxtDictionary:
98                BuildRuleFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_BUILD_RULE_CONF]
99            if BuildRuleFile in [None, '']:
100                BuildRuleFile = 'Conf/build_rule.txt'
101            GenFdsGlobalVariable.__BuildRuleDatabase = BuildRule(BuildRuleFile)
102            ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
103            if ToolDefinitionFile == '':
104                ToolDefinitionFile = "Conf/tools_def.txt"
105            if os.path.isfile(ToolDefinitionFile):
106                ToolDef = ToolDefClassObject()
107                ToolDef.LoadToolDefFile(ToolDefinitionFile)
108                ToolDefinition = ToolDef.ToolsDefTxtDatabase
109                if DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDefinition \
110                   and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY] \
111                   and ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]:
112                    GenFdsGlobalVariable.BuildRuleFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]
113
114                if DataType.TAB_TOD_DEFINES_FAMILY in ToolDefinition \
115                   and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY] \
116                   and ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag]:
117                    GenFdsGlobalVariable.ToolChainFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag]
118        return GenFdsGlobalVariable.__BuildRuleDatabase
119
120    ## GetBuildRules
121    #    @param Inf: object of InfBuildData
122    #    @param Arch: current arch
123    #
124    @staticmethod
125    def GetBuildRules(Inf, Arch):
126        if not Arch:
127            Arch = 'COMMON'
128
129        if not Arch in GenFdsGlobalVariable.OutputDirDict:
130            return {}
131
132        BuildRuleDatabase = GenFdsGlobalVariable.__LoadBuildRule()
133        if not BuildRuleDatabase:
134            return {}
135
136        PathClassObj = PathClass(Inf.MetaFile.File,
137                                 GenFdsGlobalVariable.WorkSpaceDir)
138        Macro = {}
139        Macro["WORKSPACE"             ] = GenFdsGlobalVariable.WorkSpaceDir
140        Macro["MODULE_NAME"           ] = Inf.BaseName
141        Macro["MODULE_GUID"           ] = Inf.Guid
142        Macro["MODULE_VERSION"        ] = Inf.Version
143        Macro["MODULE_TYPE"           ] = Inf.ModuleType
144        Macro["MODULE_FILE"           ] = str(PathClassObj)
145        Macro["MODULE_FILE_BASE_NAME" ] = PathClassObj.BaseName
146        Macro["MODULE_RELATIVE_DIR"   ] = PathClassObj.SubDir
147        Macro["MODULE_DIR"            ] = PathClassObj.SubDir
148
149        Macro["BASE_NAME"             ] = Inf.BaseName
150
151        Macro["ARCH"                  ] = Arch
152        Macro["TOOLCHAIN"             ] = GenFdsGlobalVariable.ToolChainTag
153        Macro["TOOLCHAIN_TAG"         ] = GenFdsGlobalVariable.ToolChainTag
154        Macro["TOOL_CHAIN_TAG"        ] = GenFdsGlobalVariable.ToolChainTag
155        Macro["TARGET"                ] = GenFdsGlobalVariable.TargetName
156
157        Macro["BUILD_DIR"             ] = GenFdsGlobalVariable.OutputDirDict[Arch]
158        Macro["BIN_DIR"               ] = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch)
159        Macro["LIB_DIR"               ] = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch)
160        BuildDir = os.path.join(
161            GenFdsGlobalVariable.OutputDirDict[Arch],
162            Arch,
163            PathClassObj.SubDir,
164            PathClassObj.BaseName
165        )
166        Macro["MODULE_BUILD_DIR"      ] = BuildDir
167        Macro["OUTPUT_DIR"            ] = os.path.join(BuildDir, "OUTPUT")
168        Macro["DEBUG_DIR"             ] = os.path.join(BuildDir, "DEBUG")
169
170        BuildRules = {}
171        for Type in BuildRuleDatabase.FileTypeList:
172            #first try getting build rule by BuildRuleFamily
173            RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.BuildRuleFamily]
174            if not RuleObject:
175                # build type is always module type, but ...
176                if Inf.ModuleType != Inf.BuildType:
177                    RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.BuildRuleFamily]
178            #second try getting build rule by ToolChainFamily
179            if not RuleObject:
180                RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.ToolChainFamily]
181                if not RuleObject:
182                    # build type is always module type, but ...
183                    if Inf.ModuleType != Inf.BuildType:
184                        RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.ToolChainFamily]
185            if not RuleObject:
186                continue
187            RuleObject = RuleObject.Instantiate(Macro)
188            BuildRules[Type] = RuleObject
189            for Ext in RuleObject.SourceFileExtList:
190                BuildRules[Ext] = RuleObject
191        return BuildRules
192
193    ## GetModuleCodaTargetList
194    #
195    #    @param Inf: object of InfBuildData
196    #    @param Arch: current arch
197    #
198    @staticmethod
199    def GetModuleCodaTargetList(Inf, Arch):
200        BuildRules = GenFdsGlobalVariable.GetBuildRules(Inf, Arch)
201        if not BuildRules:
202            return []
203
204        TargetList = set()
205        FileList = []
206
207        if not Inf.IsBinaryModule:
208            for File in Inf.Sources:
209                if File.TagName in ("", "*", GenFdsGlobalVariable.ToolChainTag) and \
210                    File.ToolChainFamily in ("", "*", GenFdsGlobalVariable.ToolChainFamily):
211                    FileList.append((File, DataType.TAB_UNKNOWN_FILE))
212
213        for File in Inf.Binaries:
214            if File.Target in ['COMMON', '*', GenFdsGlobalVariable.TargetName]:
215                FileList.append((File, File.Type))
216
217        for File, FileType in FileList:
218            LastTarget = None
219            RuleChain = []
220            SourceList = [File]
221            Index = 0
222            while Index < len(SourceList):
223                Source = SourceList[Index]
224                Index = Index + 1
225
226                if File.IsBinary and File == Source and Inf.Binaries != None and File in Inf.Binaries:
227                    # Skip all files that are not binary libraries
228                    if not Inf.LibraryClass:
229                        continue
230                    RuleObject = BuildRules[DataType.TAB_DEFAULT_BINARY_FILE]
231                elif FileType in BuildRules:
232                    RuleObject = BuildRules[FileType]
233                elif Source.Ext in BuildRules:
234                    RuleObject = BuildRules[Source.Ext]
235                else:
236                    # stop at no more rules
237                    if LastTarget:
238                        TargetList.add(str(LastTarget))
239                    break
240
241                FileType = RuleObject.SourceFileType
242
243                # stop at STATIC_LIBRARY for library
244                if Inf.LibraryClass and FileType == DataType.TAB_STATIC_LIBRARY:
245                    if LastTarget:
246                        TargetList.add(str(LastTarget))
247                    break
248
249                Target = RuleObject.Apply(Source)
250                if not Target:
251                    if LastTarget:
252                        TargetList.add(str(LastTarget))
253                    break
254                elif not Target.Outputs:
255                    # Only do build for target with outputs
256                    TargetList.add(str(Target))
257
258                # to avoid cyclic rule
259                if FileType in RuleChain:
260                    break
261
262                RuleChain.append(FileType)
263                SourceList.extend(Target.Outputs)
264                LastTarget = Target
265                FileType = DataType.TAB_UNKNOWN_FILE
266
267        return list(TargetList)
268
269    ## SetDir()
270    #
271    #   @param  OutputDir           Output directory
272    #   @param  FdfParser           FDF contents parser
273    #   @param  Workspace           The directory of workspace
274    #   @param  ArchList            The Arch list of platform
275    #
276    def SetDir (OutputDir, FdfParser, WorkSpace, ArchList):
277        GenFdsGlobalVariable.VerboseLogger("GenFdsGlobalVariable.OutputDir :%s" % OutputDir)
278#        GenFdsGlobalVariable.OutputDirDict = OutputDir
279        GenFdsGlobalVariable.FdfParser = FdfParser
280        GenFdsGlobalVariable.WorkSpace = WorkSpace
281        GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], 'FV')
282        if not os.path.exists(GenFdsGlobalVariable.FvDir) :
283            os.makedirs(GenFdsGlobalVariable.FvDir)
284        GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')
285        if not os.path.exists(GenFdsGlobalVariable.FfsDir) :
286            os.makedirs(GenFdsGlobalVariable.FfsDir)
287        if ArchList != None:
288            GenFdsGlobalVariable.ArchList = ArchList
289
290        T_CHAR_LF = '\n'
291        #
292        # Create FV Address inf file
293        #
294        GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf')
295        FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w')
296        #
297        # Add [Options]
298        #
299        FvAddressFile.writelines("[options]" + T_CHAR_LF)
300        BsAddress = '0'
301        for Arch in ArchList:
302            if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress:
303                BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress
304                break
305
306        FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
307                                       BsAddress + \
308                                       T_CHAR_LF)
309
310        RtAddress = '0'
311        for Arch in ArchList:
312            if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress:
313                RtAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress
314
315        FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
316                                       RtAddress + \
317                                       T_CHAR_LF)
318
319        FvAddressFile.close()
320
321    ## ReplaceWorkspaceMacro()
322    #
323    #   @param  String           String that may contain macro
324    #
325    def ReplaceWorkspaceMacro(String):
326        String = mws.handleWsMacro(String)
327        Str = String.replace('$(WORKSPACE)', GenFdsGlobalVariable.WorkSpaceDir)
328        if os.path.exists(Str):
329            if not os.path.isabs(Str):
330                Str = os.path.abspath(Str)
331        else:
332            Str = mws.join(GenFdsGlobalVariable.WorkSpaceDir, String)
333        return os.path.normpath(Str)
334
335    ## Check if the input files are newer than output files
336    #
337    #   @param  Output          Path of output file
338    #   @param  Input           Path list of input files
339    #
340    #   @retval True            if Output doesn't exist, or any Input is newer
341    #   @retval False           if all Input is older than Output
342    #
343    @staticmethod
344    def NeedsUpdate(Output, Input):
345        if not os.path.exists(Output):
346            return True
347        # always update "Output" if no "Input" given
348        if Input == None or len(Input) == 0:
349            return True
350
351        # if fdf file is changed after the 'Output" is generated, update the 'Output'
352        OutputTime = os.path.getmtime(Output)
353        if GenFdsGlobalVariable.FdfFileTimeStamp > OutputTime:
354            return True
355
356        for F in Input:
357            # always update "Output" if any "Input" doesn't exist
358            if not os.path.exists(F):
359                return True
360            # always update "Output" if any "Input" is newer than "Output"
361            if os.path.getmtime(F) > OutputTime:
362                return True
363        return False
364
365    @staticmethod
366    def GenerateSection(Output, Input, Type=None, CompressionType=None, Guid=None,
367                        GuidHdrLen=None, GuidAttr=[], Ui=None, Ver=None, InputAlign=None, BuildNumber=None):
368        Cmd = ["GenSec"]
369        if Type not in [None, '']:
370            Cmd += ["-s", Type]
371        if CompressionType not in [None, '']:
372            Cmd += ["-c", CompressionType]
373        if Guid != None:
374            Cmd += ["-g", Guid]
375        if GuidHdrLen not in [None, '']:
376            Cmd += ["-l", GuidHdrLen]
377        if len(GuidAttr) != 0:
378            #Add each guided attribute
379            for Attr in GuidAttr:
380                Cmd += ["-r", Attr]
381        if InputAlign != None:
382            #Section Align is only for dummy section without section type
383            for SecAlign in InputAlign:
384                Cmd += ["--sectionalign", SecAlign]
385
386        CommandFile = Output + '.txt'
387        if Ui not in [None, '']:
388            #Cmd += ["-n", '"' + Ui + '"']
389            SectionData = array.array('B', [0, 0, 0, 0])
390            SectionData.fromstring(Ui.encode("utf_16_le"))
391            SectionData.append(0)
392            SectionData.append(0)
393            Len = len(SectionData)
394            GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15)
395            SaveFileOnChange(Output, SectionData.tostring())
396        elif Ver not in [None, '']:
397            Cmd += ["-n", Ver]
398            if BuildNumber:
399                Cmd += ["-j", BuildNumber]
400            Cmd += ["-o", Output]
401
402            SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
403            if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
404                return
405
406            GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
407        else:
408            Cmd += ["-o", Output]
409            Cmd += Input
410
411            SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
412            if GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
413                GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
414                GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
415
416            if (os.path.getsize(Output) >= GenFdsGlobalVariable.LARGE_FILE_SIZE and
417                GenFdsGlobalVariable.LargeFileInFvFlags):
418                GenFdsGlobalVariable.LargeFileInFvFlags[-1] = True
419
420    @staticmethod
421    def GetAlignment (AlignString):
422        if AlignString == None:
423            return 0
424        if AlignString in ("1K", "2K", "4K", "8K", "16K", "32K", "64K"):
425            return int (AlignString.rstrip('K')) * 1024
426        else:
427            return int (AlignString)
428
429    @staticmethod
430    def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None,
431                    SectionAlign=None):
432        Cmd = ["GenFfs", "-t", Type, "-g", Guid]
433        if Fixed == True:
434            Cmd += ["-x"]
435        if CheckSum:
436            Cmd += ["-s"]
437        if Align not in [None, '']:
438            Cmd += ["-a", Align]
439
440        Cmd += ["-o", Output]
441        for I in range(0, len(Input)):
442            Cmd += ("-i", Input[I])
443            if SectionAlign not in [None, '', []] and SectionAlign[I] not in [None, '']:
444                Cmd += ("-n", SectionAlign[I])
445
446        CommandFile = Output + '.txt'
447        SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
448        if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
449            return
450        GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
451
452        GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS")
453
454    @staticmethod
455    def GenerateFirmwareVolume(Output, Input, BaseAddress=None, ForceRebase=None, Capsule=False, Dump=False,
456                               AddressFile=None, MapFile=None, FfsList=[], FileSystemGuid=None):
457        if not GenFdsGlobalVariable.NeedsUpdate(Output, Input+FfsList):
458            return
459        GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
460
461        Cmd = ["GenFv"]
462        if BaseAddress not in [None, '']:
463            Cmd += ["-r", BaseAddress]
464
465        if ForceRebase == False:
466            Cmd += ["-F", "FALSE"]
467        elif ForceRebase == True:
468            Cmd += ["-F", "TRUE"]
469
470        if Capsule:
471            Cmd += ["-c"]
472        if Dump:
473            Cmd += ["-p"]
474        if AddressFile not in [None, '']:
475            Cmd += ["-a", AddressFile]
476        if MapFile not in [None, '']:
477            Cmd += ["-m", MapFile]
478        if FileSystemGuid:
479            Cmd += ["-g", FileSystemGuid]
480        Cmd += ["-o", Output]
481        for I in Input:
482            Cmd += ["-i", I]
483
484        GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV")
485
486    @staticmethod
487    def GenerateVtf(Output, Input, BaseAddress=None, FvSize=None):
488        if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
489            return
490        GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
491
492        Cmd = ["GenVtf"]
493        if BaseAddress not in [None, ''] and FvSize not in [None, ''] \
494            and len(BaseAddress) == len(FvSize):
495            for I in range(0, len(BaseAddress)):
496                Cmd += ["-r", BaseAddress[I], "-s", FvSize[I]]
497        Cmd += ["-o", Output]
498        for F in Input:
499            Cmd += ["-f", F]
500
501        GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate VTF")
502
503    @staticmethod
504    def GenerateFirmwareImage(Output, Input, Type="efi", SubType=None, Zero=False,
505                              Strip=False, Replace=False, TimeStamp=None, Join=False,
506                              Align=None, Padding=None, Convert=False):
507        if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
508            return
509        GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
510
511        Cmd = ["GenFw"]
512        if Type.lower() == "te":
513            Cmd += ["-t"]
514        if SubType not in [None, '']:
515            Cmd += ["-e", SubType]
516        if TimeStamp not in [None, '']:
517            Cmd += ["-s", TimeStamp]
518        if Align not in [None, '']:
519            Cmd += ["-a", Align]
520        if Padding not in [None, '']:
521            Cmd += ["-p", Padding]
522        if Zero:
523            Cmd += ["-z"]
524        if Strip:
525            Cmd += ["-l"]
526        if Replace:
527            Cmd += ["-r"]
528        if Join:
529            Cmd += ["-j"]
530        if Convert:
531            Cmd += ["-m"]
532        Cmd += ["-o", Output]
533        Cmd += Input
534
535        GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image")
536
537    @staticmethod
538    def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None,
539                        Revision=None, DeviceId=None, VendorId=None):
540        InputList = []
541        Cmd = ["EfiRom"]
542        if len(EfiInput) > 0:
543
544            if Compress:
545                Cmd += ["-ec"]
546            else:
547                Cmd += ["-e"]
548
549            for EfiFile in EfiInput:
550                Cmd += [EfiFile]
551                InputList.append (EfiFile)
552
553        if len(BinaryInput) > 0:
554            Cmd += ["-b"]
555            for BinFile in BinaryInput:
556                Cmd += [BinFile]
557                InputList.append (BinFile)
558
559        # Check List
560        if not GenFdsGlobalVariable.NeedsUpdate(Output, InputList):
561            return
562        GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, InputList))
563
564        if ClassCode != None:
565            Cmd += ["-l", ClassCode]
566        if Revision != None:
567            Cmd += ["-r", Revision]
568        if DeviceId != None:
569            Cmd += ["-i", DeviceId]
570        if VendorId != None:
571            Cmd += ["-f", VendorId]
572
573        Cmd += ["-o", Output]
574        GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate option rom")
575
576    @staticmethod
577    def GuidTool(Output, Input, ToolPath, Options='', returnValue=[]):
578        if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
579            return
580        GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
581
582        Cmd = [ToolPath, ]
583        Cmd += Options.split(' ')
584        Cmd += ["-o", Output]
585        Cmd += Input
586
587        GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath, returnValue)
588
589    def CallExternalTool (cmd, errorMess, returnValue=[]):
590
591        if type(cmd) not in (tuple, list):
592            GenFdsGlobalVariable.ErrorLogger("ToolError!  Invalid parameter type in call to CallExternalTool")
593
594        if GenFdsGlobalVariable.DebugLevel != -1:
595            cmd += ('--debug', str(GenFdsGlobalVariable.DebugLevel))
596            GenFdsGlobalVariable.InfLogger (cmd)
597
598        if GenFdsGlobalVariable.VerboseMode:
599            cmd += ('-v',)
600            GenFdsGlobalVariable.InfLogger (cmd)
601        else:
602            sys.stdout.write ('#')
603            sys.stdout.flush()
604            GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1
605            if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0:
606                sys.stdout.write('\n')
607
608        try:
609            PopenObject = subprocess.Popen(' '.join(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
610        except Exception, X:
611            EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0]))
612        (out, error) = PopenObject.communicate()
613
614        while PopenObject.returncode == None :
615            PopenObject.wait()
616        if returnValue != [] and returnValue[0] != 0:
617            #get command return value
618            returnValue[0] = PopenObject.returncode
619            return
620        if PopenObject.returncode != 0 or GenFdsGlobalVariable.VerboseMode or GenFdsGlobalVariable.DebugLevel != -1:
621            GenFdsGlobalVariable.InfLogger ("Return Value = %d" % PopenObject.returncode)
622            GenFdsGlobalVariable.InfLogger (out)
623            GenFdsGlobalVariable.InfLogger (error)
624            if PopenObject.returncode != 0:
625                print "###", cmd
626                EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess)
627
628    def VerboseLogger (msg):
629        EdkLogger.verbose(msg)
630
631    def InfLogger (msg):
632        EdkLogger.info(msg)
633
634    def ErrorLogger (msg, File=None, Line=None, ExtraData=None):
635        EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData)
636
637    def DebugLogger (Level, msg):
638        EdkLogger.debug(Level, msg)
639
640    ## ReplaceWorkspaceMacro()
641    #
642    #   @param  Str           String that may contain macro
643    #   @param  MacroDict     Dictionary that contains macro value pair
644    #
645    def MacroExtend (Str, MacroDict={}, Arch='COMMON'):
646        if Str == None :
647            return None
648
649        Dict = {'$(WORKSPACE)'   : GenFdsGlobalVariable.WorkSpaceDir,
650                '$(EDK_SOURCE)'  : GenFdsGlobalVariable.EdkSourceDir,
651#                '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
652                '$(TARGET)' : GenFdsGlobalVariable.TargetName,
653                '$(TOOL_CHAIN_TAG)' : GenFdsGlobalVariable.ToolChainTag,
654                '$(SPACE)' : ' '
655               }
656        OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]]
657        if Arch != 'COMMON' and Arch in GenFdsGlobalVariable.ArchList:
658            OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch]
659
660        Dict['$(OUTPUT_DIRECTORY)'] = OutputDir
661
662        if MacroDict != None  and len (MacroDict) != 0:
663            Dict.update(MacroDict)
664
665        for key in Dict.keys():
666            if Str.find(key) >= 0 :
667                Str = Str.replace (key, Dict[key])
668
669        if Str.find('$(ARCH)') >= 0:
670            if len(GenFdsGlobalVariable.ArchList) == 1:
671                Str = Str.replace('$(ARCH)', GenFdsGlobalVariable.ArchList[0])
672            else:
673                EdkLogger.error("GenFds", GENFDS_ERROR, "No way to determine $(ARCH) for %s" % Str)
674
675        return Str
676
677    ## GetPcdValue()
678    #
679    #   @param  PcdPattern           pattern that labels a PCD.
680    #
681    def GetPcdValue (PcdPattern):
682        if PcdPattern == None :
683            return None
684        PcdPair = PcdPattern.lstrip('PCD(').rstrip(')').strip().split('.')
685        TokenSpace = PcdPair[0]
686        TokenCName = PcdPair[1]
687
688        PcdValue = ''
689        for Arch in GenFdsGlobalVariable.ArchList:
690            Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
691            PcdDict = Platform.Pcds
692            for Key in PcdDict:
693                PcdObj = PcdDict[Key]
694                if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
695                    if PcdObj.Type != 'FixedAtBuild':
696                        EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
697                    if PcdObj.DatumType != 'VOID*':
698                        EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
699
700                    PcdValue = PcdObj.DefaultValue
701                    return PcdValue
702
703            for Package in GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform,
704                                                                         Arch,
705                                                                         GenFdsGlobalVariable.TargetName,
706                                                                         GenFdsGlobalVariable.ToolChainTag):
707                PcdDict = Package.Pcds
708                for Key in PcdDict:
709                    PcdObj = PcdDict[Key]
710                    if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
711                        if PcdObj.Type != 'FixedAtBuild':
712                            EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
713                        if PcdObj.DatumType != 'VOID*':
714                            EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
715
716                        PcdValue = PcdObj.DefaultValue
717                        return PcdValue
718
719        return PcdValue
720
721    SetDir = staticmethod(SetDir)
722    ReplaceWorkspaceMacro = staticmethod(ReplaceWorkspaceMacro)
723    CallExternalTool = staticmethod(CallExternalTool)
724    VerboseLogger = staticmethod(VerboseLogger)
725    InfLogger = staticmethod(InfLogger)
726    ErrorLogger = staticmethod(ErrorLogger)
727    DebugLogger = staticmethod(DebugLogger)
728    MacroExtend = staticmethod (MacroExtend)
729    GetPcdValue = staticmethod(GetPcdValue)
730