1## @file
2# process FFS generation from INF statement
3#
4#  Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
5#  Copyright (c) 2014 Hewlett-Packard Development Company, L.P.<BR>
6#
7#  This program and the accompanying materials
8#  are licensed and made available under the terms and conditions of the BSD License
9#  which accompanies this distribution.  The full text of the license may be found at
10#  http://opensource.org/licenses/bsd-license.php
11#
12#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14#
15
16##
17# Import Modules
18#
19import Rule
20import Common.LongFilePathOs as os
21import StringIO
22from struct import *
23from GenFdsGlobalVariable import GenFdsGlobalVariable
24import Ffs
25import subprocess
26import sys
27import Section
28import RuleSimpleFile
29import RuleComplexFile
30from CommonDataClass.FdfClass import FfsInfStatementClassObject
31from Common.MultipleWorkspace import MultipleWorkspace as mws
32from Common.String import *
33from Common.Misc import PathClass
34from Common.Misc import GuidStructureByteArrayToGuidString
35from Common.Misc import ProcessDuplicatedInf
36from Common.Misc import GetVariableOffset
37from Common import EdkLogger
38from Common.BuildToolError import *
39from GuidSection import GuidSection
40from FvImageSection import FvImageSection
41from Common.Misc import PeImageClass
42from AutoGen.GenDepex import DependencyExpression
43from PatchPcdValue.PatchPcdValue import PatchBinaryFile
44from Common.LongFilePathSupport import CopyLongFilePath
45from Common.LongFilePathSupport import OpenLongFilePath as open
46
47## generate FFS from INF
48#
49#
50class FfsInfStatement(FfsInfStatementClassObject):
51    ## The mapping dictionary from datum type to its maximum number.
52    _MAX_SIZE_TYPE = {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}
53    ## The constructor
54    #
55    #   @param  self        The object pointer
56    #
57    def __init__(self):
58        FfsInfStatementClassObject.__init__(self)
59        self.TargetOverrideList = []
60        self.ShadowFromInfFile = None
61        self.KeepRelocFromRule = None
62        self.InDsc = True
63        self.OptRomDefs = {}
64        self.PiSpecVersion = '0x00000000'
65        self.InfModule = None
66        self.FinalTargetSuffixMap = {}
67        self.CurrentLineNum = None
68        self.CurrentLineContent = None
69        self.FileName = None
70        self.InfFileName = None
71        self.OverrideGuid = None
72        self.PatchedBinFile = ''
73        self.MacroDict = {}
74
75    ## GetFinalTargetSuffixMap() method
76    #
77    #    Get final build target list
78    def GetFinalTargetSuffixMap(self):
79        if not self.InfModule or not self.CurrentArch:
80            return []
81        if not self.FinalTargetSuffixMap:
82            FinalBuildTargetList = GenFdsGlobalVariable.GetModuleCodaTargetList(self.InfModule, self.CurrentArch)
83            for File in FinalBuildTargetList:
84                self.FinalTargetSuffixMap.setdefault(os.path.splitext(File)[1], []).append(File)
85
86            # Check if current INF module has DEPEX
87            if '.depex' not in self.FinalTargetSuffixMap and self.InfModule.ModuleType != "USER_DEFINED" \
88                and not self.InfModule.DxsFile and not self.InfModule.LibraryClass:
89                ModuleType = self.InfModule.ModuleType
90                PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
91
92                if ModuleType != DataType.SUP_MODULE_USER_DEFINED:
93                    for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys():
94                        if LibraryClass.startswith("NULL") and PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]:
95                            self.InfModule.LibraryClasses[LibraryClass] = PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]
96
97                StrModule = str(self.InfModule)
98                PlatformModule = None
99                if StrModule in PlatformDataBase.Modules:
100                    PlatformModule = PlatformDataBase.Modules[StrModule]
101                    for LibraryClass in PlatformModule.LibraryClasses:
102                        if LibraryClass.startswith("NULL"):
103                            self.InfModule.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
104
105                DependencyList = [self.InfModule]
106                LibraryInstance = {}
107                DepexList = []
108                while len(DependencyList) > 0:
109                    Module = DependencyList.pop(0)
110                    if not Module:
111                        continue
112                    for Dep in Module.Depex[self.CurrentArch, ModuleType]:
113                        if DepexList != []:
114                            DepexList.append('AND')
115                        DepexList.append('(')
116                        DepexList.extend(Dep)
117                        if DepexList[-1] == 'END':  # no need of a END at this time
118                            DepexList.pop()
119                        DepexList.append(')')
120                    if 'BEFORE' in DepexList or 'AFTER' in DepexList:
121                        break
122                    for LibName in Module.LibraryClasses:
123                        if LibName in LibraryInstance:
124                            continue
125                        if PlatformModule and LibName in PlatformModule.LibraryClasses:
126                            LibraryPath = PlatformModule.LibraryClasses[LibName]
127                        else:
128                            LibraryPath = PlatformDataBase.LibraryClasses[LibName, ModuleType]
129                        if not LibraryPath:
130                            LibraryPath = Module.LibraryClasses[LibName]
131                        if not LibraryPath:
132                            continue
133                        LibraryModule = GenFdsGlobalVariable.WorkSpace.BuildObject[LibraryPath, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
134                        LibraryInstance[LibName] = LibraryModule
135                        DependencyList.append(LibraryModule)
136                if DepexList:
137                    Dpx = DependencyExpression(DepexList, ModuleType, True)
138                    if len(Dpx.PostfixNotation) != 0:
139                        # It means this module has DEPEX
140                        self.FinalTargetSuffixMap['.depex'] = [os.path.join(self.EfiOutputPath, self.BaseName) + '.depex']
141        return self.FinalTargetSuffixMap
142
143    ## __InfParse() method
144    #
145    #   Parse inf file to get module information
146    #
147    #   @param  self        The object pointer
148    #   @param  Dict        dictionary contains macro and value pair
149    #
150    def __InfParse__(self, Dict = {}):
151
152        GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)
153
154        self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')
155        if len(self.InfFileName) > 1 and self.InfFileName[0] == '\\' and self.InfFileName[1] == '\\':
156            pass
157        elif self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :
158            self.InfFileName = self.InfFileName[1:]
159
160        if self.InfFileName.find('$') == -1:
161            InfPath = NormPath(self.InfFileName)
162            if not os.path.exists(InfPath):
163                InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath)
164                if not os.path.exists(InfPath):
165                    EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName))
166
167        self.CurrentArch = self.GetCurrentArch()
168        #
169        # Get the InfClass object
170        #
171
172        PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
173        ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
174        if ErrorCode != 0:
175            EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
176
177        #
178        # Cache lower case version of INF path before processing FILE_GUID override
179        #
180        InfLowerPath = str(PathClassObj).lower()
181        if self.OverrideGuid:
182            PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)
183        if self.CurrentArch != None:
184
185            Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
186            #
187            # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
188            #
189            self.BaseName = Inf.BaseName
190            self.ModuleGuid = Inf.Guid
191            self.ModuleType = Inf.ModuleType
192            if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
193                self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']
194            if Inf.AutoGenVersion < 0x00010005:
195                self.ModuleType = Inf.ComponentType
196            self.VersionString = Inf.Version
197            self.BinFileList = Inf.Binaries
198            self.SourceFileList = Inf.Sources
199            if self.KeepReloc == None and Inf.Shadow:
200                self.ShadowFromInfFile = Inf.Shadow
201
202        else:
203            Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
204            self.BaseName = Inf.BaseName
205            self.ModuleGuid = Inf.Guid
206            self.ModuleType = Inf.ModuleType
207            if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
208                self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']
209            self.VersionString = Inf.Version
210            self.BinFileList = Inf.Binaries
211            self.SourceFileList = Inf.Sources
212            if self.BinFileList == []:
213                EdkLogger.error("GenFds", GENFDS_ERROR,
214                                "INF %s specified in FDF could not be found in build ARCH %s!" \
215                                % (self.InfFileName, GenFdsGlobalVariable.ArchList))
216
217        if self.OverrideGuid:
218            self.ModuleGuid = self.OverrideGuid
219
220        if len(self.SourceFileList) != 0 and not self.InDsc:
221            EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))
222
223        if self.ModuleType == 'SMM_CORE' and int(self.PiSpecVersion, 16) < 0x0001000A:
224            EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "SMM_CORE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A", File=self.InfFileName)
225
226        if Inf._Defs != None and len(Inf._Defs) > 0:
227            self.OptRomDefs.update(Inf._Defs)
228
229        self.PatchPcds = []
230        InfPcds = Inf.Pcds
231        Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
232        FdfPcdDict = GenFdsGlobalVariable.FdfParser.Profile.PcdDict
233
234        # Workaround here: both build and GenFds tool convert the workspace path to lower case
235        # But INF file path in FDF and DSC file may have real case characters.
236        # Try to convert the path to lower case to see if PCDs value are override by DSC.
237        DscModules = {}
238        for DscModule in Platform.Modules:
239            DscModules[str(DscModule).lower()] = Platform.Modules[DscModule]
240        for PcdKey in InfPcds:
241            Pcd = InfPcds[PcdKey]
242            if not hasattr(Pcd, 'Offset'):
243                continue
244            if Pcd.Type != 'PatchableInModule':
245                continue
246            # Override Patchable PCD value by the value from DSC
247            PatchPcd = None
248            if InfLowerPath in DscModules and PcdKey in DscModules[InfLowerPath].Pcds:
249                PatchPcd = DscModules[InfLowerPath].Pcds[PcdKey]
250            elif PcdKey in Platform.Pcds:
251                PatchPcd = Platform.Pcds[PcdKey]
252            DscOverride = False
253            if PatchPcd and Pcd.Type == PatchPcd.Type:
254                DefaultValue = PatchPcd.DefaultValue
255                DscOverride = True
256
257            # Override Patchable PCD value by the value from FDF
258            FdfOverride = False
259            if PcdKey in FdfPcdDict:
260                DefaultValue = FdfPcdDict[PcdKey]
261                FdfOverride = True
262
263            if not DscOverride and not FdfOverride:
264                continue
265            # Check value, if value are equal, no need to patch
266            if Pcd.DatumType == "VOID*":
267                if Pcd.DefaultValue == DefaultValue or DefaultValue in [None, '']:
268                    continue
269                # Get the string size from FDF or DSC
270                if DefaultValue[0] == 'L':
271                    # Remove L"", but the '\0' must be appended
272                    MaxDatumSize = str((len(DefaultValue) - 2) * 2)
273                elif DefaultValue[0] == '{':
274                    MaxDatumSize = str(len(DefaultValue.split(',')))
275                else:
276                    MaxDatumSize = str(len(DefaultValue) - 1)
277                if DscOverride:
278                    Pcd.MaxDatumSize = PatchPcd.MaxDatumSize
279                # If no defined the maximum size in DSC, try to get current size from INF
280                if Pcd.MaxDatumSize in ['', None]:
281                    Pcd.MaxDatumSize = str(len(Pcd.DefaultValue.split(',')))
282            else:
283                Base1 = Base2 = 10
284                if Pcd.DefaultValue.upper().startswith('0X'):
285                    Base1 = 16
286                if DefaultValue.upper().startswith('0X'):
287                    Base2 = 16
288                try:
289                    PcdValueInImg = int(Pcd.DefaultValue, Base1)
290                    PcdValueInDscOrFdf = int(DefaultValue, Base2)
291                    if PcdValueInImg == PcdValueInDscOrFdf:
292                        continue
293                except:
294                    continue
295            # Check the Pcd size and data type
296            if Pcd.DatumType == "VOID*":
297                if int(MaxDatumSize) > int(Pcd.MaxDatumSize):
298                    EdkLogger.error("GenFds", GENFDS_ERROR, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
299                                    % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, int(MaxDatumSize) - int(Pcd.MaxDatumSize)))
300            else:
301                if PcdValueInDscOrFdf > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType] \
302                    or PcdValueInImg > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType]:
303                    EdkLogger.error("GenFds", GENFDS_ERROR, "The size of %s type PCD '%s.%s' doesn't match its data type." \
304                                    % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
305            self.PatchPcds.append((Pcd, DefaultValue))
306
307        self.InfModule = Inf
308        self.PcdIsDriver = Inf.PcdIsDriver
309        self.IsBinaryModule = Inf.IsBinaryModule
310        GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName)
311        GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid)
312        GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType)
313        GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString)
314        GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName)
315
316        #
317        # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
318        #
319
320        self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \
321                                       self.ModuleGuid + self.BaseName)
322        if not os.path.exists(self.OutputPath) :
323            os.makedirs(self.OutputPath)
324
325        self.EfiOutputPath = self.__GetEFIOutPutPath__()
326        GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)
327
328    ## PatchEfiFile
329    #
330    #  Patch EFI file with patch PCD
331    #
332    #  @param EfiFile: EFI file needs to be patched.
333    #  @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
334    #           If passed in file does not end with efi, return as is
335    #
336    def PatchEfiFile(self, EfiFile, FileType):
337        #
338        # If the module does not have any patches, then return path to input file
339        #
340        if not self.PatchPcds:
341            return EfiFile
342
343        #
344        # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED
345        #
346        if FileType != 'PE32' and self.ModuleType != "USER_DEFINED":
347            return EfiFile
348
349        #
350        # Generate path to patched output file
351        #
352        Basename = os.path.basename(EfiFile)
353        Output = os.path.normpath (os.path.join(self.OutputPath, Basename))
354
355        #
356        # If this file has already been patched, then return the path to the patched file
357        #
358        if self.PatchedBinFile == Output:
359          return Output
360
361        #
362        # If a different file from the same module has already been patched, then generate an error
363        #
364        if self.PatchedBinFile:
365            EdkLogger.error("GenFds", GENFDS_ERROR,
366                            'Only one binary file can be patched:\n'
367                            '  a binary file has been patched: %s\n'
368                            '  current file: %s' % (self.PatchedBinFile, EfiFile),
369                            File=self.InfFileName)
370
371        #
372        # Copy unpatched file contents to output file location to perform patching
373        #
374        CopyLongFilePath(EfiFile, Output)
375
376        #
377        # Apply patches to patched output file
378        #
379        for Pcd, Value in self.PatchPcds:
380            RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)
381            if RetVal:
382                EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName)
383
384        #
385        # Save the path of the patched output file
386        #
387        self.PatchedBinFile = Output
388
389        #
390        # Return path to patched output file
391        #
392        return Output
393
394    ## GenFfs() method
395    #
396    #   Generate FFS
397    #
398    #   @param  self         The object pointer
399    #   @param  Dict         dictionary contains macro and value pair
400    #   @param  FvChildAddr  Array of the inside FvImage base address
401    #   @param  FvParentAddr Parent Fv base address
402    #   @retval string       Generated FFS file name
403    #
404    def GenFfs(self, Dict = {}, FvChildAddr = [], FvParentAddr=None):
405        #
406        # Parse Inf file get Module related information
407        #
408
409        self.__InfParse__(Dict)
410        SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir , self.InfFileName);
411        DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
412
413        SrcFileDir = "."
414        SrcPath = os.path.dirname(SrcFile)
415        SrcFileName = os.path.basename(SrcFile)
416        SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName)
417        DestPath = os.path.dirname(DestFile)
418        DestFileName = os.path.basename(DestFile)
419        DestFileBase, DestFileExt = os.path.splitext(DestFileName)
420        self.MacroDict = {
421            # source file
422            "${src}"      :   SrcFile,
423            "${s_path}"   :   SrcPath,
424            "${s_dir}"    :   SrcFileDir,
425            "${s_name}"   :   SrcFileName,
426            "${s_base}"   :   SrcFileBase,
427            "${s_ext}"    :   SrcFileExt,
428            # destination file
429            "${dst}"      :   DestFile,
430            "${d_path}"   :   DestPath,
431            "${d_name}"   :   DestFileName,
432            "${d_base}"   :   DestFileBase,
433            "${d_ext}"    :   DestFileExt
434        }
435        #
436        # Allow binary type module not specify override rule in FDF file.
437        #
438        if len(self.BinFileList) > 0:
439            if self.Rule == None or self.Rule == "":
440                self.Rule = "BINARY"
441
442        #
443        # Get the rule of how to generate Ffs file
444        #
445        Rule = self.__GetRule__()
446        GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)
447        #
448        # Convert Fv File Type for PI1.1 SMM driver.
449        #
450        if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
451            if Rule.FvFileType == 'DRIVER':
452                Rule.FvFileType = 'SMM'
453        #
454        # Framework SMM Driver has no SMM FV file type
455        #
456        if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
457            if Rule.FvFileType == 'SMM' or Rule.FvFileType == 'SMM_CORE':
458                EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File=self.InfFileName)
459        #
460        # For the rule only has simpleFile
461        #
462        if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) :
463            SectionOutputList = self.__GenSimpleFileSection__(Rule)
464            FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList)
465            return FfsOutput
466        #
467        # For Rule has ComplexFile
468        #
469        elif isinstance(Rule, RuleComplexFile.RuleComplexFile):
470            InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr)
471            FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments)
472
473            return FfsOutput
474
475    ## __ExtendMacro__() method
476    #
477    #   Replace macro with its value
478    #
479    #   @param  self        The object pointer
480    #   @param  String      The string to be replaced
481    #   @retval string      Macro replaced string
482    #
483    def __ExtendMacro__ (self, String):
484        MacroDict = {
485            '$(INF_OUTPUT)'  : self.EfiOutputPath,
486            '$(MODULE_NAME)' : self.BaseName,
487            '$(BUILD_NUMBER)': self.BuildNum,
488            '$(INF_VERSION)' : self.VersionString,
489            '$(NAMED_GUID)'  : self.ModuleGuid
490        }
491        String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)
492        String = GenFdsGlobalVariable.MacroExtend(String, self.MacroDict)
493        return String
494
495    ## __GetRule__() method
496    #
497    #   Get correct rule for generating FFS for this INF
498    #
499    #   @param  self        The object pointer
500    #   @retval Rule        Rule object
501    #
502    def __GetRule__ (self) :
503        CurrentArchList = []
504        if self.CurrentArch == None:
505            CurrentArchList = ['common']
506        else:
507            CurrentArchList.append(self.CurrentArch)
508
509        for CurrentArch in CurrentArchList:
510            RuleName = 'RULE'              + \
511                       '.'                 + \
512                       CurrentArch.upper() + \
513                       '.'                 + \
514                       self.ModuleType.upper()
515            if self.Rule != None:
516                RuleName = RuleName + \
517                           '.'      + \
518                           self.Rule.upper()
519
520            Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
521            if Rule != None:
522                GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
523                return Rule
524
525        RuleName = 'RULE'      + \
526                   '.'         + \
527                   'COMMON'    + \
528                   '.'         + \
529                   self.ModuleType.upper()
530
531        if self.Rule != None:
532            RuleName = RuleName + \
533                       '.'      + \
534                       self.Rule.upper()
535
536        GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))
537
538        Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
539        if Rule != None:
540            GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
541            return Rule
542
543        if Rule == None :
544            EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \
545                            % (RuleName, self.InfFileName))
546
547    ## __GetPlatformArchList__() method
548    #
549    #   Get Arch list this INF built under
550    #
551    #   @param  self        The object pointer
552    #   @retval list        Arch list
553    #
554    def __GetPlatformArchList__(self):
555
556        InfFileKey = os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))
557        DscArchList = []
558        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IA32', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
559        if  PlatformDataBase != None:
560            if InfFileKey in PlatformDataBase.Modules:
561                DscArchList.append ('IA32')
562
563        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'X64', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
564        if  PlatformDataBase != None:
565            if InfFileKey in PlatformDataBase.Modules:
566                DscArchList.append ('X64')
567
568        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IPF', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
569        if PlatformDataBase != None:
570            if InfFileKey in (PlatformDataBase.Modules):
571                DscArchList.append ('IPF')
572
573        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'ARM', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
574        if PlatformDataBase != None:
575            if InfFileKey in (PlatformDataBase.Modules):
576                DscArchList.append ('ARM')
577
578        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'EBC', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
579        if PlatformDataBase != None:
580            if InfFileKey in (PlatformDataBase.Modules):
581                DscArchList.append ('EBC')
582
583        PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'AARCH64', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
584        if PlatformDataBase != None:
585            if InfFileKey in (PlatformDataBase.Modules):
586                DscArchList.append ('AARCH64')
587
588        return DscArchList
589
590    ## GetCurrentArch() method
591    #
592    #   Get Arch list of the module from this INF is to be placed into flash
593    #
594    #   @param  self        The object pointer
595    #   @retval list        Arch list
596    #
597    def GetCurrentArch(self) :
598
599        TargetArchList = GenFdsGlobalVariable.ArchList
600
601        PlatformArchList = self.__GetPlatformArchList__()
602
603        CurArchList = TargetArchList
604        if PlatformArchList != []:
605            CurArchList = list(set (TargetArchList) & set (PlatformArchList))
606        GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))
607
608        ArchList = []
609        if self.KeyStringList != []:
610            for Key in self.KeyStringList:
611                Key = GenFdsGlobalVariable.MacroExtend(Key)
612                Target, Tag, Arch = Key.split('_')
613                if Arch in CurArchList:
614                    ArchList.append(Arch)
615                if Target not in self.TargetOverrideList:
616                    self.TargetOverrideList.append(Target)
617        else:
618            ArchList = CurArchList
619
620        UseArchList = TargetArchList
621        if self.UseArch != None:
622            UseArchList = []
623            UseArchList.append(self.UseArch)
624            ArchList = list(set (UseArchList) & set (ArchList))
625
626        self.InfFileName = NormPath(self.InfFileName)
627        if len(PlatformArchList) == 0:
628            self.InDsc = False
629            PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
630            ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
631            if ErrorCode != 0:
632                EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
633        if len(ArchList) == 1:
634            Arch = ArchList[0]
635            return Arch
636        elif len(ArchList) > 1:
637            if len(PlatformArchList) == 0:
638                EdkLogger.error("GenFds", GENFDS_ERROR, "GenFds command line option has multiple ARCHs %s. Not able to determine which ARCH is valid for Module %s !" % (str(ArchList), self.InfFileName))
639            else:
640                EdkLogger.error("GenFds", GENFDS_ERROR, "Module built under multiple ARCHs %s. Not able to determine which output to put into flash for Module %s !" % (str(ArchList), self.InfFileName))
641        else:
642            EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s appears under ARCH %s in platform %s, but current deduced ARCH is %s, so NO build output could be put into flash." \
643                            % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))
644
645    ## __GetEFIOutPutPath__() method
646    #
647    #   Get the output path for generated files
648    #
649    #   @param  self        The object pointer
650    #   @retval string      Path that output files from this INF go to
651    #
652    def __GetEFIOutPutPath__(self):
653        Arch = ''
654        OutputPath = ''
655        (ModulePath, FileName) = os.path.split(self.InfFileName)
656        Index = FileName.rfind('.')
657        FileName = FileName[0:Index]
658        if self.OverrideGuid:
659            FileName = self.OverrideGuid
660        Arch = "NoneArch"
661        if self.CurrentArch != None:
662            Arch = self.CurrentArch
663
664        OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
665                                  Arch ,
666                                  ModulePath,
667                                  FileName,
668                                  'OUTPUT'
669                                  )
670        OutputPath = os.path.realpath(OutputPath)
671        return OutputPath
672
673    ## __GenSimpleFileSection__() method
674    #
675    #   Generate section by specified file name or a list of files with file extension
676    #
677    #   @param  self        The object pointer
678    #   @param  Rule        The rule object used to generate section
679    #   @retval string      File name of the generated section file
680    #
681    def __GenSimpleFileSection__(self, Rule):
682        #
683        # Prepare the parameter of GenSection
684        #
685        FileList = []
686        OutputFileList = []
687        GenSecInputFile = None
688        if Rule.FileName != None:
689            GenSecInputFile = self.__ExtendMacro__(Rule.FileName)
690            if os.path.isabs(GenSecInputFile):
691                GenSecInputFile = os.path.normpath(GenSecInputFile)
692            else:
693                GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))
694        else:
695            FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)
696
697        Index = 1
698        SectionType = Rule.SectionType
699        #
700        # Convert Fv Section Type for PI1.1 SMM driver.
701        #
702        if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
703            if SectionType == 'DXE_DEPEX':
704                SectionType = 'SMM_DEPEX'
705        #
706        # Framework SMM Driver has no SMM_DEPEX section type
707        #
708        if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
709            if SectionType == 'SMM_DEPEX':
710                EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
711        NoStrip = True
712        if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):
713            if self.KeepReloc != None:
714                NoStrip = self.KeepReloc
715            elif Rule.KeepReloc != None:
716                NoStrip = Rule.KeepReloc
717            elif self.ShadowFromInfFile != None:
718                NoStrip = self.ShadowFromInfFile
719
720        if FileList != [] :
721            for File in FileList:
722
723                SecNum = '%d' %Index
724                GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
725                              Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum
726                Index = Index + 1
727                OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
728                File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)
729
730                #Get PE Section alignment when align is set to AUTO
731                if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):
732                    ImageObj = PeImageClass (File)
733                    if ImageObj.SectionAlignment < 0x400:
734                        self.Alignment = str (ImageObj.SectionAlignment)
735                    else:
736                        self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'
737
738                if not NoStrip:
739                    FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
740                    if not os.path.exists(FileBeforeStrip) or \
741                           (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):
742                        CopyLongFilePath(File, FileBeforeStrip)
743                    StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
744                    GenFdsGlobalVariable.GenerateFirmwareImage(
745                                            StrippedFile,
746                                            [File],
747                                            Strip=True
748                                            )
749                    File = StrippedFile
750
751                if SectionType == 'TE':
752                    TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
753                    GenFdsGlobalVariable.GenerateFirmwareImage(
754                                            TeFile,
755                                            [File],
756                                            Type='te'
757                                            )
758                    File = TeFile
759
760                GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType])
761                OutputFileList.append(OutputFile)
762        else:
763            SecNum = '%d' %Index
764            GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
765                              Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum
766            OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
767            GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)
768
769            #Get PE Section alignment when align is set to AUTO
770            if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):
771                ImageObj = PeImageClass (GenSecInputFile)
772                if ImageObj.SectionAlignment < 0x400:
773                    self.Alignment = str (ImageObj.SectionAlignment)
774                else:
775                    self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'
776
777            if not NoStrip:
778                FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
779                if not os.path.exists(FileBeforeStrip) or \
780                       (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):
781                    CopyLongFilePath(GenSecInputFile, FileBeforeStrip)
782
783                StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
784                GenFdsGlobalVariable.GenerateFirmwareImage(
785                                        StrippedFile,
786                                        [GenSecInputFile],
787                                        Strip=True
788                                        )
789                GenSecInputFile = StrippedFile
790
791            if SectionType == 'TE':
792                TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
793                GenFdsGlobalVariable.GenerateFirmwareImage(
794                                        TeFile,
795                                        [GenSecInputFile],
796                                        Type='te'
797                                        )
798                GenSecInputFile = TeFile
799
800            GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType])
801            OutputFileList.append(OutputFile)
802
803        return OutputFileList
804
805    ## __GenSimpleFileFfs__() method
806    #
807    #   Generate FFS
808    #
809    #   @param  self        The object pointer
810    #   @param  Rule        The rule object used to generate section
811    #   @param  InputFileList        The output file list from GenSection
812    #   @retval string      Generated FFS file name
813    #
814    def __GenSimpleFileFfs__(self, Rule, InputFileList):
815        FfsOutput = self.OutputPath                     + \
816                    os.sep                              + \
817                    self.__ExtendMacro__(Rule.NameGuid) + \
818                    '.ffs'
819
820        GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))
821        InputSection = []
822        SectionAlignments = []
823        for InputFile in InputFileList:
824            InputSection.append(InputFile)
825            SectionAlignments.append(Rule.SectAlignment)
826
827        if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):
828            PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
829            if len(PcdValue) == 0:
830                EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
831                            % (Rule.NameGuid))
832            if PcdValue.startswith('{'):
833                PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
834            RegistryGuidStr = PcdValue
835            if len(RegistryGuidStr) == 0:
836                EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
837                            % (Rule.NameGuid))
838            self.ModuleGuid = RegistryGuidStr
839
840        GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,
841                                         Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],
842                                         self.ModuleGuid, Fixed=Rule.Fixed,
843                                         CheckSum=Rule.CheckSum, Align=Rule.Alignment,
844                                         SectionAlign=SectionAlignments
845                                        )
846        return FfsOutput
847
848    ## __GenComplexFileSection__() method
849    #
850    #   Generate section by sections in Rule
851    #
852    #   @param  self         The object pointer
853    #   @param  Rule         The rule object used to generate section
854    #   @param  FvChildAddr  Array of the inside FvImage base address
855    #   @param  FvParentAddr Parent Fv base address
856    #   @retval string       File name of the generated section file
857    #
858    def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr):
859        if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):
860            if Rule.KeepReloc != None:
861                self.KeepRelocFromRule = Rule.KeepReloc
862        SectFiles = []
863        SectAlignments = []
864        Index = 1
865        HasGneratedFlag = False
866        if self.PcdIsDriver == 'PEI_PCD_DRIVER':
867            if self.IsBinaryModule:
868                PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "PEIPcdDataBase.raw")
869            else:
870                PcdExDbFileName = os.path.join(self.EfiOutputPath, "PEIPcdDataBase.raw")
871            PcdExDbSecName = os.path.join(self.OutputPath, "PEIPcdDataBaseSec.raw")
872            GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,
873                                                 [PcdExDbFileName],
874                                                 "EFI_SECTION_RAW",
875                                                 )
876            SectFiles.append(PcdExDbSecName)
877            SectAlignments.append(None)
878        elif self.PcdIsDriver == 'DXE_PCD_DRIVER':
879            if self.IsBinaryModule:
880                PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "DXEPcdDataBase.raw")
881            else:
882                PcdExDbFileName = os.path.join(self.EfiOutputPath, "DXEPcdDataBase.raw")
883            PcdExDbSecName = os.path.join(self.OutputPath, "DXEPcdDataBaseSec.raw")
884            GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,
885                                                 [PcdExDbFileName],
886                                                 "EFI_SECTION_RAW",
887                                                 )
888            SectFiles.append(PcdExDbSecName)
889            SectAlignments.append(None)
890        for Sect in Rule.SectionList:
891            SecIndex = '%d' %Index
892            SectList  = []
893            #
894            # Convert Fv Section Type for PI1.1 SMM driver.
895            #
896            if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
897                if Sect.SectionType == 'DXE_DEPEX':
898                    Sect.SectionType = 'SMM_DEPEX'
899            #
900            # Framework SMM Driver has no SMM_DEPEX section type
901            #
902            if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
903                if Sect.SectionType == 'SMM_DEPEX':
904                    EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
905            #
906            # process the inside FvImage from FvSection or GuidSection
907            #
908            if FvChildAddr != []:
909                if isinstance(Sect, FvImageSection):
910                    Sect.FvAddr = FvChildAddr.pop(0)
911                elif isinstance(Sect, GuidSection):
912                    Sect.FvAddr = FvChildAddr
913            if FvParentAddr != None and isinstance(Sect, GuidSection):
914                Sect.FvParentAddr = FvParentAddr
915
916            if Rule.KeyStringList != []:
917                SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self)
918            else :
919                SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self)
920
921            if not HasGneratedFlag:
922                UniVfrOffsetFileSection = ""
923                ModuleFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)
924                InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]
925                #
926                # Search the source list in InfData to find if there are .vfr file exist.
927                #
928                VfrUniBaseName = {}
929                VfrUniOffsetList = []
930                for SourceFile in InfData.Sources:
931                    if SourceFile.Type.upper() == ".VFR" :
932                        #
933                        # search the .map file to find the offset of vfr binary in the PE32+/TE file.
934                        #
935                        VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
936                    if SourceFile.Type.upper() == ".UNI" :
937                        #
938                        # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
939                        #
940                        VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")
941
942
943                if len(VfrUniBaseName) > 0:
944                    VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)
945                    #
946                    # Generate the Raw data of raw section
947                    #
948                    os.path.join( self.OutputPath, self.BaseName + '.offset')
949                    UniVfrOffsetFileName    =  os.path.join( self.OutputPath, self.BaseName + '.offset')
950                    UniVfrOffsetFileSection =  os.path.join( self.OutputPath, self.BaseName + 'Offset' + '.raw')
951
952                    self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)
953
954                    UniVfrOffsetFileNameList = []
955                    UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
956                    """Call GenSection"""
957                    GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
958                                                         UniVfrOffsetFileNameList,
959                                                         "EFI_SECTION_RAW"
960                                                         )
961                    os.remove(UniVfrOffsetFileName)
962                    SectList.append(UniVfrOffsetFileSection)
963                    HasGneratedFlag = True
964
965            for SecName in  SectList :
966                SectFiles.append(SecName)
967                SectAlignments.append(Align)
968            Index = Index + 1
969        return SectFiles, SectAlignments
970
971    ## __GenComplexFileFfs__() method
972    #
973    #   Generate FFS
974    #
975    #   @param  self        The object pointer
976    #   @param  Rule        The rule object used to generate section
977    #   @param  InputFileList        The output file list from GenSection
978    #   @retval string      Generated FFS file name
979    #
980    def __GenComplexFileFfs__(self, Rule, InputFile, Alignments):
981
982        if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):
983            PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
984            if len(PcdValue) == 0:
985                EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
986                            % (Rule.NameGuid))
987            if PcdValue.startswith('{'):
988                PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
989            RegistryGuidStr = PcdValue
990            if len(RegistryGuidStr) == 0:
991                EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
992                            % (Rule.NameGuid))
993            self.ModuleGuid = RegistryGuidStr
994
995        FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
996        GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,
997                                         Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],
998                                         self.ModuleGuid, Fixed=Rule.Fixed,
999                                         CheckSum=Rule.CheckSum, Align=Rule.Alignment,
1000                                         SectionAlign=Alignments
1001                                        )
1002        return FfsOutput
1003
1004    ## __GetGenFfsCmdParameter__() method
1005    #
1006    #   Create parameter string for GenFfs
1007    #
1008    #   @param  self        The object pointer
1009    #   @param  Rule        The rule object used to generate section
1010    #   @retval tuple       (FileType, Fixed, CheckSum, Alignment)
1011    #
1012    def __GetGenFfsCmdParameter__(self, Rule):
1013        result = tuple()
1014        result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType])
1015        if Rule.Fixed != False:
1016            result += ('-x',)
1017        if Rule.CheckSum != False:
1018            result += ('-s',)
1019
1020        if Rule.Alignment != None and Rule.Alignment != '':
1021            result += ('-a', Rule.Alignment)
1022
1023        return result
1024
1025    ## __GetBuildOutputMapFileVfrUniInfo() method
1026    #
1027    #   Find the offset of UNI/INF object offset in the EFI image file.
1028    #
1029    #   @param  self                  The object pointer
1030    #   @param  VfrUniBaseName        A name list contain the UNI/INF object name.
1031    #   @retval RetValue              A list contain offset of UNI/INF object.
1032    #
1033    def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):
1034        MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")
1035        EfiFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".efi")
1036        return GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())
1037
1038    ## __GenUniVfrOffsetFile() method
1039    #
1040    #   Generate the offset file for the module which contain VFR or UNI file.
1041    #
1042    #   @param  self                    The object pointer
1043    #   @param  VfrUniOffsetList        A list contain the VFR/UNI offsets in the EFI image file.
1044    #   @param  UniVfrOffsetFileName    The output offset file name.
1045    #
1046    def __GenUniVfrOffsetFile(self, VfrUniOffsetList, UniVfrOffsetFileName):
1047
1048        try:
1049            fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
1050        except:
1051            EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %UniVfrOffsetFileName,None)
1052
1053        # Use a instance of StringIO to cache data
1054        fStringIO = StringIO.StringIO('')
1055
1056        for Item in VfrUniOffsetList:
1057            if (Item[0].find("Strings") != -1):
1058                #
1059                # UNI offset in image.
1060                # GUID + Offset
1061                # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1062                #
1063                UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
1064                UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]
1065                fStringIO.write(''.join(UniGuid))
1066                UniValue = pack ('Q', int (Item[1], 16))
1067                fStringIO.write (UniValue)
1068            else:
1069                #
1070                # VFR binary offset in image.
1071                # GUID + Offset
1072                # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1073                #
1074                VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
1075                VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]
1076                fStringIO.write(''.join(VfrGuid))
1077                type (Item[1])
1078                VfrValue = pack ('Q', int (Item[1], 16))
1079                fStringIO.write (VfrValue)
1080
1081        #
1082        # write data into file.
1083        #
1084        try :
1085            fInputfile.write (fStringIO.getvalue())
1086        except:
1087            EdkLogger.error("GenFds", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the file been locked or using by other applications." %UniVfrOffsetFileName,None)
1088
1089        fStringIO.close ()
1090        fInputfile.close ()
1091
1092
1093
1094
1095
1096
1097
1098
1099