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