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