1## @file GenInfFile.py
2#
3# This file contained the logical of transfer package object to INF files.
4#
5# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
6#
7# This program and the accompanying materials are licensed and made available
8# under the terms and conditions of the BSD License which accompanies this
9# 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'''
16GenInf
17'''
18import os
19import stat
20import codecs
21import md5
22from Core.FileHook import __FileHookOpen__
23from Library.String import GetSplitValueList
24from Library.Parsing import GenSection
25from Library.Parsing import GetWorkspacePackage
26from Library.Parsing import ConvertArchForInstall
27from Library.Misc import SaveFileOnChange
28from Library.Misc import IsAllModuleList
29from Library.Misc import Sdict
30from Library.Misc import ConvertPath
31from Library.Misc import ConvertSpec
32from Library.Misc import GetRelativePath
33from Library.Misc import GetLocalValue
34from Library.CommentGenerating import GenHeaderCommentSection
35from Library.CommentGenerating import GenGenericCommentF
36from Library.CommentGenerating import _GetHelpStr
37from Library import GlobalData
38from Logger import StringTable as ST
39from Logger import ToolError
40import Logger.Log as Logger
41from Library import DataType as DT
42from GenMetaFile import GenMetaFileMisc
43from Library.UniClassObject import FormatUniEntry
44
45
46## Transfer Module Object to Inf files
47#
48# Transfer all contents of a standard Module Object to an Inf file
49# @param ModuleObject: A Module Object
50#
51def ModuleToInf(ModuleObject, PackageObject=None, DistHeader=None):
52    if not GlobalData.gWSPKG_LIST:
53        GlobalData.gWSPKG_LIST = GetWorkspacePackage()
54    #
55    # Init global information for the file
56    #
57    ContainerFile = ModuleObject.GetFullPath()
58
59    Content = ''
60    #
61    # Generate file header, If any Abstract, Description, Copyright or License XML elements are missing,
62    # should 1) use the Abstract, Description, Copyright or License from the PackageSurfaceArea.Header elements
63    # that the module belongs to, or 2) if this is a stand-alone module that is not included in a PackageSurfaceArea,
64    # use the abstract, description, copyright or license from the DistributionPackage.Header elements.
65    #
66    ModuleAbstract = GetLocalValue(ModuleObject.GetAbstract())
67    if not ModuleAbstract and PackageObject:
68        ModuleAbstract = GetLocalValue(PackageObject.GetAbstract())
69    if not ModuleAbstract and DistHeader:
70        ModuleAbstract = GetLocalValue(DistHeader.GetAbstract())
71    ModuleDescription = GetLocalValue(ModuleObject.GetDescription())
72    if not ModuleDescription and PackageObject:
73        ModuleDescription = GetLocalValue(PackageObject.GetDescription())
74    if not ModuleDescription and DistHeader:
75        ModuleDescription = GetLocalValue(DistHeader.GetDescription())
76    ModuleCopyright = ''
77    for (Lang, Copyright) in ModuleObject.GetCopyright():
78        if Lang:
79            pass
80        ModuleCopyright = Copyright
81    if not ModuleCopyright and PackageObject:
82        for (Lang, Copyright) in PackageObject.GetCopyright():
83            if Lang:
84                pass
85            ModuleCopyright = Copyright
86    if not ModuleCopyright and DistHeader:
87        for (Lang, Copyright) in DistHeader.GetCopyright():
88            if Lang:
89                pass
90            ModuleCopyright = Copyright
91    ModuleLicense = ''
92    for (Lang, License) in ModuleObject.GetLicense():
93        if Lang:
94            pass
95        ModuleLicense = License
96    if not ModuleLicense and PackageObject:
97        for (Lang, License) in PackageObject.GetLicense():
98            if Lang:
99                pass
100            ModuleLicense = License
101    if not ModuleLicense and DistHeader:
102        for (Lang, License) in DistHeader.GetLicense():
103            if Lang:
104                pass
105            ModuleLicense = License
106
107    #
108    # Generate header comment section of INF file
109    #
110    Content += GenHeaderCommentSection(ModuleAbstract,
111                                       ModuleDescription,
112                                       ModuleCopyright,
113                                       ModuleLicense).replace('\r\n', '\n')
114
115    #
116    # Generate Binary Header
117    #
118    for UserExtension in ModuleObject.GetUserExtensionList():
119        if UserExtension.GetUserID() == DT.TAB_BINARY_HEADER_USERID \
120        and UserExtension.GetIdentifier() == DT.TAB_BINARY_HEADER_IDENTIFIER:
121            ModuleBinaryAbstract = GetLocalValue(UserExtension.GetBinaryAbstract())
122            ModuleBinaryDescription = GetLocalValue(UserExtension.GetBinaryDescription())
123            ModuleBinaryCopyright = ''
124            ModuleBinaryLicense = ''
125            for (Lang, Copyright) in UserExtension.GetBinaryCopyright():
126                ModuleBinaryCopyright = Copyright
127            for (Lang, License) in UserExtension.GetBinaryLicense():
128                ModuleBinaryLicense = License
129            if ModuleBinaryAbstract and ModuleBinaryDescription and \
130            ModuleBinaryCopyright and ModuleBinaryLicense:
131                Content += GenHeaderCommentSection(ModuleBinaryAbstract,
132                                           ModuleBinaryDescription,
133                                           ModuleBinaryCopyright,
134                                           ModuleBinaryLicense,
135                                           True)
136
137    #
138    # Generate MODULE_UNI_FILE for module
139    #
140    FileHeader = GenHeaderCommentSection(ModuleAbstract, ModuleDescription, ModuleCopyright, ModuleLicense, False, \
141                                         DT.TAB_COMMENT_EDK1_SPLIT)
142    GenModuleUNIEncodeFile(ModuleObject, FileHeader)
143
144    #
145    # Judge whether the INF file is an AsBuild INF.
146    #
147    if ModuleObject.BinaryModule:
148        GlobalData.gIS_BINARY_INF = True
149    else:
150        GlobalData.gIS_BINARY_INF = False
151    #
152    # for each section, maintain a dict, sorted arch will be its key,
153    # statement list will be its data
154    # { 'Arch1 Arch2 Arch3': [statement1, statement2],
155    #   'Arch1' : [statement1, statement3]
156    #  }
157    #
158    # Gen section contents
159    #
160    Content += GenDefines(ModuleObject)
161    Content += GenBuildOptions(ModuleObject)
162    Content += GenLibraryClasses(ModuleObject)
163    Content += GenPackages(ModuleObject)
164    Content += GenPcdSections(ModuleObject)
165    Content += GenSources(ModuleObject)
166    Content += GenProtocolPPiSections(ModuleObject.GetProtocolList(), True)
167    Content += GenProtocolPPiSections(ModuleObject.GetPpiList(), False)
168    Content += GenGuidSections(ModuleObject.GetGuidList())
169    Content += GenBinaries(ModuleObject)
170    Content += GenDepex(ModuleObject)
171    Content += GenUserExtensions(ModuleObject)
172    if ModuleObject.GetEventList() or ModuleObject.GetBootModeList() or ModuleObject.GetHobList():
173        Content += '\n'
174    #
175    # generate [Event], [BootMode], [Hob] section
176    #
177    Content += GenSpecialSections(ModuleObject.GetEventList(), 'Event')
178    Content += GenSpecialSections(ModuleObject.GetBootModeList(), 'BootMode')
179    Content += GenSpecialSections(ModuleObject.GetHobList(), 'Hob')
180    SaveFileOnChange(ContainerFile, Content, False)
181    if DistHeader.ReadOnly:
182        os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH)
183    else:
184        os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH)
185    return ContainerFile
186
187## GenModuleUNIEncodeFile
188# GenModuleUNIEncodeFile, default is a UCS-2LE encode file
189#
190def GenModuleUNIEncodeFile(ModuleObject, UniFileHeader='', Encoding=DT.TAB_ENCODING_UTF16LE):
191    GenUNIFlag = False
192    OnlyLANGUAGE_EN_X = True
193    BinaryAbstract = []
194    BinaryDescription = []
195    #
196    # If more than one language code is used for any element that would be present in the MODULE_UNI_FILE,
197    # then the MODULE_UNI_FILE must be created.
198    #
199    for (Key, Value) in ModuleObject.GetAbstract() + ModuleObject.GetDescription():
200        if Key == DT.TAB_LANGUAGE_EN_X:
201            GenUNIFlag = True
202        else:
203            OnlyLANGUAGE_EN_X = False
204
205    for UserExtension in ModuleObject.GetUserExtensionList():
206        if UserExtension.GetUserID() == DT.TAB_BINARY_HEADER_USERID \
207        and UserExtension.GetIdentifier() == DT.TAB_BINARY_HEADER_IDENTIFIER:
208            for (Key, Value) in UserExtension.GetBinaryAbstract():
209                if Key == DT.TAB_LANGUAGE_EN_X:
210                    GenUNIFlag = True
211                else:
212                    OnlyLANGUAGE_EN_X = False
213                BinaryAbstract.append((Key, Value))
214            for (Key, Value) in UserExtension.GetBinaryDescription():
215                if Key == DT.TAB_LANGUAGE_EN_X:
216                    GenUNIFlag = True
217                else:
218                    OnlyLANGUAGE_EN_X = False
219                BinaryDescription.append((Key, Value))
220
221
222    if not GenUNIFlag:
223        return
224    elif OnlyLANGUAGE_EN_X:
225        return
226    else:
227        ModuleObject.UNIFlag = True
228    ContainerFile = os.path.normpath(os.path.join(os.path.dirname(ModuleObject.GetFullPath()),
229                                                  (ModuleObject.GetBaseName() + '.uni')))
230    if not os.path.exists(os.path.dirname(ModuleObject.GetFullPath())):
231        os.makedirs(os.path.dirname(ModuleObject.GetFullPath()))
232
233    Content = UniFileHeader + '\r\n'
234    Content += '\r\n'
235
236    Content += FormatUniEntry('#string ' + DT.TAB_INF_ABSTRACT, ModuleObject.GetAbstract(), ContainerFile) + '\r\n'
237
238    Content += FormatUniEntry('#string ' + DT.TAB_INF_DESCRIPTION, ModuleObject.GetDescription(), ContainerFile) \
239            + '\r\n'
240
241    BinaryAbstractString = FormatUniEntry('#string ' + DT.TAB_INF_BINARY_ABSTRACT, BinaryAbstract, ContainerFile)
242    if BinaryAbstractString:
243        Content += BinaryAbstractString + '\r\n'
244
245    BinaryDescriptionString = FormatUniEntry('#string ' + DT.TAB_INF_BINARY_DESCRIPTION, BinaryDescription, \
246                                             ContainerFile)
247    if BinaryDescriptionString:
248        Content += BinaryDescriptionString + '\r\n'
249
250    if not os.path.exists(ContainerFile):
251        File = codecs.open(ContainerFile, 'wb', Encoding)
252        File.write(u'\uFEFF' + Content)
253        File.stream.close()
254    Md5Sigature = md5.new(__FileHookOpen__(str(ContainerFile), 'rb').read())
255    Md5Sum = Md5Sigature.hexdigest()
256    if (ContainerFile, Md5Sum) not in ModuleObject.FileList:
257        ModuleObject.FileList.append((ContainerFile, Md5Sum))
258
259    return ContainerFile
260def GenDefines(ModuleObject):
261    #
262    # generate [Defines] section
263    #
264    LeftOffset = 31
265    Content = ''
266    NewSectionDict = {}
267
268    for UserExtension in ModuleObject.GetUserExtensionList():
269        DefinesDict = UserExtension.GetDefinesDict()
270        if not DefinesDict:
271            continue
272        for Statement in DefinesDict:
273            if Statement.split(DT.TAB_EQUAL_SPLIT) > 1:
274                Statement = (u'%s ' % Statement.split(DT.TAB_EQUAL_SPLIT, 1)[0]).ljust(LeftOffset) \
275                             + u'= %s' % Statement.split(DT.TAB_EQUAL_SPLIT, 1)[1].lstrip()
276            SortedArch = DT.TAB_ARCH_COMMON
277            if Statement.strip().startswith(DT.TAB_INF_DEFINES_CUSTOM_MAKEFILE):
278                pos = Statement.find(DT.TAB_VALUE_SPLIT)
279                if pos == -1:
280                    pos = Statement.find(DT.TAB_EQUAL_SPLIT)
281                Makefile = ConvertPath(Statement[pos + 1:].strip())
282                Statement = Statement[:pos + 1] + ' ' + Makefile
283            if SortedArch in NewSectionDict:
284                NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [Statement]
285            else:
286                NewSectionDict[SortedArch] = [Statement]
287    SpecialStatementList = []
288
289    # TAB_INF_DEFINES_INF_VERSION
290    Statement = (u'%s ' % DT.TAB_INF_DEFINES_INF_VERSION).ljust(LeftOffset) + u'= %s' % '0x00010017'
291    SpecialStatementList.append(Statement)
292
293    # BaseName
294    BaseName = ModuleObject.GetBaseName()
295    if BaseName.startswith('.') or BaseName.startswith('-'):
296        BaseName = '_' + BaseName
297    Statement = (u'%s ' % DT.TAB_INF_DEFINES_BASE_NAME).ljust(LeftOffset) + u'= %s' % BaseName
298    SpecialStatementList.append(Statement)
299
300    # TAB_INF_DEFINES_FILE_GUID
301    Statement = (u'%s ' % DT.TAB_INF_DEFINES_FILE_GUID).ljust(LeftOffset) + u'= %s' % ModuleObject.GetGuid()
302    SpecialStatementList.append(Statement)
303
304    # TAB_INF_DEFINES_VERSION_STRING
305    Statement = (u'%s ' % DT.TAB_INF_DEFINES_VERSION_STRING).ljust(LeftOffset) + u'= %s' % ModuleObject.GetVersion()
306    SpecialStatementList.append(Statement)
307
308    # TAB_INF_DEFINES_VERSION_STRING
309    if ModuleObject.UNIFlag:
310        Statement = (u'%s ' % DT.TAB_INF_DEFINES_MODULE_UNI_FILE).ljust(LeftOffset) + \
311                    u'= %s' % ModuleObject.GetBaseName() + '.uni'
312        SpecialStatementList.append(Statement)
313
314    # TAB_INF_DEFINES_MODULE_TYPE
315    if ModuleObject.GetModuleType():
316        Statement = (u'%s ' % DT.TAB_INF_DEFINES_MODULE_TYPE).ljust(LeftOffset) + u'= %s' % ModuleObject.GetModuleType()
317        SpecialStatementList.append(Statement)
318
319    # TAB_INF_DEFINES_PCD_IS_DRIVER
320    if ModuleObject.GetPcdIsDriver():
321        Statement = (u'%s ' % DT.TAB_INF_DEFINES_PCD_IS_DRIVER).ljust(LeftOffset) + \
322                    u'= %s' % ModuleObject.GetPcdIsDriver()
323        SpecialStatementList.append(Statement)
324
325    # TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION
326    if ModuleObject.GetUefiSpecificationVersion():
327        Statement = (u'%s ' % DT.TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION).ljust(LeftOffset) + \
328                    u'= %s' % ModuleObject.GetUefiSpecificationVersion()
329        SpecialStatementList.append(Statement)
330
331    # TAB_INF_DEFINES_PI_SPECIFICATION_VERSION
332    if ModuleObject.GetPiSpecificationVersion():
333        Statement = (u'%s ' % DT.TAB_INF_DEFINES_PI_SPECIFICATION_VERSION).ljust(LeftOffset) + \
334                    u'= %s' % ModuleObject.GetPiSpecificationVersion()
335        SpecialStatementList.append(Statement)
336
337    # LibraryClass
338    for LibraryClass in ModuleObject.GetLibraryClassList():
339        if LibraryClass.GetUsage() == DT.USAGE_ITEM_PRODUCES or \
340           LibraryClass.GetUsage() == DT.USAGE_ITEM_SOMETIMES_PRODUCES:
341            Statement = (u'%s ' % DT.TAB_INF_DEFINES_LIBRARY_CLASS).ljust(LeftOffset) + \
342                        u'= %s' % LibraryClass.GetLibraryClass()
343            if LibraryClass.GetSupModuleList():
344                Statement += '|' + DT.TAB_SPACE_SPLIT.join(l for l in LibraryClass.GetSupModuleList())
345            SpecialStatementList.append(Statement)
346
347    # Spec Item
348    for SpecItem in ModuleObject.GetSpecList():
349        Spec, Version = SpecItem
350        Spec = ConvertSpec(Spec)
351        Statement = '%s %s = %s' % (DT.TAB_INF_DEFINES_SPEC, Spec, Version)
352        SpecialStatementList.append(Statement)
353
354    # Extern
355    ExternList = []
356    for Extern in ModuleObject.GetExternList():
357        ArchList = Extern.GetSupArchList()
358        EntryPoint = Extern.GetEntryPoint()
359        UnloadImage = Extern.GetUnloadImage()
360        Constructor = Extern.GetConstructor()
361        Destructor = Extern.GetDestructor()
362        HelpStringList = Extern.GetHelpTextList()
363        FFE = Extern.GetFeatureFlag()
364        ExternList.append([ArchList, EntryPoint, UnloadImage, Constructor, Destructor, FFE, HelpStringList])
365    #
366    # Add VALID_ARCHITECTURES information
367    #
368    ValidArchStatement = None
369    if ModuleObject.SupArchList:
370        ValidArchStatement = '\n' + '# ' + '\n'
371        ValidArchStatement += '# The following information is for reference only and not required by the build tools.\n'
372        ValidArchStatement += '# ' + '\n'
373        ValidArchStatement += '# VALID_ARCHITECTURES = %s' % (' '.join(ModuleObject.SupArchList)) + '\n'
374        ValidArchStatement += '# '
375    if DT.TAB_ARCH_COMMON not in NewSectionDict:
376        NewSectionDict[DT.TAB_ARCH_COMMON] = []
377    NewSectionDict[DT.TAB_ARCH_COMMON] = NewSectionDict[DT.TAB_ARCH_COMMON] + SpecialStatementList
378    GenMetaFileMisc.AddExternToDefineSec(NewSectionDict, DT.TAB_ARCH_COMMON, ExternList)
379    if ValidArchStatement is not None:
380        NewSectionDict[DT.TAB_ARCH_COMMON] = NewSectionDict[DT.TAB_ARCH_COMMON] + [ValidArchStatement]
381    Content += GenSection('Defines', NewSectionDict)
382    return Content
383
384def GenLibraryClasses(ModuleObject):
385    #
386    # generate [LibraryClasses] section
387    #
388    Content = ''
389    NewSectionDict = {}
390    if not GlobalData.gIS_BINARY_INF:
391        for LibraryClass in ModuleObject.GetLibraryClassList():
392            if LibraryClass.GetUsage() == DT.USAGE_ITEM_PRODUCES:
393                continue
394            #
395            # Generate generic comment
396            #
397            HelpTextList = LibraryClass.GetHelpTextList()
398            HelpStr = _GetHelpStr(HelpTextList)
399            CommentStr = GenGenericCommentF(HelpStr)
400            Statement = CommentStr
401            Name = LibraryClass.GetLibraryClass()
402            FFE = LibraryClass.GetFeatureFlag()
403            Statement += Name
404            if FFE:
405                Statement += '|' + FFE
406            ModuleList = LibraryClass.GetSupModuleList()
407            ArchList = LibraryClass.GetSupArchList()
408            for Index in xrange(0, len(ArchList)):
409                ArchList[Index] = ConvertArchForInstall(ArchList[Index])
410            ArchList.sort()
411            SortedArch = ' '.join(ArchList)
412            KeyList = []
413            if not ModuleList or IsAllModuleList(ModuleList):
414                KeyList = [SortedArch]
415            else:
416                ModuleString = DT.TAB_VALUE_SPLIT.join(l for l in ModuleList)
417                if not ArchList:
418                    SortedArch = DT.TAB_ARCH_COMMON
419                    KeyList = [SortedArch + '.' + ModuleString]
420                else:
421                    KeyList = [Arch + '.' + ModuleString for Arch in ArchList]
422            for Key in KeyList:
423                if Key in NewSectionDict:
424                    NewSectionDict[Key] = NewSectionDict[Key] + [Statement]
425                else:
426                    NewSectionDict[Key] = [Statement]
427        Content += GenSection('LibraryClasses', NewSectionDict)
428    else:
429        LibraryClassDict = {}
430        for BinaryFile in ModuleObject.GetBinaryFileList():
431            if not BinaryFile.AsBuiltList:
432                continue
433            for LibraryItem in BinaryFile.AsBuiltList[0].LibraryInstancesList:
434                Statement = '# Guid: ' + LibraryItem.Guid + ' Version: ' + LibraryItem.Version
435
436                if len(BinaryFile.SupArchList) == 0:
437                    if LibraryClassDict.has_key('COMMON') and Statement not in LibraryClassDict['COMMON']:
438                        LibraryClassDict['COMMON'].append(Statement)
439                    else:
440                        LibraryClassDict['COMMON'] = ['## @LIB_INSTANCES']
441                        LibraryClassDict['COMMON'].append(Statement)
442                else:
443                    for Arch in BinaryFile.SupArchList:
444                        if LibraryClassDict.has_key(Arch):
445                            if Statement not in LibraryClassDict[Arch]:
446                                LibraryClassDict[Arch].append(Statement)
447                            else:
448                                continue
449                        else:
450                            LibraryClassDict[Arch] = ['## @LIB_INSTANCES']
451                            LibraryClassDict[Arch].append(Statement)
452        Content += GenSection('LibraryClasses', LibraryClassDict)
453
454    return Content
455
456def GenPackages(ModuleObject):
457    Content = ''
458    #
459    # generate [Packages] section
460    #
461    NewSectionDict = Sdict()
462    WorkspaceDir = GlobalData.gWORKSPACE
463    for PackageDependency in ModuleObject.GetPackageDependencyList():
464        #
465        # Generate generic comment
466        #
467        CommentStr = ''
468        HelpText = PackageDependency.GetHelpText()
469        if HelpText:
470            HelpStr = HelpText.GetString()
471            CommentStr = GenGenericCommentF(HelpStr)
472        Statement = CommentStr
473        Guid = PackageDependency.GetGuid()
474        Version = PackageDependency.GetVersion()
475        FFE = PackageDependency.GetFeatureFlag()
476        Path = ''
477        #
478        # find package path/name
479        #
480        for PkgInfo in GlobalData.gWSPKG_LIST:
481            if Guid == PkgInfo[1]:
482                if (not Version) or (Version == PkgInfo[2]):
483                    Path = PkgInfo[3]
484                    break
485        #
486        # get relative path
487        #
488        RelaPath = GetRelativePath(Path, WorkspaceDir)
489        Statement += RelaPath.replace('\\', '/')
490        if FFE:
491            Statement += '|' + FFE
492        ArchList = PackageDependency.GetSupArchList()
493        ArchList.sort()
494        SortedArch = ' '.join(ArchList)
495        if SortedArch in NewSectionDict:
496            NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [Statement]
497        else:
498            NewSectionDict[SortedArch] = [Statement]
499    Content += GenSection('Packages', NewSectionDict)
500    return Content
501
502def GenSources(ModuleObject):
503    #
504    # generate [Sources] section
505    #
506    Content = ''
507    NewSectionDict = {}
508    for Source in ModuleObject.GetSourceFileList():
509        SourceFile = Source.GetSourceFile()
510        Family = Source.GetFamily()
511        FeatureFlag = Source.GetFeatureFlag()
512        SupArchList = Source.GetSupArchList()
513        SupArchList.sort()
514        SortedArch = ' '.join(SupArchList)
515        Statement = GenSourceStatement(ConvertPath(SourceFile), Family, FeatureFlag)
516        if SortedArch in NewSectionDict:
517            NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [Statement]
518        else:
519            NewSectionDict[SortedArch] = [Statement]
520    Content += GenSection('Sources', NewSectionDict)
521
522    return Content
523
524def GenDepex(ModuleObject):
525    #
526    # generate [Depex] section
527    #
528    NewSectionDict = Sdict()
529    Content = ''
530    for Depex in ModuleObject.GetPeiDepex() + ModuleObject.GetDxeDepex() + ModuleObject.GetSmmDepex():
531        HelpTextList = Depex.GetHelpTextList()
532        HelpStr = _GetHelpStr(HelpTextList)
533        CommentStr = GenGenericCommentF(HelpStr)
534        SupArchList = Depex.GetSupArchList()
535        SupModList = Depex.GetModuleType()
536        Expression = Depex.GetDepex()
537        Statement = CommentStr + Expression
538        SupArchList.sort()
539        KeyList = []
540        if not SupArchList:
541            SupArchList.append(DT.TAB_ARCH_COMMON.lower())
542        if not SupModList:
543            KeyList = SupArchList
544        else:
545            for ModuleType in SupModList:
546                for Arch in SupArchList:
547                    KeyList.append(ConvertArchForInstall(Arch) + '.' + ModuleType)
548        for Key in KeyList:
549            if Key in NewSectionDict:
550                NewSectionDict[Key] = NewSectionDict[Key] + [Statement]
551            else:
552                NewSectionDict[Key] = [Statement]
553    Content += GenSection('Depex', NewSectionDict, False)
554
555    return Content
556## GenUserExtensions
557#
558# GenUserExtensions
559#
560def GenUserExtensions(ModuleObject):
561    NewSectionDict = {}
562    for UserExtension in ModuleObject.GetUserExtensionList():
563        if UserExtension.GetUserID() == DT.TAB_BINARY_HEADER_USERID and \
564            UserExtension.GetIdentifier() == DT.TAB_BINARY_HEADER_IDENTIFIER:
565            continue
566        if UserExtension.GetIdentifier() == 'Depex':
567            continue
568        Statement = UserExtension.GetStatement()
569        if not Statement:
570            continue
571        ArchList = UserExtension.GetSupArchList()
572        for Index in xrange(0, len(ArchList)):
573            ArchList[Index] = ConvertArchForInstall(ArchList[Index])
574        ArchList.sort()
575        KeyList = []
576        CommonPreFix = ''
577        if UserExtension.GetUserID():
578            CommonPreFix = UserExtension.GetUserID()
579            if CommonPreFix.find('.') > -1:
580                CommonPreFix = '"' + CommonPreFix + '"'
581            if UserExtension.GetIdentifier():
582                CommonPreFix += '.' + '"' + UserExtension.GetIdentifier() + '"'
583            if ArchList:
584                KeyList = [CommonPreFix + '.' + Arch for Arch in ArchList]
585            else:
586                KeyList = [CommonPreFix]
587        for Key in KeyList:
588            if Key in NewSectionDict:
589                NewSectionDict[Key] = NewSectionDict[Key] + [Statement]
590            else:
591                NewSectionDict[Key] = [Statement]
592    Content = GenSection('UserExtensions', NewSectionDict, False)
593
594    return Content
595
596# GenSourceStatement
597#
598#  @param SourceFile: string of source file path/name
599#  @param Family:     string of source file family field
600#  @param FeatureFlag:  string of source file FeatureFlag field
601#  @param TagName:  string of source file TagName field
602#  @param ToolCode:  string of source file ToolCode field
603#  @param HelpStr:  string of source file HelpStr field
604#
605#  @retval Statement: The generated statement for source
606#
607def GenSourceStatement(SourceFile, Family, FeatureFlag, TagName=None,
608                       ToolCode=None, HelpStr=None):
609    Statement = ''
610    if HelpStr:
611        Statement += GenGenericCommentF(HelpStr)
612    #
613    # format of SourceFile|Family|TagName|ToolCode|FeatureFlag
614    #
615    Statement += SourceFile
616    if TagName == None:
617        TagName = ''
618    if ToolCode == None:
619        ToolCode = ''
620    if HelpStr == None:
621        HelpStr = ''
622    if FeatureFlag:
623        Statement += '|' + Family + '|' + TagName + '|' + ToolCode + '|' + FeatureFlag
624    elif ToolCode:
625        Statement += '|' + Family + '|' + TagName + '|' + ToolCode
626    elif TagName:
627        Statement += '|' + Family + '|' + TagName
628    elif Family:
629        Statement += '|' + Family
630    return Statement
631
632# GenBinaryStatement
633#
634#  @param Key:       (FileName, FileType, FFE, SortedArch)
635#  @param Value:     (Target, Family, TagName, Comment)
636#
637#
638def GenBinaryStatement(Key, Value, SubTypeGuidValue=None):
639    (FileName, FileType, FFE, SortedArch) = Key
640    if SortedArch:
641        pass
642    if Value:
643        (Target, Family, TagName, Comment) = Value
644    else:
645        Target = ''
646        Family = ''
647        TagName = ''
648        Comment = ''
649    if Comment:
650        Statement = GenGenericCommentF(Comment)
651    else:
652        Statement = ''
653    if FileType == 'SUBTYPE_GUID' and SubTypeGuidValue:
654        Statement += FileType + '|' + SubTypeGuidValue + '|' + FileName
655    else:
656        Statement += FileType + '|' + FileName
657    if FileType in DT.BINARY_FILE_TYPE_UI_LIST + DT.BINARY_FILE_TYPE_VER_LIST:
658        if FFE:
659            Statement += '|' + Target + '|' + FFE
660        elif Target:
661            Statement += '|' + Target
662    else:
663        if FFE:
664            Statement += '|' + Target + '|' + Family + '|' + TagName + '|' + FFE
665        elif TagName:
666            Statement += '|' + Target + '|' + Family + '|' + TagName
667        elif Family:
668            Statement += '|' + Target + '|' + Family
669        elif Target:
670            Statement += '|' + Target
671    return Statement
672## GenGuidSections
673#
674#  @param GuidObjList: List of GuidObject
675#  @retVal Content: The generated section contents
676#
677def GenGuidSections(GuidObjList):
678    #
679    # generate [Guids] section
680    #
681    Content = ''
682    GuidDict = Sdict()
683    for Guid in GuidObjList:
684        HelpTextList = Guid.GetHelpTextList()
685        HelpStr = _GetHelpStr(HelpTextList)
686        CName = Guid.GetCName()
687        FFE = Guid.GetFeatureFlag()
688        Statement = CName
689        if FFE:
690            Statement += '|' + FFE
691        Usage = Guid.GetUsage()
692        GuidType = Guid.GetGuidTypeList()[0]
693        VariableName = Guid.GetVariableName()
694        #
695        # Differentiate the generic comment and usage comment as multiple generic comment need to be put at first
696        #
697        if Usage == DT.ITEM_UNDEFINED and GuidType == DT.ITEM_UNDEFINED:
698            # generate list of generic comment
699            Comment = GenGenericCommentF(HelpStr)
700        else:
701            # generate list of other comment
702            Comment = HelpStr.replace('\n', ' ')
703            Comment = Comment.strip()
704            if Comment:
705                Comment = ' # ' + Comment
706            else:
707                Comment = ''
708            if Usage != DT.ITEM_UNDEFINED and GuidType == DT.ITEM_UNDEFINED:
709                Comment = '## ' + Usage + Comment
710            elif GuidType == 'Variable':
711                Comment = '## ' + Usage + ' ## ' + GuidType + ':' + VariableName + Comment
712            else:
713                Comment = '## ' + Usage + ' ## ' + GuidType + Comment
714
715            if Comment:
716                Comment += '\n'
717        #
718        # merge duplicate items
719        #
720        ArchList = Guid.GetSupArchList()
721        ArchList.sort()
722        SortedArch = ' '.join(ArchList)
723        if (Statement, SortedArch) in GuidDict:
724            PreviousComment = GuidDict[Statement, SortedArch]
725            Comment = PreviousComment + Comment
726        GuidDict[Statement, SortedArch] = Comment
727    NewSectionDict = GenMetaFileMisc.TransferDict(GuidDict, 'INF_GUID')
728    #
729    # generate the section contents
730    #
731    if NewSectionDict:
732        Content = GenSection('Guids', NewSectionDict)
733
734    return Content
735
736## GenProtocolPPiSections
737#
738#  @param ObjList: List of ProtocolObject or Ppi Object
739#  @retVal Content: The generated section contents
740#
741def GenProtocolPPiSections(ObjList, IsProtocol):
742    Content = ''
743    Dict = Sdict()
744    for Object in ObjList:
745        HelpTextList = Object.GetHelpTextList()
746        HelpStr = _GetHelpStr(HelpTextList)
747        CName = Object.GetCName()
748        FFE = Object.GetFeatureFlag()
749        Statement = CName
750        if FFE:
751            Statement += '|' + FFE
752        Usage = Object.GetUsage()
753        Notify = Object.GetNotify()
754        #
755        # Differentiate the generic comment and usage comment as consecutive generic comment need to be put together
756        #
757        if Usage == DT.ITEM_UNDEFINED and Notify == '':
758            # generate list of generic comment
759            Comment = GenGenericCommentF(HelpStr)
760        else:
761            # generate list of other comment
762            Comment = HelpStr.replace('\n', ' ')
763            Comment = Comment.strip()
764            if Comment:
765                Comment = ' # ' + Comment
766            else:
767                Comment = ''
768            if Usage == DT.ITEM_UNDEFINED and not Comment and Notify == '':
769                Comment = ''
770            else:
771                if Notify:
772                    Comment = '## ' + Usage + ' ## ' + 'NOTIFY' + Comment
773                else:
774                    Comment = '## ' + Usage + Comment
775            if Comment:
776                Comment += '\n'
777        #
778        # merge duplicate items
779        #
780        ArchList = Object.GetSupArchList()
781        ArchList.sort()
782        SortedArch = ' '.join(ArchList)
783        if (Statement, SortedArch) in Dict:
784            PreviousComment = Dict[Statement, SortedArch]
785            Comment = PreviousComment + Comment
786        Dict[Statement, SortedArch] = Comment
787    NewSectionDict = GenMetaFileMisc.TransferDict(Dict, 'INF_PPI_PROTOCOL')
788    #
789    # generate the section contents
790    #
791    if NewSectionDict:
792        if IsProtocol:
793            Content = GenSection('Protocols', NewSectionDict)
794        else:
795            Content = GenSection('Ppis', NewSectionDict)
796
797    return Content
798
799## GenPcdSections
800#
801#
802def GenPcdSections(ModuleObject):
803    Content = ''
804    if not GlobalData.gIS_BINARY_INF:
805        #
806        # for each Pcd Itemtype, maintain a dict so the same type will be grouped
807        # together
808        #
809        ItemTypeDict = {}
810        for Pcd in ModuleObject.GetPcdList():
811            HelpTextList = Pcd.GetHelpTextList()
812            HelpStr = _GetHelpStr(HelpTextList)
813            Statement = ''
814            CName = Pcd.GetCName()
815            TokenSpaceGuidCName = Pcd.GetTokenSpaceGuidCName()
816            DefaultValue = Pcd.GetDefaultValue()
817            ItemType = Pcd.GetItemType()
818            if ItemType in ItemTypeDict:
819                Dict = ItemTypeDict[ItemType]
820            else:
821                Dict = Sdict()
822                ItemTypeDict[ItemType] = Dict
823            FFE = Pcd.GetFeatureFlag()
824            Statement += TokenSpaceGuidCName + '.' + CName
825            if DefaultValue:
826                Statement += '|' + DefaultValue
827                if FFE:
828                    Statement += '|' + FFE
829            elif FFE:
830                Statement += '||' + FFE
831            #
832            # Generate comment
833            #
834            Usage = Pcd.GetValidUsage()
835            # if FeatureFlag Pcd, then assume all Usage is CONSUMES
836            if ItemType == DT.TAB_INF_FEATURE_PCD:
837                Usage = DT.USAGE_ITEM_CONSUMES
838            if Usage == DT.ITEM_UNDEFINED:
839                # generate list of generic comment
840                Comment = GenGenericCommentF(HelpStr)
841            else:
842                # generate list of other comment
843                Comment = HelpStr.replace('\n', ' ')
844                Comment = Comment.strip()
845                if Comment:
846                    Comment = ' # ' + Comment
847                else:
848                    Comment = ''
849                Comment = '## ' + Usage + Comment
850                if Comment:
851                    Comment += '\n'
852            #
853            # Merge duplicate entries
854            #
855            ArchList = Pcd.GetSupArchList()
856            ArchList.sort()
857            SortedArch = ' '.join(ArchList)
858            if (Statement, SortedArch) in Dict:
859                PreviousComment = Dict[Statement, SortedArch]
860                Comment = PreviousComment + Comment
861            Dict[Statement, SortedArch] = Comment
862        for ItemType in ItemTypeDict:
863            # First we need to transfer the Dict to use SortedArch as key
864            Dict = ItemTypeDict[ItemType]
865            NewSectionDict = GenMetaFileMisc.TransferDict(Dict, 'INF_PCD')
866            if NewSectionDict:
867                Content += GenSection(ItemType, NewSectionDict)
868    #
869    # For AsBuild INF files
870    #
871    else:
872        Content += GenAsBuiltPacthPcdSections(ModuleObject)
873        Content += GenAsBuiltPcdExSections(ModuleObject)
874
875    return Content
876
877## GenPcdSections
878#
879#
880def GenAsBuiltPacthPcdSections(ModuleObject):
881    PatchPcdDict = {}
882    for BinaryFile in ModuleObject.GetBinaryFileList():
883        if not BinaryFile.AsBuiltList:
884            continue
885        for PatchPcd in BinaryFile.AsBuiltList[0].PatchPcdList:
886            TokenSpaceName = ''
887            PcdCName = PatchPcd.CName
888            PcdValue = PatchPcd.DefaultValue
889            PcdOffset = PatchPcd.Offset
890            TokenSpaceGuidValue = PatchPcd.TokenSpaceGuidValue
891            Token = PatchPcd.Token
892            HelpTextList = PatchPcd.HelpTextList
893            HelpString = ''
894            for HelpStringItem in HelpTextList:
895                for HelpLine in GetSplitValueList(HelpStringItem.String, '\n'):
896                    HelpString += '## ' + HelpLine + '\n'
897            TokenSpaceName, PcdCName = GenMetaFileMisc.ObtainPcdName(ModuleObject.PackageDependencyList,
898                                                                     TokenSpaceGuidValue,
899                                                                     Token)
900            if TokenSpaceName == '' or PcdCName == '':
901                Logger.Error("Upt",
902                             ToolError.RESOURCE_NOT_AVAILABLE,
903                             ST.ERR_INSTALL_FILE_DEC_FILE_ERROR % (TokenSpaceGuidValue, Token),
904                             File=ModuleObject.GetFullPath())
905            Statement = HelpString + TokenSpaceName + '.' + PcdCName + ' | ' + PcdValue + ' | ' + \
906                         PcdOffset + DT.TAB_SPACE_SPLIT
907            #
908            # Use binary file's Arch to be Pcd's Arch
909            #
910            ArchList = []
911            FileNameObjList = BinaryFile.GetFileNameList()
912            if FileNameObjList:
913                ArchList = FileNameObjList[0].GetSupArchList()
914            if len(ArchList) == 0:
915                if PatchPcdDict.has_key(DT.TAB_ARCH_COMMON):
916                    if Statement not in PatchPcdDict[DT.TAB_ARCH_COMMON]:
917                        PatchPcdDict[DT.TAB_ARCH_COMMON].append(Statement)
918                else:
919                    PatchPcdDict[DT.TAB_ARCH_COMMON] = [Statement]
920            else:
921                for Arch in ArchList:
922                    if PatchPcdDict.has_key(Arch):
923                        if Statement not in PatchPcdDict[Arch]:
924                            PatchPcdDict[Arch].append(Statement)
925                    else:
926                        PatchPcdDict[Arch] = [Statement]
927    return GenSection(DT.TAB_INF_PATCH_PCD, PatchPcdDict)
928## GenPcdSections
929#
930#
931def GenAsBuiltPcdExSections(ModuleObject):
932    PcdExDict = {}
933    for BinaryFile in ModuleObject.GetBinaryFileList():
934        if not BinaryFile.AsBuiltList:
935            continue
936        for PcdExItem in BinaryFile.AsBuiltList[0].PcdExValueList:
937            TokenSpaceName = ''
938            PcdCName = PcdExItem.CName
939            TokenSpaceGuidValue = PcdExItem.TokenSpaceGuidValue
940            Token = PcdExItem.Token
941            HelpTextList = PcdExItem.HelpTextList
942            HelpString = ''
943            for HelpStringItem in HelpTextList:
944                for HelpLine in GetSplitValueList(HelpStringItem.String, '\n'):
945                    HelpString += '## ' + HelpLine + '\n'
946            TokenSpaceName, PcdCName = GenMetaFileMisc.ObtainPcdName(ModuleObject.PackageDependencyList,
947                                                                     TokenSpaceGuidValue, Token)
948            if TokenSpaceName == '' or PcdCName == '':
949                Logger.Error("Upt",
950                             ToolError.RESOURCE_NOT_AVAILABLE,
951                             ST.ERR_INSTALL_FILE_DEC_FILE_ERROR % (TokenSpaceGuidValue, Token),
952                             File=ModuleObject.GetFullPath())
953
954            Statement = HelpString + TokenSpaceName + DT.TAB_SPLIT + PcdCName + DT.TAB_SPACE_SPLIT
955
956            #
957            # Use binary file's Arch to be Pcd's Arch
958            #
959            ArchList = []
960            FileNameObjList = BinaryFile.GetFileNameList()
961            if FileNameObjList:
962                ArchList = FileNameObjList[0].GetSupArchList()
963
964            if len(ArchList) == 0:
965                if PcdExDict.has_key('COMMON'):
966                    PcdExDict['COMMON'].append(Statement)
967                else:
968                    PcdExDict['COMMON'] = [Statement]
969            else:
970                for Arch in ArchList:
971                    if PcdExDict.has_key(Arch):
972                        if Statement not in PcdExDict[Arch]:
973                            PcdExDict[Arch].append(Statement)
974                    else:
975                        PcdExDict[Arch] = [Statement]
976    return GenSection('PcdEx', PcdExDict)
977
978## GenSpecialSections
979#  generate special sections for Event/BootMode/Hob
980#
981def GenSpecialSections(ObjectList, SectionName):
982    #
983    # generate section
984    #
985    Content = ''
986    NewSectionDict = {}
987    for Obj in ObjectList:
988        #
989        # Generate comment
990        #
991        CommentStr = ''
992        HelpTextList = Obj.GetHelpTextList()
993        HelpStr = _GetHelpStr(HelpTextList)
994        CommentStr = GenGenericCommentF(HelpStr)
995        if SectionName == 'Hob':
996            Type = Obj.GetHobType()
997        elif SectionName == 'Event':
998            Type = Obj.GetEventType()
999        elif SectionName == 'BootMode':
1000            Type = Obj.GetSupportedBootModes()
1001        else:
1002            assert(SectionName)
1003        Usage = Obj.GetUsage()
1004        Statement = ' ' + Type + ' ## ' + Usage
1005        if CommentStr in ['#\n', '#\n#\n']:
1006            CommentStr = '#\n#\n#\n'
1007        #
1008        # the first head comment line should start with '##\n', if it starts with '#\n', then add one '#'
1009        # else add '##\n' to meet the format defined in INF spec
1010        #
1011        if CommentStr.startswith('#\n'):
1012            CommentStr = '#' + CommentStr
1013        elif CommentStr:
1014            CommentStr = '##\n' + CommentStr
1015        if CommentStr and not CommentStr.endswith('\n#\n'):
1016            CommentStr = CommentStr + '#\n'
1017        NewStateMent = CommentStr + Statement
1018        SupArch = Obj.GetSupArchList()
1019        SupArch.sort()
1020        SortedArch = ' '.join(SupArch)
1021        if SortedArch in NewSectionDict:
1022            NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [NewStateMent]
1023        else:
1024            NewSectionDict[SortedArch] = [NewStateMent]
1025    SectionContent = GenSection(SectionName, NewSectionDict)
1026    SectionContent = SectionContent.strip()
1027    if SectionContent:
1028        Content = '# ' + ('\n' + '# ').join(GetSplitValueList(SectionContent, '\n'))
1029        Content = Content.lstrip()
1030    #
1031    # add a return to differentiate it between other possible sections
1032    #
1033    if Content:
1034        Content += '\n'
1035    return Content
1036## GenBuildOptions
1037#
1038#
1039def GenBuildOptions(ModuleObject):
1040    Content = ''
1041    if not ModuleObject.BinaryModule:
1042        #
1043        # generate [BuildOptions] section
1044        #
1045        NewSectionDict = {}
1046        for UserExtension in ModuleObject.GetUserExtensionList():
1047            BuildOptionDict = UserExtension.GetBuildOptionDict()
1048            if not BuildOptionDict:
1049                continue
1050            for Arch in BuildOptionDict:
1051                if Arch in NewSectionDict:
1052                    NewSectionDict[Arch] = NewSectionDict[Arch] + [BuildOptionDict[Arch]]
1053                else:
1054                    NewSectionDict[Arch] = [BuildOptionDict[Arch]]
1055        Content = GenSection('BuildOptions', NewSectionDict)
1056    else:
1057        BuildOptionDict = {}
1058        for BinaryFile in ModuleObject.GetBinaryFileList():
1059            if not BinaryFile.AsBuiltList:
1060                continue
1061            for BuilOptionItem in BinaryFile.AsBuiltList[0].BinaryBuildFlagList:
1062                Statement = '#' + BuilOptionItem.AsBuiltOptionFlags
1063                if len(BinaryFile.SupArchList) == 0:
1064                    if BuildOptionDict.has_key('COMMON'):
1065                        if Statement not in BuildOptionDict['COMMON']:
1066                            BuildOptionDict['COMMON'].append(Statement)
1067                    else:
1068                        BuildOptionDict['COMMON'] = ['## @AsBuilt']
1069                        BuildOptionDict['COMMON'].append(Statement)
1070                else:
1071                    for Arch in BinaryFile.SupArchList:
1072                        if BuildOptionDict.has_key(Arch):
1073                            if Statement not in BuildOptionDict[Arch]:
1074                                BuildOptionDict[Arch].append(Statement)
1075                        else:
1076                            BuildOptionDict[Arch] = ['## @AsBuilt']
1077                            BuildOptionDict[Arch].append(Statement)
1078        Content = GenSection('BuildOptions', BuildOptionDict)
1079
1080    return Content
1081## GenBinaries
1082#
1083#
1084def GenBinaries(ModuleObject):
1085    NewSectionDict = {}
1086    BinariesDict = []
1087    for UserExtension in ModuleObject.GetUserExtensionList():
1088        BinariesDict = UserExtension.GetBinariesDict()
1089        if BinariesDict:
1090            break
1091    for BinaryFile in ModuleObject.GetBinaryFileList():
1092        FileNameObjList = BinaryFile.GetFileNameList()
1093        for FileNameObj in FileNameObjList:
1094            FileName = ConvertPath(FileNameObj.GetFilename())
1095            FileType = FileNameObj.GetFileType()
1096            FFE = FileNameObj.GetFeatureFlag()
1097            ArchList = FileNameObj.GetSupArchList()
1098            ArchList.sort()
1099            SortedArch = ' '.join(ArchList)
1100            Key = (FileName, FileType, FFE, SortedArch)
1101            if Key in BinariesDict:
1102                ValueList = BinariesDict[Key]
1103                for ValueItem in ValueList:
1104                    Statement = GenBinaryStatement(Key, ValueItem)
1105                    if SortedArch in NewSectionDict:
1106                        NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [Statement]
1107                    else:
1108                        NewSectionDict[SortedArch] = [Statement]
1109                #
1110                # as we already generated statement for this DictKey here set the Valuelist to be empty
1111                # to avoid generate duplicate entries as the DictKey may have multiple entries
1112                #
1113                BinariesDict[Key] = []
1114            else:
1115                if FileType == 'SUBTYPE_GUID' and FileNameObj.GetGuidValue():
1116                    Statement = GenBinaryStatement(Key, None, FileNameObj.GetGuidValue())
1117                else:
1118                    Statement = GenBinaryStatement(Key, None)
1119                if SortedArch in NewSectionDict:
1120                    NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [Statement]
1121                else:
1122                    NewSectionDict[SortedArch] = [Statement]
1123    Content = GenSection('Binaries', NewSectionDict)
1124
1125    return Content
1126