Home | History | Annotate | Download | only in GenMetaFile
      1 ## @file GenDecFile.py

      2 #

      3 # This file contained the logical of transfer package object to DEC files.

      4 #

      5 # Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>

      6 #

      7 # This program and the accompanying materials are licensed and made available 

      8 # under the terms and conditions of the BSD License which accompanies this 

      9 # distribution. The full text of the license may be found at 

     10 # http://opensource.org/licenses/bsd-license.php

     11 #

     12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

     13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

     14 #

     15 
     16 '''
     17 GenDEC
     18 '''
     19 import os
     20 import stat
     21 import codecs
     22 import md5
     23 from Core.FileHook import __FileHookOpen__
     24 from Library.Parsing import GenSection
     25 from Library.CommentGenerating import GenHeaderCommentSection
     26 from Library.CommentGenerating import GenGenericCommentF
     27 from Library.CommentGenerating import GenDecTailComment
     28 from Library.CommentGenerating import _GetHelpStr
     29 from Library.Misc import GuidStringToGuidStructureString
     30 from Library.Misc import SaveFileOnChange
     31 from Library.Misc import ConvertPath
     32 from Library.Misc import GetLocalValue
     33 from Library.DataType import TAB_SPACE_SPLIT
     34 from Library.DataType import TAB_COMMA_SPLIT
     35 from Library.DataType import END_OF_LINE
     36 from Library.DataType import TAB_ARCH_COMMON
     37 from Library.DataType import TAB_VALUE_SPLIT
     38 from Library.DataType import TAB_COMMENT_SPLIT
     39 from Library.DataType import TAB_PCD_VALIDRANGE
     40 from Library.DataType import TAB_PCD_VALIDLIST
     41 from Library.DataType import TAB_PCD_EXPRESSION
     42 from Library.DataType import TAB_DEC_DEFINES_DEC_SPECIFICATION
     43 from Library.DataType import TAB_DEC_DEFINES_PACKAGE_NAME
     44 from Library.DataType import TAB_DEC_DEFINES_PACKAGE_GUID
     45 from Library.DataType import TAB_DEC_DEFINES_PACKAGE_VERSION
     46 from Library.DataType import TAB_DEC_DEFINES_PKG_UNI_FILE
     47 from Library.DataType import TAB_DEC_PACKAGE_ABSTRACT
     48 from Library.DataType import TAB_DEC_PACKAGE_DESCRIPTION
     49 from Library.DataType import TAB_DEC_BINARY_ABSTRACT
     50 from Library.DataType import TAB_DEC_BINARY_DESCRIPTION
     51 from Library.DataType import TAB_LANGUAGE_EN_X
     52 from Library.DataType import TAB_BINARY_HEADER_USERID
     53 from Library.DataType import TAB_BINARY_HEADER_IDENTIFIER
     54 from Library.DataType import TAB_COMMENT_EDK1_SPLIT
     55 from Library.DataType import TAB_ENCODING_UTF16LE
     56 from Library.DataType import TAB_CAPHEX_START
     57 from Library.DataType import TAB_HEX_START
     58 from Library.DataType import TAB_UNDERLINE_SPLIT
     59 from Library.DataType import TAB_STR_TOKENERR
     60 from Library.DataType import TAB_STR_TOKENCNAME
     61 from Library.DataType import TAB_PCD_ERROR_SECTION_COMMENT
     62 from Library.DataType import TAB_PCD_ERROR
     63 from Library.DataType import TAB_SECTION_START
     64 from Library.DataType import TAB_SECTION_END
     65 from Library.DataType import TAB_SPLIT
     66 from Library.UniClassObject import FormatUniEntry
     67 
     68 def GenPcd(Package, Content):
     69     #

     70     # generate [Pcd] section

     71     # <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>    

     72     #

     73     ValidUsageDict = {}
     74     for Pcd in Package.GetPcdList():
     75         #

     76         # Generate generic comment

     77         #

     78         HelpTextList = Pcd.GetHelpTextList()
     79         HelpStr = _GetHelpStr(HelpTextList)
     80         CommentStr = GenGenericCommentF(HelpStr, 2)
     81         
     82         PromptList = Pcd.GetPromptList()
     83         PromptStr = _GetHelpStr(PromptList)
     84         CommentStr += GenGenericCommentF(PromptStr.strip(), 1, True)
     85         
     86         PcdErrList = Pcd.GetPcdErrorsList()
     87         for PcdErr in PcdErrList:
     88             CommentStr += GenPcdErrComment(PcdErr)
     89         Statement = CommentStr
     90  
     91         CName = Pcd.GetCName()
     92         TokenSpaceGuidCName = Pcd.GetTokenSpaceGuidCName()
     93         DefaultValue = Pcd.GetDefaultValue()
     94         DatumType = Pcd.GetDatumType()
     95         Token = Pcd.GetToken()
     96         ValidUsage = Pcd.GetValidUsage()
     97 
     98         if ValidUsage == 'FeaturePcd':
     99             ValidUsage = 'PcdsFeatureFlag'
    100         elif ValidUsage == 'PatchPcd':
    101             ValidUsage = 'PcdsPatchableInModule'
    102         elif ValidUsage == 'FixedPcd':
    103             ValidUsage = 'PcdsFixedAtBuild'
    104         elif ValidUsage == 'Pcd':
    105             ValidUsage = 'PcdsDynamic'
    106         elif ValidUsage == 'PcdEx':
    107             ValidUsage = 'PcdsDynamicEx'
    108                                 
    109         if ValidUsage in ValidUsageDict:
    110             NewSectionDict = ValidUsageDict[ValidUsage]
    111         else:
    112             NewSectionDict = {}
    113             ValidUsageDict[ValidUsage] = NewSectionDict
    114         Statement += TokenSpaceGuidCName + '.' + CName
    115         Statement += '|' + DefaultValue
    116         Statement += '|' + DatumType
    117         Statement += '|' + Token
    118         #

    119         # generate tail comment

    120         #

    121         if Pcd.GetSupModuleList():
    122             Statement += GenDecTailComment(Pcd.GetSupModuleList())
    123 
    124         ArchList = Pcd.GetSupArchList()
    125         ArchList.sort()
    126         SortedArch = ' '.join(ArchList)
    127         if SortedArch in NewSectionDict:
    128             NewSectionDict[SortedArch] = \
    129             NewSectionDict[SortedArch] + [Statement]
    130         else:
    131             NewSectionDict[SortedArch] = [Statement]            
    132         
    133     for ValidUsage in ValidUsageDict:
    134         Content += GenSection(ValidUsage, ValidUsageDict[ValidUsage], True, True)
    135     
    136     return Content
    137 
    138 def GenPcdErrorMsgSection(Package, Content):
    139     if not Package.PcdErrorCommentDict:
    140         return Content
    141     
    142     #

    143     # Generate '# [Error.<TokenSpcCName>]' section

    144     #

    145     Content += END_OF_LINE + END_OF_LINE
    146     SectionComment = TAB_COMMENT_SPLIT + END_OF_LINE
    147     SectionComment += TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_ERROR_SECTION_COMMENT + END_OF_LINE
    148     SectionComment += TAB_COMMENT_SPLIT + END_OF_LINE
    149     TokenSpcCNameList = []
    150     
    151     #

    152     # Get TokenSpcCName list in PcdErrorCommentDict in Package object

    153     #

    154     for (TokenSpcCName, ErrorNumber) in Package.PcdErrorCommentDict:
    155         if TokenSpcCName not in TokenSpcCNameList:
    156             TokenSpcCNameList.append(TokenSpcCName)
    157     
    158     for TokenSpcCNameItem in TokenSpcCNameList:
    159         SectionName = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_SECTION_START + TAB_PCD_ERROR + \
    160                       TAB_SPLIT + TokenSpcCNameItem + TAB_SECTION_END + END_OF_LINE
    161         Content += SectionComment
    162         Content += SectionName
    163         for (TokenSpcCName, ErrorNumber) in Package.PcdErrorCommentDict:
    164             if TokenSpcCNameItem == TokenSpcCName:
    165                 PcdErrorMsg = GetLocalValue(Package.PcdErrorCommentDict[(TokenSpcCName, ErrorNumber)])
    166                 SectionItem = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_SPACE_SPLIT + \
    167                               ErrorNumber + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT + \
    168                               PcdErrorMsg + END_OF_LINE
    169                 Content += SectionItem
    170                 
    171     Content += TAB_COMMENT_SPLIT
    172     return Content
    173             
    174 def GenGuidProtocolPpi(Package, Content):
    175     #

    176     # generate [Guids] section

    177     #

    178     NewSectionDict = {}
    179 
    180     LeftOffset = 46
    181     # Get the line offset need

    182     # If the real one < the min one, use the min one

    183     # else use the real one

    184     for Guid in Package.GetGuidList():
    185         if len(Guid.GetCName()) > LeftOffset:
    186             LeftOffset = len(Guid.GetCName())
    187 
    188     # Generate

    189     for Guid in Package.GetGuidList():
    190         #

    191         # Generate generic comment

    192         #

    193         HelpTextList = Guid.GetHelpTextList()
    194         HelpStr = _GetHelpStr(HelpTextList)
    195         CommentStr = GenGenericCommentF(HelpStr, 2)
    196 
    197         Statement = CommentStr
    198         CName = Guid.GetCName()
    199         Value = GuidStringToGuidStructureString(Guid.GetGuid())
    200         Statement += CName.ljust(LeftOffset) + ' = ' + Value
    201         #

    202         # generate tail comment

    203         #

    204         if Guid.GetSupModuleList():
    205             Statement += GenDecTailComment(Guid.GetSupModuleList())     
    206         ArchList = Guid.GetSupArchList()
    207         ArchList.sort()
    208         SortedArch = ' '.join(ArchList)
    209         if SortedArch in NewSectionDict:
    210             NewSectionDict[SortedArch] = \
    211             NewSectionDict[SortedArch] + [Statement]
    212         else:
    213             NewSectionDict[SortedArch] = [Statement]            
    214 
    215     Content += GenSection('Guids', NewSectionDict, True, True)
    216  
    217     #

    218     # generate [Protocols] section

    219     #

    220     NewSectionDict = {}
    221     LeftOffset = 46
    222     # Get the line offset need

    223     # If the real one < the min one, use the min one

    224     # else use the real one

    225     for Protocol in Package.GetProtocolList():
    226         if len(Protocol.GetCName()) > LeftOffset:
    227             LeftOffset = len(Protocol.GetCName())
    228 
    229     for Protocol in Package.GetProtocolList():
    230         #

    231         # Generate generic comment

    232         #

    233         HelpTextList = Protocol.GetHelpTextList()
    234         HelpStr = _GetHelpStr(HelpTextList)
    235         CommentStr = GenGenericCommentF(HelpStr, 2)        
    236 
    237         Statement = CommentStr        
    238         CName = Protocol.GetCName()
    239         Value = GuidStringToGuidStructureString(Protocol.GetGuid())
    240         Statement += CName.ljust(LeftOffset) + ' = ' + Value
    241 
    242         #

    243         # generate tail comment

    244         #

    245         if Protocol.GetSupModuleList():
    246             Statement += GenDecTailComment(Protocol.GetSupModuleList())
    247         ArchList = Protocol.GetSupArchList()
    248         ArchList.sort()
    249         SortedArch = ' '.join(ArchList)
    250         if SortedArch in NewSectionDict:
    251             NewSectionDict[SortedArch] = \
    252             NewSectionDict[SortedArch] + [Statement]
    253         else:
    254             NewSectionDict[SortedArch] = [Statement]            
    255 
    256     Content += GenSection('Protocols', NewSectionDict, True, True) 
    257 
    258     #

    259     # generate [Ppis] section

    260     #

    261     NewSectionDict = {}
    262     LeftOffset = 46
    263     # Get the line offset need

    264     # If the real one < the min one, use the min one

    265     # else use the real one

    266     for Ppi in Package.GetPpiList():
    267         if len(Ppi.GetCName()) > LeftOffset:
    268             LeftOffset = len(Ppi.GetCName())
    269 
    270     for Ppi in Package.GetPpiList():
    271         #

    272         # Generate generic comment

    273         #

    274         HelpTextList = Ppi.GetHelpTextList()
    275         HelpStr = _GetHelpStr(HelpTextList)
    276         CommentStr = GenGenericCommentF(HelpStr, 2)
    277 
    278         Statement = CommentStr
    279         CName = Ppi.GetCName()
    280         Value = GuidStringToGuidStructureString(Ppi.GetGuid())
    281         Statement += CName.ljust(LeftOffset) + ' = ' + Value
    282 
    283         #

    284         # generate tail comment

    285         #

    286         if Ppi.GetSupModuleList():
    287             Statement += GenDecTailComment(Ppi.GetSupModuleList())
    288         ArchList = Ppi.GetSupArchList()
    289         ArchList.sort()
    290         SortedArch = ' '.join(ArchList)
    291         if SortedArch in NewSectionDict:
    292             NewSectionDict[SortedArch] = \
    293             NewSectionDict[SortedArch] + [Statement]
    294         else:
    295             NewSectionDict[SortedArch] = [Statement]            
    296 
    297     Content += GenSection('Ppis', NewSectionDict, True, True)
    298     
    299     return Content
    300 
    301 ## Transfer Package Object to Dec files

    302 #

    303 # Transfer all contents of a standard Package Object to a Dec file 

    304 #

    305 # @param Package:  A Package 

    306 #

    307 def PackageToDec(Package, DistHeader = None):
    308     #

    309     # Init global information for the file

    310     #

    311     ContainerFile = Package.GetFullPath()
    312     
    313     Content = ''
    314     
    315     #

    316     # Generate file header 

    317     #

    318     PackageAbstract = GetLocalValue(Package.GetAbstract())
    319     PackageDescription = GetLocalValue(Package.GetDescription())
    320     PackageCopyright = ''
    321     PackageLicense = ''
    322     for (Lang, Copyright) in Package.GetCopyright():
    323         if Lang:
    324             pass
    325         PackageCopyright = Copyright
    326     for (Lang, License) in Package.GetLicense():
    327         if Lang:
    328             pass
    329         PackageLicense = License
    330     if not PackageAbstract and DistHeader:
    331         PackageAbstract = GetLocalValue(DistHeader.GetAbstract())
    332     if not PackageDescription and DistHeader:
    333         PackageDescription = GetLocalValue(DistHeader.GetDescription())
    334     if not PackageCopyright and DistHeader:
    335         for (Lang, Copyright) in DistHeader.GetCopyright():
    336             PackageCopyright = Copyright
    337     if not PackageLicense and DistHeader:
    338         for (Lang, License) in DistHeader.GetLicense():
    339             PackageLicense = License
    340          
    341     #

    342     # Generate header comment section of DEC file

    343     #

    344     Content += GenHeaderCommentSection(PackageAbstract, \
    345                                        PackageDescription, \
    346                                        PackageCopyright, \
    347                                        PackageLicense).replace('\r\n', '\n')
    348 
    349     #

    350     # Generate Binary header 

    351     #

    352     for UserExtension in Package.GetUserExtensionList():
    353         if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID \
    354         and UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER:
    355             PackageBinaryAbstract = GetLocalValue(UserExtension.GetBinaryAbstract())
    356             PackageBinaryDescription = GetLocalValue(UserExtension.GetBinaryDescription())
    357             PackageBinaryCopyright = ''
    358             PackageBinaryLicense = ''
    359             for (Lang, Copyright) in UserExtension.GetBinaryCopyright():
    360                 PackageBinaryCopyright = Copyright
    361             for (Lang, License) in UserExtension.GetBinaryLicense():
    362                 PackageBinaryLicense = License 
    363             if PackageBinaryAbstract and PackageBinaryDescription and \
    364             PackageBinaryCopyright and PackageBinaryLicense:
    365                 Content += GenHeaderCommentSection(PackageBinaryAbstract, 
    366                                            PackageBinaryDescription, 
    367                                            PackageBinaryCopyright, 
    368                                            PackageBinaryLicense,
    369                                            True)
    370 
    371     #

    372     # Generate PACKAGE_UNI_FILE for the Package

    373     #

    374     FileHeader = GenHeaderCommentSection(PackageAbstract, PackageDescription, PackageCopyright, PackageLicense, False, \
    375                                          TAB_COMMENT_EDK1_SPLIT)
    376     GenPackageUNIEncodeFile(Package, FileHeader)
    377 
    378     #

    379     # for each section, maintain a dict, sorted arch will be its key, 

    380     #statement list will be its data

    381     # { 'Arch1 Arch2 Arch3': [statement1, statement2],

    382     #   'Arch1' : [statement1, statement3] 

    383     #  }

    384     #

    385     
    386     #

    387     # generate [Defines] section                     

    388     #

    389     LeftOffset = 31
    390     NewSectionDict = {TAB_ARCH_COMMON : []}
    391     SpecialItemList = []
    392     
    393     Statement = (u'%s ' % TAB_DEC_DEFINES_DEC_SPECIFICATION).ljust(LeftOffset) + u'= %s' % '0x00010017'
    394     SpecialItemList.append(Statement)
    395     
    396     BaseName = Package.GetBaseName()
    397     if BaseName.startswith('.') or BaseName.startswith('-'):
    398         BaseName = '_' + BaseName
    399     Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_NAME).ljust(LeftOffset) + u'= %s' % BaseName
    400     SpecialItemList.append(Statement)
    401 
    402     Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_VERSION).ljust(LeftOffset) + u'= %s' % Package.GetVersion()
    403     SpecialItemList.append(Statement)
    404 
    405     Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_GUID).ljust(LeftOffset) + u'= %s' % Package.GetGuid()
    406     SpecialItemList.append(Statement)
    407 
    408     if Package.UNIFlag:
    409         Statement = (u'%s ' % TAB_DEC_DEFINES_PKG_UNI_FILE).ljust(LeftOffset) + u'= %s' % Package.GetBaseName() + '.uni'
    410         SpecialItemList.append(Statement)               
    411 
    412     for SortedArch in NewSectionDict:
    413         NewSectionDict[SortedArch] = \
    414         NewSectionDict[SortedArch] + SpecialItemList
    415     Content += GenSection('Defines', NewSectionDict)
    416 
    417     #

    418     # generate [Includes] section

    419     #

    420     NewSectionDict = {}
    421     IncludeArchList = Package.GetIncludeArchList()
    422     if IncludeArchList:            
    423         for Path, ArchList in IncludeArchList:
    424             Statement = Path
    425             ArchList.sort()
    426             SortedArch = ' '.join(ArchList)
    427             if SortedArch in NewSectionDict:
    428                 NewSectionDict[SortedArch] = \
    429                 NewSectionDict[SortedArch] + [ConvertPath(Statement)]
    430             else:
    431                 NewSectionDict[SortedArch] = [ConvertPath(Statement)]
    432 
    433     Content += GenSection('Includes', NewSectionDict)
    434 
    435     #

    436     # generate [guids][protocols][ppis] sections

    437     #

    438     Content = GenGuidProtocolPpi(Package, Content)
    439 
    440     #

    441     # generate [LibraryClasses] section

    442     #

    443     NewSectionDict = {}
    444     for LibraryClass in Package.GetLibraryClassList():
    445         #

    446         # Generate generic comment

    447         #

    448         HelpTextList = LibraryClass.GetHelpTextList()
    449         HelpStr = _GetHelpStr(HelpTextList)
    450         if HelpStr:
    451             HelpStr = '@libraryclass' + HelpStr
    452         CommentStr = GenGenericCommentF(HelpStr, 2, False, True)
    453 
    454         Statement = CommentStr
    455         Name = LibraryClass.GetLibraryClass()
    456         IncludeHeader = LibraryClass.GetIncludeHeader()
    457         Statement += Name + '|' + ConvertPath(IncludeHeader)
    458         #

    459         # generate tail comment

    460         #

    461         if LibraryClass.GetSupModuleList():
    462             Statement += \
    463             GenDecTailComment(LibraryClass.GetSupModuleList())
    464         ArchList = LibraryClass.GetSupArchList()
    465         ArchList.sort()
    466         SortedArch = ' '.join(ArchList)
    467         if SortedArch in NewSectionDict:
    468             NewSectionDict[SortedArch] = \
    469             NewSectionDict[SortedArch] + [Statement]
    470         else:
    471             NewSectionDict[SortedArch] = [Statement]            
    472 
    473     Content += GenSection('LibraryClasses', NewSectionDict, True, True)
    474 
    475     #

    476     # Generate '# [Error.<TokenSpcCName>]' section

    477     #

    478     Content = GenPcdErrorMsgSection(Package, Content)
    479     
    480     Content = GenPcd(Package, Content)
    481 
    482     #

    483     # generate [UserExtensions] section

    484     #

    485     NewSectionDict = {}
    486     for UserExtension in Package.GetUserExtensionList():
    487         if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID and \
    488             UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER:
    489             continue
    490         Statement = UserExtension.GetStatement()
    491         if not Statement:
    492             continue
    493         else:
    494             LineList = Statement.split('\n')
    495             NewStatement = ""
    496             for Line in LineList:
    497                 NewStatement += "  %s\n" % Line
    498         
    499         SectionList = []
    500         SectionName = 'UserExtensions'
    501         UserId = UserExtension.GetUserID()
    502         if UserId:
    503             if '.' in UserId:
    504                 UserId = '"' + UserId + '"'
    505             SectionName += '.' + UserId
    506             if UserExtension.GetIdentifier():
    507                 SectionName += '.' + '"' + UserExtension.GetIdentifier() + '"'
    508         if not UserExtension.GetSupArchList():
    509             SectionList.append(SectionName)
    510         else:
    511             for Arch in UserExtension.GetSupArchList():
    512                 SectionList.append(SectionName + '.' + Arch)
    513         SectionName = ', '.join(SectionList)
    514         SectionName = ''.join(['[', SectionName, ']\n'])
    515         Content += '\n' + SectionName + NewStatement
    516 
    517     SaveFileOnChange(ContainerFile, Content, False)
    518     if DistHeader.ReadOnly:
    519         os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH)
    520     else:
    521         os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH)
    522     return ContainerFile
    523 
    524 ## GenPackageUNIEncodeFile

    525 # GenPackageUNIEncodeFile, default is a UCS-2LE encode file

    526 #

    527 def GenPackageUNIEncodeFile(PackageObject, UniFileHeader = '', Encoding=TAB_ENCODING_UTF16LE):
    528     GenUNIFlag = False
    529     OnlyLANGUAGE_EN_X = True
    530     BinaryAbstract = []
    531     BinaryDescription = []
    532     #

    533     # If more than one language code is used for any element that would be present in the PACKAGE_UNI_FILE, 

    534     # then the PACKAGE_UNI_FILE must be created.

    535     #

    536     for (Key, Value) in PackageObject.GetAbstract() + PackageObject.GetDescription():
    537         if Key == TAB_LANGUAGE_EN_X:
    538             GenUNIFlag = True
    539         else:
    540             OnlyLANGUAGE_EN_X = False
    541             
    542     for UserExtension in PackageObject.GetUserExtensionList():
    543         if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID \
    544         and UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER:
    545             for (Key, Value) in UserExtension.GetBinaryAbstract():
    546                 if Key == TAB_LANGUAGE_EN_X:
    547                     GenUNIFlag = True
    548                 else:
    549                     OnlyLANGUAGE_EN_X = False
    550                 BinaryAbstract.append((Key, Value))
    551 
    552             for (Key, Value) in UserExtension.GetBinaryDescription():
    553                 if Key == TAB_LANGUAGE_EN_X:
    554                     GenUNIFlag = True
    555                 else:
    556                     OnlyLANGUAGE_EN_X = False
    557                 BinaryDescription.append((Key, Value))
    558 
    559     for Pcd in PackageObject.GetPcdList():
    560         for TxtObj in Pcd.GetPromptList() + Pcd.GetHelpTextList():
    561             if TxtObj.GetLang() == TAB_LANGUAGE_EN_X:
    562                 GenUNIFlag = True
    563             else:
    564                 OnlyLANGUAGE_EN_X = False
    565                 
    566         for PcdError in Pcd.GetPcdErrorsList():
    567             if PcdError.GetErrorNumber().startswith('0x') or PcdError.GetErrorNumber().startswith('0X'):
    568                 for (Key, Value) in PcdError.GetErrorMessageList():
    569                     if Key == TAB_LANGUAGE_EN_X:
    570                         GenUNIFlag = True
    571                     else:
    572                         OnlyLANGUAGE_EN_X = False
    573     if not GenUNIFlag:
    574         return
    575     elif OnlyLANGUAGE_EN_X:
    576         return
    577     else:
    578         PackageObject.UNIFlag = True
    579         
    580     if not os.path.exists(os.path.dirname(PackageObject.GetFullPath())):
    581         os.makedirs(os.path.dirname(PackageObject.GetFullPath()))
    582     ContainerFile = os.path.normpath(os.path.join(os.path.dirname(PackageObject.GetFullPath()), 
    583                                                   (PackageObject.GetBaseName() + '.uni')))
    584     
    585     Content = UniFileHeader + '\r\n'
    586     Content += '\r\n'
    587     
    588     Content += FormatUniEntry('#string ' + TAB_DEC_PACKAGE_ABSTRACT, PackageObject.GetAbstract(), ContainerFile) + '\r\n'
    589         
    590     Content += FormatUniEntry('#string ' + TAB_DEC_PACKAGE_DESCRIPTION, PackageObject.GetDescription(), ContainerFile) \
    591     + '\r\n'
    592     
    593     Content += FormatUniEntry('#string ' + TAB_DEC_BINARY_ABSTRACT, BinaryAbstract, ContainerFile) + '\r\n'
    594     
    595     Content += FormatUniEntry('#string ' + TAB_DEC_BINARY_DESCRIPTION, BinaryDescription, ContainerFile) + '\r\n'
    596     
    597     PromptGenList = []
    598     HelpTextGenList = []    
    599     for Pcd in PackageObject.GetPcdList():
    600         # Generate Prompt for each Pcd

    601         PcdPromptStrName = '#string ' + 'STR_' + Pcd.GetTokenSpaceGuidCName() + '_' + Pcd.GetCName() + '_PROMPT '
    602         TokenValueList = []
    603         for TxtObj in Pcd.GetPromptList():
    604             Lang = TxtObj.GetLang()
    605             PromptStr = TxtObj.GetString()
    606             #

    607             # Avoid generating the same PROMPT entry more than one time. 

    608             #

    609             if (PcdPromptStrName, Lang) not in PromptGenList:
    610                 TokenValueList.append((Lang, PromptStr))
    611                 PromptGenList.append((PcdPromptStrName, Lang))
    612         PromptString = FormatUniEntry(PcdPromptStrName, TokenValueList, ContainerFile) + '\r\n'
    613         if PromptString not in Content:
    614             Content += PromptString
    615             
    616         # Generate Help String for each Pcd

    617         PcdHelpStrName = '#string ' + 'STR_' + Pcd.GetTokenSpaceGuidCName() + '_' + Pcd.GetCName() + '_HELP '
    618         TokenValueList = []
    619         for TxtObj in Pcd.GetHelpTextList():
    620             Lang = TxtObj.GetLang()
    621             HelpStr = TxtObj.GetString()
    622             #

    623             # Avoid generating the same HELP entry more than one time. 

    624             #

    625             if (PcdHelpStrName, Lang) not in HelpTextGenList:
    626                 TokenValueList.append((Lang, HelpStr))
    627                 HelpTextGenList.append((PcdHelpStrName, Lang))
    628         HelpTextString = FormatUniEntry(PcdHelpStrName, TokenValueList, ContainerFile) + '\r\n'
    629         if HelpTextString not in Content:
    630             Content += HelpTextString
    631             
    632         # Generate PcdError for each Pcd if ErrorNo exist.

    633         for PcdError in Pcd.GetPcdErrorsList():
    634             ErrorNo = PcdError.GetErrorNumber()
    635             if ErrorNo.startswith(TAB_HEX_START) or ErrorNo.startswith(TAB_CAPHEX_START):
    636                 PcdErrStrName = '#string ' + TAB_STR_TOKENCNAME + TAB_UNDERLINE_SPLIT + Pcd.GetTokenSpaceGuidCName() \
    637                     + TAB_UNDERLINE_SPLIT + TAB_STR_TOKENERR \
    638                     + TAB_UNDERLINE_SPLIT + ErrorNo[2:]
    639                 PcdErrString = FormatUniEntry(PcdErrStrName, PcdError.GetErrorMessageList(), ContainerFile) + '\r\n'
    640                 if PcdErrString not in Content:
    641                     Content += PcdErrString
    642                     
    643     File = codecs.open(ContainerFile, 'w', Encoding)
    644     File.write(u'\uFEFF' + Content)
    645     File.stream.close()
    646     Md5Sigature = md5.new(__FileHookOpen__(str(ContainerFile), 'rb').read())
    647     Md5Sum = Md5Sigature.hexdigest()
    648     if (ContainerFile, Md5Sum) not in PackageObject.FileList:
    649         PackageObject.FileList.append((ContainerFile, Md5Sum))
    650 
    651     return ContainerFile
    652     
    653 ## GenPcdErrComment

    654 #

    655 #  @param PcdErrObject:  PcdErrorObject

    656 #  

    657 #  @retval CommentStr:   Generated comment lines, with prefix "#"

    658 # 

    659 def GenPcdErrComment (PcdErrObject):
    660     CommentStr = '' 
    661     ErrorCode = PcdErrObject.GetErrorNumber()
    662     ValidValueRange = PcdErrObject.GetValidValueRange()
    663     if ValidValueRange:
    664         CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_VALIDRANGE + TAB_SPACE_SPLIT 
    665         if ErrorCode:
    666             CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT
    667         CommentStr += ValidValueRange + END_OF_LINE
    668     
    669     ValidValue = PcdErrObject.GetValidValue()
    670     if ValidValue:
    671         ValidValueList = \
    672         [Value for Value in ValidValue.split(TAB_SPACE_SPLIT) if Value]
    673         CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_VALIDLIST + TAB_SPACE_SPLIT
    674         if ErrorCode:
    675             CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT
    676         CommentStr += TAB_COMMA_SPLIT.join(ValidValueList) + END_OF_LINE
    677         
    678     Expression = PcdErrObject.GetExpression()
    679     if Expression:
    680         CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_EXPRESSION + TAB_SPACE_SPLIT
    681         if ErrorCode:
    682             CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT
    683         CommentStr += Expression + END_OF_LINE
    684         
    685     return CommentStr
    686 
    687