1## @file GenDecFile.py
2#
3# This file contained the logical of transfer package object to DEC files.
4#
5# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
6#
7# SPDX-License-Identifier: BSD-2-Clause-Patent
8#
9
10'''
11GenDEC
12'''
13import os
14import stat
15import codecs
16from hashlib import md5
17from Core.FileHook import __FileHookOpen__
18from Library.Parsing import GenSection
19from Library.CommentGenerating import GenHeaderCommentSection
20from Library.CommentGenerating import GenGenericCommentF
21from Library.CommentGenerating import GenDecTailComment
22from Library.CommentGenerating import _GetHelpStr
23from Library.Misc import GuidStringToGuidStructureString
24from Library.Misc import SaveFileOnChange
25from Library.Misc import ConvertPath
26from Library.Misc import GetLocalValue
27from Library.DataType import TAB_SPACE_SPLIT
28from Library.DataType import TAB_COMMA_SPLIT
29from Library.DataType import END_OF_LINE
30from Library.DataType import TAB_ARCH_COMMON
31from Library.DataType import TAB_VALUE_SPLIT
32from Library.DataType import TAB_COMMENT_SPLIT
33from Library.DataType import TAB_PCD_VALIDRANGE
34from Library.DataType import TAB_PCD_VALIDLIST
35from Library.DataType import TAB_PCD_EXPRESSION
36from Library.DataType import TAB_DEC_DEFINES_DEC_SPECIFICATION
37from Library.DataType import TAB_DEC_DEFINES_PACKAGE_NAME
38from Library.DataType import TAB_DEC_DEFINES_PACKAGE_GUID
39from Library.DataType import TAB_DEC_DEFINES_PACKAGE_VERSION
40from Library.DataType import TAB_DEC_DEFINES_PKG_UNI_FILE
41from Library.DataType import TAB_DEC_PACKAGE_ABSTRACT
42from Library.DataType import TAB_DEC_PACKAGE_DESCRIPTION
43from Library.DataType import TAB_DEC_BINARY_ABSTRACT
44from Library.DataType import TAB_DEC_BINARY_DESCRIPTION
45from Library.DataType import TAB_LANGUAGE_EN_X
46from Library.DataType import TAB_BINARY_HEADER_USERID
47from Library.DataType import TAB_BINARY_HEADER_IDENTIFIER
48from Library.DataType import TAB_COMMENT_EDK1_SPLIT
49from Library.DataType import TAB_ENCODING_UTF16LE
50from Library.DataType import TAB_CAPHEX_START
51from Library.DataType import TAB_HEX_START
52from Library.DataType import TAB_UNDERLINE_SPLIT
53from Library.DataType import TAB_STR_TOKENERR
54from Library.DataType import TAB_STR_TOKENCNAME
55from Library.DataType import TAB_PCD_ERROR_SECTION_COMMENT
56from Library.DataType import TAB_PCD_ERROR
57from Library.DataType import TAB_SECTION_START
58from Library.DataType import TAB_SECTION_END
59from Library.DataType import TAB_SPLIT
60import Library.DataType as DT
61from Library.UniClassObject import FormatUniEntry
62from Library.StringUtils import GetUniFileName
63
64def GenPcd(Package, Content):
65    #
66    # generate [Pcd] section
67    # <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>
68    #
69    ValidUsageDict = {}
70    for Pcd in Package.GetPcdList():
71        #
72        # Generate generic comment
73        #
74        HelpTextList = Pcd.GetHelpTextList()
75        HelpStr = _GetHelpStr(HelpTextList)
76        CommentStr = GenGenericCommentF(HelpStr, 2)
77
78        PromptList = Pcd.GetPromptList()
79        PromptStr = _GetHelpStr(PromptList)
80        CommentStr += GenGenericCommentF(PromptStr.strip(), 1, True)
81
82        PcdErrList = Pcd.GetPcdErrorsList()
83        for PcdErr in PcdErrList:
84            CommentStr += GenPcdErrComment(PcdErr)
85        Statement = CommentStr
86
87        CName = Pcd.GetCName()
88        TokenSpaceGuidCName = Pcd.GetTokenSpaceGuidCName()
89        DefaultValue = Pcd.GetDefaultValue()
90        DatumType = Pcd.GetDatumType()
91        Token = Pcd.GetToken()
92        ValidUsage = Pcd.GetValidUsage()
93
94        if ValidUsage == 'FeaturePcd':
95            ValidUsage = 'PcdsFeatureFlag'
96        elif ValidUsage == 'PatchPcd':
97            ValidUsage = 'PcdsPatchableInModule'
98        elif ValidUsage == 'FixedPcd':
99            ValidUsage = 'PcdsFixedAtBuild'
100        elif ValidUsage == 'Pcd':
101            ValidUsage = 'PcdsDynamic'
102        elif ValidUsage == 'PcdEx':
103            ValidUsage = 'PcdsDynamicEx'
104
105        if ValidUsage in ValidUsageDict:
106            NewSectionDict = ValidUsageDict[ValidUsage]
107        else:
108            NewSectionDict = {}
109            ValidUsageDict[ValidUsage] = NewSectionDict
110        Statement += TokenSpaceGuidCName + '.' + CName
111        Statement += '|' + DefaultValue
112        Statement += '|' + DatumType
113        Statement += '|' + Token
114        #
115        # generate tail comment
116        #
117        if Pcd.GetSupModuleList():
118            Statement += GenDecTailComment(Pcd.GetSupModuleList())
119
120        ArchList = sorted(Pcd.GetSupArchList())
121        SortedArch = ' '.join(ArchList)
122        if SortedArch in NewSectionDict:
123            NewSectionDict[SortedArch] = \
124            NewSectionDict[SortedArch] + [Statement]
125        else:
126            NewSectionDict[SortedArch] = [Statement]
127
128    for ValidUsage in ValidUsageDict:
129        Content += GenSection(ValidUsage, ValidUsageDict[ValidUsage], True, True)
130
131    return Content
132
133def GenPcdErrorMsgSection(Package, Content):
134    if not Package.PcdErrorCommentDict:
135        return Content
136
137    #
138    # Generate '# [Error.<TokenSpcCName>]' section
139    #
140    Content += END_OF_LINE + END_OF_LINE
141    SectionComment = TAB_COMMENT_SPLIT + END_OF_LINE
142    SectionComment += TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_ERROR_SECTION_COMMENT + END_OF_LINE
143    SectionComment += TAB_COMMENT_SPLIT + END_OF_LINE
144    TokenSpcCNameList = []
145
146    #
147    # Get TokenSpcCName list in PcdErrorCommentDict in Package object
148    #
149    for (TokenSpcCName, ErrorNumber) in Package.PcdErrorCommentDict:
150        if TokenSpcCName not in TokenSpcCNameList:
151            TokenSpcCNameList.append(TokenSpcCName)
152
153    for TokenSpcCNameItem in TokenSpcCNameList:
154        SectionName = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_SECTION_START + TAB_PCD_ERROR + \
155                      TAB_SPLIT + TokenSpcCNameItem + TAB_SECTION_END + END_OF_LINE
156        Content += SectionComment
157        Content += SectionName
158        for (TokenSpcCName, ErrorNumber) in Package.PcdErrorCommentDict:
159            if TokenSpcCNameItem == TokenSpcCName:
160                PcdErrorMsg = GetLocalValue(Package.PcdErrorCommentDict[(TokenSpcCName, ErrorNumber)])
161                SectionItem = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_SPACE_SPLIT + \
162                              ErrorNumber + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT + \
163                              PcdErrorMsg + END_OF_LINE
164                Content += SectionItem
165
166    Content += TAB_COMMENT_SPLIT
167    return Content
168
169def GenGuidProtocolPpi(Package, Content):
170    #
171    # generate [Guids] section
172    #
173    NewSectionDict = {}
174
175    LeftOffset = 46
176    # Get the line offset need
177    # If the real one < the min one, use the min one
178    # else use the real one
179    for Guid in Package.GetGuidList():
180        if len(Guid.GetCName()) > LeftOffset:
181            LeftOffset = len(Guid.GetCName())
182
183    # Generate
184    for Guid in Package.GetGuidList():
185        #
186        # Generate generic comment
187        #
188        HelpTextList = Guid.GetHelpTextList()
189        HelpStr = _GetHelpStr(HelpTextList)
190        CommentStr = GenGenericCommentF(HelpStr, 2)
191
192        Statement = CommentStr
193        CName = Guid.GetCName()
194        Value = GuidStringToGuidStructureString(Guid.GetGuid())
195        Statement += CName.ljust(LeftOffset) + ' = ' + Value
196        #
197        # generate tail comment
198        #
199        if Guid.GetSupModuleList():
200            Statement += GenDecTailComment(Guid.GetSupModuleList())
201        ArchList = sorted(Guid.GetSupArchList())
202        SortedArch = ' '.join(ArchList)
203        if SortedArch in NewSectionDict:
204            NewSectionDict[SortedArch] = \
205            NewSectionDict[SortedArch] + [Statement]
206        else:
207            NewSectionDict[SortedArch] = [Statement]
208
209    Content += GenSection('Guids', NewSectionDict, True, True)
210
211    #
212    # generate [Protocols] section
213    #
214    NewSectionDict = {}
215    LeftOffset = 46
216    # Get the line offset need
217    # If the real one < the min one, use the min one
218    # else use the real one
219    for Protocol in Package.GetProtocolList():
220        if len(Protocol.GetCName()) > LeftOffset:
221            LeftOffset = len(Protocol.GetCName())
222
223    for Protocol in Package.GetProtocolList():
224        #
225        # Generate generic comment
226        #
227        HelpTextList = Protocol.GetHelpTextList()
228        HelpStr = _GetHelpStr(HelpTextList)
229        CommentStr = GenGenericCommentF(HelpStr, 2)
230
231        Statement = CommentStr
232        CName = Protocol.GetCName()
233        Value = GuidStringToGuidStructureString(Protocol.GetGuid())
234        Statement += CName.ljust(LeftOffset) + ' = ' + Value
235
236        #
237        # generate tail comment
238        #
239        if Protocol.GetSupModuleList():
240            Statement += GenDecTailComment(Protocol.GetSupModuleList())
241        ArchList = sorted(Protocol.GetSupArchList())
242        SortedArch = ' '.join(ArchList)
243        if SortedArch in NewSectionDict:
244            NewSectionDict[SortedArch] = \
245            NewSectionDict[SortedArch] + [Statement]
246        else:
247            NewSectionDict[SortedArch] = [Statement]
248
249    Content += GenSection('Protocols', NewSectionDict, True, True)
250
251    #
252    # generate [Ppis] section
253    #
254    NewSectionDict = {}
255    LeftOffset = 46
256    # Get the line offset need
257    # If the real one < the min one, use the min one
258    # else use the real one
259    for Ppi in Package.GetPpiList():
260        if len(Ppi.GetCName()) > LeftOffset:
261            LeftOffset = len(Ppi.GetCName())
262
263    for Ppi in Package.GetPpiList():
264        #
265        # Generate generic comment
266        #
267        HelpTextList = Ppi.GetHelpTextList()
268        HelpStr = _GetHelpStr(HelpTextList)
269        CommentStr = GenGenericCommentF(HelpStr, 2)
270
271        Statement = CommentStr
272        CName = Ppi.GetCName()
273        Value = GuidStringToGuidStructureString(Ppi.GetGuid())
274        Statement += CName.ljust(LeftOffset) + ' = ' + Value
275
276        #
277        # generate tail comment
278        #
279        if Ppi.GetSupModuleList():
280            Statement += GenDecTailComment(Ppi.GetSupModuleList())
281        ArchList = sorted(Ppi.GetSupArchList())
282        SortedArch = ' '.join(ArchList)
283        if SortedArch in NewSectionDict:
284            NewSectionDict[SortedArch] = \
285            NewSectionDict[SortedArch] + [Statement]
286        else:
287            NewSectionDict[SortedArch] = [Statement]
288
289    Content += GenSection('Ppis', NewSectionDict, True, True)
290
291    return Content
292
293## Transfer Package Object to Dec files
294#
295# Transfer all contents of a standard Package Object to a Dec file
296#
297# @param Package:  A Package
298#
299def PackageToDec(Package, DistHeader = None):
300    #
301    # Init global information for the file
302    #
303    ContainerFile = Package.GetFullPath()
304
305    Content = ''
306
307    #
308    # Generate file header
309    #
310    PackageAbstract = GetLocalValue(Package.GetAbstract())
311    PackageDescription = GetLocalValue(Package.GetDescription())
312    PackageCopyright = ''
313    PackageLicense = ''
314    for (Lang, Copyright) in Package.GetCopyright():
315        if Lang:
316            pass
317        PackageCopyright = Copyright
318    for (Lang, License) in Package.GetLicense():
319        if Lang:
320            pass
321        PackageLicense = License
322    if not PackageAbstract and DistHeader:
323        PackageAbstract = GetLocalValue(DistHeader.GetAbstract())
324    if not PackageDescription and DistHeader:
325        PackageDescription = GetLocalValue(DistHeader.GetDescription())
326    if not PackageCopyright and DistHeader:
327        for (Lang, Copyright) in DistHeader.GetCopyright():
328            PackageCopyright = Copyright
329    if not PackageLicense and DistHeader:
330        for (Lang, License) in DistHeader.GetLicense():
331            PackageLicense = License
332
333    #
334    # Generate header comment section of DEC file
335    #
336    Content += GenHeaderCommentSection(PackageAbstract, \
337                                       PackageDescription, \
338                                       PackageCopyright, \
339                                       PackageLicense).replace('\r\n', '\n')
340
341    #
342    # Generate Binary header
343    #
344    for UserExtension in Package.GetUserExtensionList():
345        if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID \
346        and UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER:
347            PackageBinaryAbstract = GetLocalValue(UserExtension.GetBinaryAbstract())
348            PackageBinaryDescription = GetLocalValue(UserExtension.GetBinaryDescription())
349            PackageBinaryCopyright = ''
350            PackageBinaryLicense = ''
351            for (Lang, Copyright) in UserExtension.GetBinaryCopyright():
352                PackageBinaryCopyright = Copyright
353            for (Lang, License) in UserExtension.GetBinaryLicense():
354                PackageBinaryLicense = License
355            if PackageBinaryAbstract and PackageBinaryDescription and \
356            PackageBinaryCopyright and PackageBinaryLicense:
357                Content += GenHeaderCommentSection(PackageBinaryAbstract,
358                                           PackageBinaryDescription,
359                                           PackageBinaryCopyright,
360                                           PackageBinaryLicense,
361                                           True)
362
363    #
364    # Generate PACKAGE_UNI_FILE for the Package
365    #
366    FileHeader = GenHeaderCommentSection(PackageAbstract, PackageDescription, PackageCopyright, PackageLicense, False, \
367                                         TAB_COMMENT_EDK1_SPLIT)
368    GenPackageUNIEncodeFile(Package, FileHeader)
369
370    #
371    # for each section, maintain a dict, sorted arch will be its key,
372    #statement list will be its data
373    # { 'Arch1 Arch2 Arch3': [statement1, statement2],
374    #   'Arch1' : [statement1, statement3]
375    #  }
376    #
377
378    #
379    # generate [Defines] section
380    #
381    LeftOffset = 31
382    NewSectionDict = {TAB_ARCH_COMMON : []}
383    SpecialItemList = []
384
385    Statement = (u'%s ' % TAB_DEC_DEFINES_DEC_SPECIFICATION).ljust(LeftOffset) + u'= %s' % '0x00010017'
386    SpecialItemList.append(Statement)
387
388    BaseName = Package.GetBaseName()
389    if BaseName.startswith('.') or BaseName.startswith('-'):
390        BaseName = '_' + BaseName
391    Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_NAME).ljust(LeftOffset) + u'= %s' % BaseName
392    SpecialItemList.append(Statement)
393
394    Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_VERSION).ljust(LeftOffset) + u'= %s' % Package.GetVersion()
395    SpecialItemList.append(Statement)
396
397    Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_GUID).ljust(LeftOffset) + u'= %s' % Package.GetGuid()
398    SpecialItemList.append(Statement)
399
400    if Package.UNIFlag:
401        Statement = (u'%s ' % TAB_DEC_DEFINES_PKG_UNI_FILE).ljust(LeftOffset) + u'= %s' % Package.GetBaseName() + '.uni'
402        SpecialItemList.append(Statement)
403
404    for SortedArch in NewSectionDict:
405        NewSectionDict[SortedArch] = \
406        NewSectionDict[SortedArch] + SpecialItemList
407    Content += GenSection('Defines', NewSectionDict)
408
409    #
410    # generate [Includes] section
411    #
412    NewSectionDict = {}
413    IncludeArchList = Package.GetIncludeArchList()
414    if IncludeArchList:
415        for Path, ArchList in IncludeArchList:
416            Statement = Path
417            ArchList.sort()
418            SortedArch = ' '.join(ArchList)
419            if SortedArch in NewSectionDict:
420                NewSectionDict[SortedArch] = \
421                NewSectionDict[SortedArch] + [ConvertPath(Statement)]
422            else:
423                NewSectionDict[SortedArch] = [ConvertPath(Statement)]
424
425    Content += GenSection('Includes', NewSectionDict)
426
427    #
428    # generate [guids][protocols][ppis] sections
429    #
430    Content = GenGuidProtocolPpi(Package, Content)
431
432    #
433    # generate [LibraryClasses] section
434    #
435    NewSectionDict = {}
436    for LibraryClass in Package.GetLibraryClassList():
437        #
438        # Generate generic comment
439        #
440        HelpTextList = LibraryClass.GetHelpTextList()
441        HelpStr = _GetHelpStr(HelpTextList)
442        if HelpStr:
443            HelpStr = '@libraryclass' + HelpStr
444        CommentStr = GenGenericCommentF(HelpStr, 2, False, True)
445
446        Statement = CommentStr
447        Name = LibraryClass.GetLibraryClass()
448        IncludeHeader = LibraryClass.GetIncludeHeader()
449        Statement += Name + '|' + ConvertPath(IncludeHeader)
450        #
451        # generate tail comment
452        #
453        if LibraryClass.GetSupModuleList():
454            Statement += \
455            GenDecTailComment(LibraryClass.GetSupModuleList())
456        ArchList = sorted(LibraryClass.GetSupArchList())
457        SortedArch = ' '.join(ArchList)
458        if SortedArch in NewSectionDict:
459            NewSectionDict[SortedArch] = \
460            NewSectionDict[SortedArch] + [Statement]
461        else:
462            NewSectionDict[SortedArch] = [Statement]
463
464    Content += GenSection('LibraryClasses', NewSectionDict, True, True)
465
466    #
467    # Generate '# [Error.<TokenSpcCName>]' section
468    #
469    Content = GenPcdErrorMsgSection(Package, Content)
470
471    Content = GenPcd(Package, Content)
472
473    #
474    # generate [UserExtensions] section
475    #
476    NewSectionDict = {}
477    for UserExtension in Package.GetUserExtensionList():
478        if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID and \
479            UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER:
480            continue
481
482        # Generate Private Section first
483        if UserExtension.GetUserID() == DT.TAB_INTEL and UserExtension.GetIdentifier() == DT.TAB_PRIVATE:
484            Content += '\n' + UserExtension.GetStatement()
485            continue
486
487        Statement = UserExtension.GetStatement()
488        if not Statement:
489            continue
490        else:
491            LineList = Statement.split('\n')
492            NewStatement = ""
493            for Line in LineList:
494                NewStatement += "  %s\n" % Line
495
496        SectionList = []
497        SectionName = 'UserExtensions'
498        UserId = UserExtension.GetUserID()
499        if UserId:
500            if '.' in UserId:
501                UserId = '"' + UserId + '"'
502            SectionName += '.' + UserId
503            if UserExtension.GetIdentifier():
504                SectionName += '.' + '"' + UserExtension.GetIdentifier() + '"'
505        if not UserExtension.GetSupArchList():
506            SectionList.append(SectionName)
507        else:
508            for Arch in UserExtension.GetSupArchList():
509                SectionList.append(SectionName + '.' + Arch)
510        SectionName = ', '.join(SectionList)
511        SectionName = ''.join(['[', SectionName, ']\n'])
512        Content += '\n' + SectionName + NewStatement
513
514    SaveFileOnChange(ContainerFile, Content, False)
515    if DistHeader.ReadOnly:
516        os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH)
517    else:
518        os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH)
519    return ContainerFile
520
521## GenPackageUNIEncodeFile
522# GenPackageUNIEncodeFile, default is a UCS-2LE encode file
523#
524def GenPackageUNIEncodeFile(PackageObject, UniFileHeader = '', Encoding=TAB_ENCODING_UTF16LE):
525    GenUNIFlag = False
526    OnlyLANGUAGE_EN_X = True
527    BinaryAbstract = []
528    BinaryDescription = []
529    #
530    # If more than one language code is used for any element that would be present in the PACKAGE_UNI_FILE,
531    # then the PACKAGE_UNI_FILE must be created.
532    #
533    for (Key, Value) in PackageObject.GetAbstract() + PackageObject.GetDescription():
534        if Key == TAB_LANGUAGE_EN_X:
535            GenUNIFlag = True
536        else:
537            OnlyLANGUAGE_EN_X = False
538
539    for UserExtension in PackageObject.GetUserExtensionList():
540        if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID \
541        and UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER:
542            for (Key, Value) in UserExtension.GetBinaryAbstract():
543                if Key == TAB_LANGUAGE_EN_X:
544                    GenUNIFlag = True
545                else:
546                    OnlyLANGUAGE_EN_X = False
547                BinaryAbstract.append((Key, Value))
548
549            for (Key, Value) in UserExtension.GetBinaryDescription():
550                if Key == TAB_LANGUAGE_EN_X:
551                    GenUNIFlag = True
552                else:
553                    OnlyLANGUAGE_EN_X = False
554                BinaryDescription.append((Key, Value))
555
556    for Pcd in PackageObject.GetPcdList():
557        for TxtObj in Pcd.GetPromptList() + Pcd.GetHelpTextList():
558            if TxtObj.GetLang() == TAB_LANGUAGE_EN_X:
559                GenUNIFlag = True
560            else:
561                OnlyLANGUAGE_EN_X = False
562
563        for PcdError in Pcd.GetPcdErrorsList():
564            if PcdError.GetErrorNumber().startswith('0x') or PcdError.GetErrorNumber().startswith('0X'):
565                for (Key, Value) in PcdError.GetErrorMessageList():
566                    if Key == TAB_LANGUAGE_EN_X:
567                        GenUNIFlag = True
568                    else:
569                        OnlyLANGUAGE_EN_X = False
570    if not GenUNIFlag:
571        return
572    elif OnlyLANGUAGE_EN_X:
573        return
574    else:
575        PackageObject.UNIFlag = True
576
577    if not os.path.exists(os.path.dirname(PackageObject.GetFullPath())):
578        os.makedirs(os.path.dirname(PackageObject.GetFullPath()))
579
580    ContainerFile = GetUniFileName(os.path.dirname(PackageObject.GetFullPath()), PackageObject.GetBaseName())
581
582    Content = UniFileHeader + '\r\n'
583    Content += '\r\n'
584
585    Content += FormatUniEntry('#string ' + TAB_DEC_PACKAGE_ABSTRACT, PackageObject.GetAbstract(), ContainerFile) + '\r\n'
586
587    Content += FormatUniEntry('#string ' + TAB_DEC_PACKAGE_DESCRIPTION, PackageObject.GetDescription(), ContainerFile) \
588    + '\r\n'
589
590    Content += FormatUniEntry('#string ' + TAB_DEC_BINARY_ABSTRACT, BinaryAbstract, ContainerFile) + '\r\n'
591
592    Content += FormatUniEntry('#string ' + TAB_DEC_BINARY_DESCRIPTION, BinaryDescription, ContainerFile) + '\r\n'
593
594    PromptGenList = []
595    HelpTextGenList = []
596    for Pcd in PackageObject.GetPcdList():
597        # Generate Prompt for each Pcd
598        PcdPromptStrName = '#string ' + 'STR_' + Pcd.GetTokenSpaceGuidCName() + '_' + Pcd.GetCName() + '_PROMPT '
599        TokenValueList = []
600        for TxtObj in Pcd.GetPromptList():
601            Lang = TxtObj.GetLang()
602            PromptStr = TxtObj.GetString()
603            #
604            # Avoid generating the same PROMPT entry more than one time.
605            #
606            if (PcdPromptStrName, Lang) not in PromptGenList:
607                TokenValueList.append((Lang, PromptStr))
608                PromptGenList.append((PcdPromptStrName, Lang))
609        PromptString = FormatUniEntry(PcdPromptStrName, TokenValueList, ContainerFile) + '\r\n'
610        if PromptString not in Content:
611            Content += PromptString
612
613        # Generate Help String for each Pcd
614        PcdHelpStrName = '#string ' + 'STR_' + Pcd.GetTokenSpaceGuidCName() + '_' + Pcd.GetCName() + '_HELP '
615        TokenValueList = []
616        for TxtObj in Pcd.GetHelpTextList():
617            Lang = TxtObj.GetLang()
618            HelpStr = TxtObj.GetString()
619            #
620            # Avoid generating the same HELP entry more than one time.
621            #
622            if (PcdHelpStrName, Lang) not in HelpTextGenList:
623                TokenValueList.append((Lang, HelpStr))
624                HelpTextGenList.append((PcdHelpStrName, Lang))
625        HelpTextString = FormatUniEntry(PcdHelpStrName, TokenValueList, ContainerFile) + '\r\n'
626        if HelpTextString not in Content:
627            Content += HelpTextString
628
629        # Generate PcdError for each Pcd if ErrorNo exist.
630        for PcdError in Pcd.GetPcdErrorsList():
631            ErrorNo = PcdError.GetErrorNumber()
632            if ErrorNo.startswith(TAB_HEX_START) or ErrorNo.startswith(TAB_CAPHEX_START):
633                PcdErrStrName = '#string ' + TAB_STR_TOKENCNAME + TAB_UNDERLINE_SPLIT + Pcd.GetTokenSpaceGuidCName() \
634                    + TAB_UNDERLINE_SPLIT + TAB_STR_TOKENERR \
635                    + TAB_UNDERLINE_SPLIT + ErrorNo[2:]
636                PcdErrString = FormatUniEntry(PcdErrStrName, PcdError.GetErrorMessageList(), ContainerFile) + '\r\n'
637                if PcdErrString not in Content:
638                    Content += PcdErrString
639
640    File = codecs.open(ContainerFile, 'w', Encoding)
641    File.write(u'\uFEFF' + Content)
642    File.stream.close()
643    Md5Signature = md5(__FileHookOpen__(str(ContainerFile), 'rb').read())
644    Md5Sum = Md5Signature.hexdigest()
645    if (ContainerFile, Md5Sum) not in PackageObject.FileList:
646        PackageObject.FileList.append((ContainerFile, Md5Sum))
647
648    return ContainerFile
649
650## GenPcdErrComment
651#
652#  @param PcdErrObject:  PcdErrorObject
653#
654#  @retval CommentStr:   Generated comment lines, with prefix "#"
655#
656def GenPcdErrComment (PcdErrObject):
657    CommentStr = ''
658    ErrorCode = PcdErrObject.GetErrorNumber()
659    ValidValueRange = PcdErrObject.GetValidValueRange()
660    if ValidValueRange:
661        CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_VALIDRANGE + TAB_SPACE_SPLIT
662        if ErrorCode:
663            CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT
664        CommentStr += ValidValueRange + END_OF_LINE
665
666    ValidValue = PcdErrObject.GetValidValue()
667    if ValidValue:
668        ValidValueList = \
669        [Value for Value in ValidValue.split(TAB_SPACE_SPLIT) if Value]
670        CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_VALIDLIST + TAB_SPACE_SPLIT
671        if ErrorCode:
672            CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT
673        CommentStr += TAB_COMMA_SPLIT.join(ValidValueList) + END_OF_LINE
674
675    Expression = PcdErrObject.GetExpression()
676    if Expression:
677        CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_EXPRESSION + TAB_SPACE_SPLIT
678        if ErrorCode:
679            CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT
680        CommentStr += Expression + END_OF_LINE
681
682    return CommentStr
683
684