1## @file
2# This file is used to parse a xml file of .PKG file
3#
4# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
5#
6# This program and the accompanying materials are licensed and made available
7# under the terms and conditions of the BSD License which accompanies this
8# distribution. The full text of the license may be found at
9# http://opensource.org/licenses/bsd-license.php
10#
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13#
14
15'''
16XmlParser
17'''
18
19##
20# Import Modules
21#
22import re
23
24from Library.Xml.XmlRoutines import XmlNode
25from Library.Xml.XmlRoutines import CreateXmlElement
26from Library.Xml.XmlRoutines import XmlList
27from Library.Xml.XmlRoutines import XmlParseFile
28from Core.DistributionPackageClass import DistributionPackageClass
29from Object.POM.ModuleObject import DepexObject
30from Library.ParserValidate import IsValidInfMoudleType
31from Library.ParserValidate import IsValidInstallPath
32from Library.Misc import IsEqualList
33from Library.Misc import Sdict
34
35from Logger.StringTable import ERR_XML_INVALID_VARIABLENAME
36from Logger.StringTable import ERR_XML_INVALID_LIB_SUPMODLIST
37from Logger.StringTable import ERR_XML_INVALID_EXTERN_SUPARCHLIST
38from Logger.StringTable import ERR_XML_INVALID_EXTERN_SUPMODLIST
39from Logger.StringTable import ERR_XML_INVALID_EXTERN_SUPMODLIST_NOT_LIB
40from Logger.StringTable import ERR_FILE_NAME_INVALIDE
41from Logger.ToolError import PARSER_ERROR
42from Logger.ToolError import FORMAT_INVALID
43
44from Xml.CommonXml import DistributionPackageHeaderXml
45from Xml.CommonXml import MiscellaneousFileXml
46from Xml.CommonXml import UserExtensionsXml
47from Xml.XmlParserMisc import ConvertVariableName
48from Xml.XmlParserMisc import IsRequiredItemListNull
49from Xml.ModuleSurfaceAreaXml import ModuleSurfaceAreaXml
50from Xml.PackageSurfaceAreaXml import PackageSurfaceAreaXml
51
52import Logger.Log as Logger
53
54##
55# DistributionPackageXml
56#
57class DistributionPackageXml(object):
58    def __init__(self):
59        self.DistP = DistributionPackageClass()
60        self.Pkg = ''
61
62    ## ValidateDistributionPackage
63    #
64    # Check if any required item is missing in DistributionPackage
65    #
66    def ValidateDistributionPackage(self):
67        XmlTreeLevel = ['DistributionPackage']
68        if self.DistP:
69            #
70            # Check DistributionPackage -> DistributionHeader
71            #
72            XmlTreeLevel = ['DistributionPackage', '']
73            CheckDict = {'DistributionHeader':self.DistP.Header }
74            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
75
76            if self.DistP.Header:
77                DpHeader = self.DistP.Header
78                XmlTreeLevel = ['DistributionPackage', 'DistributionHeader']
79                CheckDict = Sdict()
80                if DpHeader.GetAbstract():
81                    DPAbstract = DpHeader.GetAbstract()[0][1]
82                else:
83                    DPAbstract = ''
84                if DpHeader.GetCopyright():
85                    DPCopyright = DpHeader.GetCopyright()[0][1]
86                else:
87                    DPCopyright = ''
88                if DpHeader.GetLicense():
89                    DPLicense = DpHeader.GetLicense()[0][1]
90                else:
91                    DPLicense = ''
92
93                CheckDict['Name'] = DpHeader.GetName()
94                CheckDict['GUID'] = DpHeader.GetGuid()
95                CheckDict['Version'] = DpHeader.GetVersion()
96                CheckDict['Copyright'] = DPCopyright
97                CheckDict['License'] = DPLicense
98                CheckDict['Abstract'] = DPAbstract
99                CheckDict['Vendor'] = DpHeader.GetVendor()
100                CheckDict['Date'] = DpHeader.GetDate()
101                CheckDict['XmlSpecification'] = DpHeader.GetXmlSpecification()
102
103                IsRequiredItemListNull(CheckDict, XmlTreeLevel)
104            else:
105                XmlTreeLevel = ['DistributionPackage', 'DistributionHeader']
106                CheckDict = CheckDict = {'DistributionHeader':'', }
107                IsRequiredItemListNull(CheckDict, XmlTreeLevel)
108
109            #
110            # Check Each Package
111            #
112            for Key in self.DistP.PackageSurfaceArea:
113                ValidatePackageSurfaceArea(self.DistP.PackageSurfaceArea[Key])
114
115            #
116            # Check Each Module
117            #
118            for Key in self.DistP.ModuleSurfaceArea:
119                ValidateMS(self.DistP.ModuleSurfaceArea[Key], ['DistributionPackage', 'ModuleSurfaceArea'])
120
121            #
122            # Check Each Tool
123            #
124            if self.DistP.Tools:
125                XmlTreeLevel = ['DistributionPackage', 'Tools', 'Header']
126                CheckDict = {'Name':self.DistP.Tools.GetName(), }
127                IsRequiredItemListNull(CheckDict, XmlTreeLevel)
128
129                if not self.DistP.Tools.GetFileList():
130                    XmlTreeLevel = ['DistributionPackage', 'Tools']
131                    CheckDict = {'FileName':None, }
132                    IsRequiredItemListNull(CheckDict, XmlTreeLevel)
133                for Item in self.DistP.Tools.GetFileList():
134                    XmlTreeLevel = ['DistributionPackage', 'Tools']
135                    CheckDict = {'FileName':Item.GetURI(), }
136                    IsRequiredItemListNull(CheckDict, XmlTreeLevel)
137
138            #
139            # Check Each Misc File
140            #
141            if self.DistP.MiscellaneousFiles:
142                XmlTreeLevel = ['DistributionPackage', 'MiscellaneousFiles', 'Header']
143                CheckDict = {'Name':self.DistP.MiscellaneousFiles.GetName(), }
144                IsRequiredItemListNull(CheckDict, XmlTreeLevel)
145
146                if not self.DistP.MiscellaneousFiles.GetFileList():
147                    XmlTreeLevel = ['DistributionPackage', 'MiscellaneousFiles']
148                    CheckDict = {'FileName':None, }
149                    IsRequiredItemListNull(CheckDict, XmlTreeLevel)
150                for Item in self.DistP.MiscellaneousFiles.GetFileList():
151                    XmlTreeLevel = ['DistributionPackage', 'MiscellaneousFiles']
152                    CheckDict = {'FileName':Item.GetURI(), }
153                    IsRequiredItemListNull(CheckDict, XmlTreeLevel)
154
155            #
156            # Check Each Distribution Level User Extension
157            #
158            for Item in self.DistP.UserExtensions:
159                XmlTreeLevel = ['DistributionPackage', 'UserExtensions']
160                CheckDict = {'UserId':Item.GetUserID(), }
161                IsRequiredItemListNull(CheckDict, XmlTreeLevel)
162
163
164    def FromXml(self, Filename=None):
165        if Filename != None:
166            self.DistP = DistributionPackageClass()
167            #
168            # Load to XML
169            #
170            self.Pkg = XmlParseFile(Filename)
171
172            #
173            # Parse Header information
174            #
175            Tmp = DistributionPackageHeaderXml()
176            DistributionPackageHeader = \
177            Tmp.FromXml(XmlNode(self.Pkg, '/DistributionPackage/DistributionHeader'), 'DistributionHeader')
178            self.DistP.Header = DistributionPackageHeader
179            #
180            # Parse each PackageSurfaceArea
181            #
182            for Item in XmlList(self.Pkg, '/DistributionPackage/PackageSurfaceArea'):
183                Psa = PackageSurfaceAreaXml()
184                Package = Psa.FromXml(Item, 'PackageSurfaceArea')
185                self.DistP.PackageSurfaceArea[(Package.GetGuid(), \
186                                               Package.GetVersion(), \
187                                               Package.GetPackagePath())] = \
188                                               Package
189            #
190            # Parse each ModuleSurfaceArea
191            #
192            for Item in XmlList(self.Pkg, '/DistributionPackage/ModuleSurfaceArea'):
193                Msa = ModuleSurfaceAreaXml()
194                Module = Msa.FromXml(Item, 'ModuleSurfaceArea', True)
195                ModuleKey = (Module.GetGuid(), Module.GetVersion(), Module.GetName(), Module.GetModulePath())
196                self.DistP.ModuleSurfaceArea[ModuleKey] = Module
197
198            #
199            # Parse Tools
200            #
201            Tmp = MiscellaneousFileXml()
202            self.DistP.Tools = Tmp.FromXml2(XmlNode(self.Pkg, '/DistributionPackage/Tools'), 'Tools')
203
204            #
205            # Parse MiscFiles
206            #
207            Tmp = MiscellaneousFileXml()
208            self.DistP.MiscellaneousFiles = \
209            Tmp.FromXml2(XmlNode(self.Pkg, \
210                                 '/DistributionPackage/MiscellaneousFiles'), \
211                                 'MiscellaneousFiles')
212
213            #
214            # Parse UserExtensions
215            #
216            for Item in XmlList(self.Pkg, '/DistributionPackage/UserExtensions'):
217                Tmp = UserExtensionsXml()
218                self.DistP.UserExtensions.append(Tmp.FromXml2(Item, 'UserExtensions'))
219
220            #
221            # Check Required Items for XML
222            #
223            self.ValidateDistributionPackage()
224
225            return self.DistP
226
227    def ToXml(self, DistP):
228        if self.DistP:
229            pass
230        if DistP != None:
231            #
232            # Parse DistributionPackageHeader
233            #
234            Attrs = [['xmlns', 'http://www.uefi.org/2011/1.1'],
235                     ['xmlns:xsi', 'http:/www.w3.org/2001/XMLSchema-instance'],
236                     ]
237            Root = CreateXmlElement('DistributionPackage', '', [], Attrs)
238
239            Tmp = DistributionPackageHeaderXml()
240            Root.appendChild(Tmp.ToXml(DistP.Header, 'DistributionHeader'))
241            #
242            # Parse each PackageSurfaceArea
243            #
244            for Package in DistP.PackageSurfaceArea.values():
245                Psa = PackageSurfaceAreaXml()
246                DomPackage = Psa.ToXml(Package)
247                Root.appendChild(DomPackage)
248            #
249            # Parse each ModuleSurfaceArea
250            #
251            for Module in DistP.ModuleSurfaceArea.values():
252                Msa = ModuleSurfaceAreaXml()
253                DomModule = Msa.ToXml(Module)
254                Root.appendChild(DomModule)
255            #
256            # Parse Tools
257            #
258            Tmp = MiscellaneousFileXml()
259            ToolNode = Tmp.ToXml2(DistP.Tools, 'Tools')
260            if ToolNode is not None:
261                Root.appendChild(ToolNode)
262            #
263            # Parse MiscFiles
264            #
265            Tmp = MiscellaneousFileXml()
266            MiscFileNode = Tmp.ToXml2(DistP.MiscellaneousFiles,
267                                      'MiscellaneousFiles')
268            if MiscFileNode is not None:
269                Root.appendChild(MiscFileNode)
270
271            XmlContent = Root.toprettyxml(indent='  ')
272
273
274            #
275            # Remove empty element
276            #
277            XmlContent = re.sub(r'[\s\r\n]*<[^<>=]*/>', '', XmlContent)
278
279            #
280            # Remove empty help text element
281            #
282            XmlContent = re.sub(r'[\s\r\n]*<HelpText Lang="en-US"/>', '',
283                                XmlContent)
284
285            #
286            # Remove SupArchList="COMMON" or "common"
287            #
288            XmlContent = \
289            re.sub(r'[\s\r\n]*SupArchList[\s\r\n]*=[\s\r\n]*"[\s\r\n]*COMMON'
290            '[\s\r\n]*"', '', XmlContent)
291            XmlContent = \
292            re.sub(r'[\s\r\n]*SupArchList[\s\r\n]*=[\s\r\n]*"[\s\r\n]*common'
293            '[\s\r\n]*"', '', XmlContent)
294            #
295            # Remove <SupArchList> COMMON </SupArchList>
296            #
297            XmlContent = \
298            re.sub(r'[\s\r\n]*<SupArchList>[\s\r\n]*COMMON[\s\r\n]*'
299            '</SupArchList>[\s\r\n]*', '', XmlContent)
300
301            #
302            # Remove <SupArchList> common </SupArchList>
303            #
304            XmlContent = \
305            re.sub(r'[\s\r\n]*<SupArchList>[\s\r\n]*'
306            'common[\s\r\n]*</SupArchList>[\s\r\n]*', '', XmlContent)
307
308            #
309            # Remove SupModList="COMMON" or "common"
310            #
311            XmlContent = \
312            re.sub(r'[\s\r\n]*SupModList[\s\r\n]*=[\s\r\n]*"[\s\r\n]*COMMON'
313            '[\s\r\n]*"', '', XmlContent)
314            XmlContent = \
315            re.sub(r'[\s\r\n]*SupModList[\s\r\n]*=[\s\r\n]*"[\s\r\n]*common'
316            '[\s\r\n]*"', '', XmlContent)
317
318            return XmlContent
319
320        return ''
321
322## ValidateMS
323#
324# Check if any required item is missing in ModuleSurfaceArea
325#
326# @param Module: The ModuleSurfaceArea to be checked
327# @param XmlTreeLevel: The top level of Module
328#
329def ValidateMS(Module, TopXmlTreeLevel):
330    ValidateMS1(Module, TopXmlTreeLevel)
331    ValidateMS2(Module, TopXmlTreeLevel)
332    ValidateMS3(Module, TopXmlTreeLevel)
333
334## ValidateMS1
335#
336# Check if any required item is missing in ModuleSurfaceArea
337#
338# @param Module: The ModuleSurfaceArea to be checked
339# @param XmlTreeLevel: The top level of Module
340#
341def ValidateMS1(Module, TopXmlTreeLevel):
342    #
343    # Check Guids -> GuidCName
344    #
345    XmlTreeLevel = TopXmlTreeLevel + ['Guids']
346    for Item in Module.GetGuidList():
347        if Item == None:
348            CheckDict = {'GuidCName':''}
349            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
350
351    XmlTreeLevel = TopXmlTreeLevel + ['Guids', 'GuidCName']
352    for Item in Module.GetGuidList():
353        CheckDict = {'CName':Item.GetCName(),
354                     'GuidType':Item.GetGuidTypeList(),
355                     'Usage':Item.GetUsage()}
356        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
357
358        if Item.GetVariableName():
359            Result = ConvertVariableName(Item.GetVariableName())
360            if Result is None:
361                Msg = "->".join(Node for Node in XmlTreeLevel)
362                ErrorMsg = ERR_XML_INVALID_VARIABLENAME % (Item.GetVariableName(), Item.GetCName(), Msg)
363                Logger.Error('\nUPT', PARSER_ERROR, ErrorMsg, RaiseError=True)
364            else:
365                Item.SetVariableName(Result)
366
367    #
368    # Check Protocols -> Protocol
369    #
370    XmlTreeLevel = TopXmlTreeLevel + ['Protocols']
371    for Item in Module.GetProtocolList():
372        if Item == None:
373            CheckDict = {'Protocol':''}
374            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
375
376    XmlTreeLevel = TopXmlTreeLevel + ['Protocols', 'Protocol']
377    for Item in Module.GetProtocolList():
378        CheckDict = {'CName':Item.GetCName(),
379                     'Usage':Item.GetUsage()}
380        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
381
382    #
383    # Check PPIs -> Ppi
384    #
385    XmlTreeLevel = TopXmlTreeLevel + ['PPIs']
386    for Item in Module.GetPpiList():
387        if Item == None:
388            CheckDict = {'Ppi':''}
389            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
390
391    XmlTreeLevel = TopXmlTreeLevel + ['PPIs', 'Ppi']
392    for Item in Module.GetPpiList():
393        CheckDict = {'CName':Item.GetCName(),
394                     'Usage':Item.GetUsage()}
395        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
396
397    #
398    # Check PcdCoded -> Entry
399    #
400    XmlTreeLevel = TopXmlTreeLevel + ['PcdCoded']
401    for Item in Module.GetPcdList():
402        if Item == None:
403            CheckDict = {'PcdEntry':''}
404            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
405
406    XmlTreeLevel = TopXmlTreeLevel + ['PcdCoded', 'PcdEntry']
407    for Item in Module.GetPcdList():
408        CheckDict = {'TokenSpaceGuidCname':Item.GetTokenSpaceGuidCName(),
409                     'CName':Item.GetCName(),
410                     'PcdUsage':Item.GetValidUsage(),
411                     'PcdItemType':Item.GetItemType()}
412        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
413
414    #
415    # Check Externs -> Extern
416    #
417    XmlTreeLevel = TopXmlTreeLevel + ['Externs']
418    for Item in Module.GetExternList():
419        if Item == None:
420            CheckDict = {'Extern':''}
421            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
422
423    #
424    # If SupArchList is used to identify different EntryPoint, UnloadImage, Constructor/Destructor elements and
425    # that SupArchList does not match ModuleSurfaceArea.ModuleProperties:SupArchList, the tool must exit gracefully,
426    # informing the user that the EDK II Build system does not support different EntryPoint, UnloadImage,
427    # Constructor or Destructor elements based on Architecture type.  Two SupArchList attributes are considered
428    # identical if it lists the same CPU architectures in any order.
429    #
430    for Item in Module.GetExternList():
431        if len(Item.SupArchList) > 0:
432            if not IsEqualList(Item.SupArchList, Module.SupArchList):
433                Logger.Error('\nUPT',
434                             PARSER_ERROR,
435                             ERR_XML_INVALID_EXTERN_SUPARCHLIST % (str(Item.SupArchList), str(Module.SupArchList)),
436                             RaiseError=True)
437
438    #
439    # Check DistributionPackage -> ModuleSurfaceArea -> UserExtensions
440    #
441    XmlTreeLevel = TopXmlTreeLevel + ['UserExtensions']
442    for Item in Module.GetUserExtensionList():
443        CheckDict = {'UserId':Item.GetUserID(), 'Identifier':Item.GetIdentifier()}
444        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
445
446    #
447    # Check DistributionPackage -> PackageSurfaceArea -> MiscellaneousFiles -> Filename
448    #
449    XmlTreeLevel = TopXmlTreeLevel + ['MiscellaneousFiles']
450    for Item in Module.GetMiscFileList():
451        if not Item.GetFileList():
452            CheckDict = {'Filename':'', }
453            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
454        for File in Item.GetFileList():
455            CheckDict = {'Filename':File.GetURI(), }
456
457## ValidateMS2
458#
459# Check if any required item is missing in ModuleSurfaceArea
460#
461# @param Module: The ModuleSurfaceArea to be checked
462# @param XmlTreeLevel: The top level of Module
463#
464def ValidateMS2(Module, TopXmlTreeLevel):
465    #
466    # Check Header
467    #
468    XmlTreeLevel = TopXmlTreeLevel + ['Header']
469    CheckDict = Sdict()
470    CheckDict['Name'] = Module.GetName()
471    CheckDict['BaseName'] = Module.GetBaseName()
472    CheckDict['GUID'] = Module.GetGuid()
473    CheckDict['Version'] = Module.GetVersion()
474    IsRequiredItemListNull(CheckDict, XmlTreeLevel)
475
476    #
477    # Check ModuleProperties
478    #
479    XmlTreeLevel = TopXmlTreeLevel + ['ModuleProperties']
480    CheckDict = {'ModuleType':Module.GetModuleType(),
481                 'Path':Module.GetModulePath()}
482    IsRequiredItemListNull(CheckDict, XmlTreeLevel)
483
484    if not IsValidInstallPath(Module.GetModulePath()):
485        Logger.Error("UPT", FORMAT_INVALID, ERR_FILE_NAME_INVALIDE % Module.GetModulePath())
486
487    #
488    # Check ModuleProperties->BootMode
489    #
490    XmlTreeLevel = TopXmlTreeLevel + ['ModuleProperties'] + ['BootMode']
491    for Item in Module.GetBootModeList():
492        CheckDict = {'Usage':Item.GetUsage(),
493                     'SupportedBootModes':Item.GetSupportedBootModes()}
494        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
495
496    #
497    # Check ModuleProperties->Event
498    #
499    XmlTreeLevel = TopXmlTreeLevel + ['ModuleProperties'] + ['Event']
500    for Item in Module.GetEventList():
501        CheckDict = {'Usage':Item.GetUsage(),
502                     'EventType':Item.GetEventType()}
503        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
504
505    #
506    # Check ModuleProperties->Hob
507    #
508    XmlTreeLevel = TopXmlTreeLevel + ['ModuleProperties'] + ['HOB']
509    for Item in Module.GetHobList():
510        CheckDict = {'Usage':Item.GetUsage(),
511                     'HobType':Item.GetHobType()}
512        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
513
514    #
515    # The UDP Specification supports the module type of UEFI_RUNTIME_DRIVER, which is not present in the EDK II INF
516    # File Specification v. 1.23, so UPT must perform the following translation that include the generation of a
517    # [Depex] section.
518    #
519    if Module.ModuleType == "UEFI_RUNTIME_DRIVER":
520        Module.ModuleType = "DXE_RUNTIME_DRIVER"
521        DxeObj = DepexObject()
522        DxeObj.SetDepex("gEfiBdsArchProtocolGuid AND \ngEfiCpuArchProtocolGuid AND\n" + \
523                        "gEfiMetronomeArchProtocolGuid AND \ngEfiMonotonicCounterArchProtocolGuid AND\n" + \
524                        "gEfiRealTimeClockArchProtocolGuid AND \ngEfiResetArchProtocolGuid AND\n" + \
525                        "gEfiRuntimeArchProtocolGuid AND \ngEfiSecurityArchProtocolGuid AND\n" + \
526                        "gEfiTimerArchProtocolGuid AND \ngEfiVariableWriteArchProtocolGuid AND\n" + \
527                        "gEfiVariableArchProtocolGuid AND \ngEfiWatchdogTimerArchProtocolGuid")
528        DxeObj.SetModuleType(['DXE_RUNTIME_DRIVER'])
529        Module.PeiDepex = []
530        Module.DxeDepex = []
531        Module.SmmDepex = []
532        Module.DxeDepex.append(DxeObj)
533
534    #
535    # Check LibraryClassDefinitions -> LibraryClass
536    #
537    XmlTreeLevel = TopXmlTreeLevel + ['LibraryClassDefinitions']
538    for Item in Module.GetLibraryClassList():
539        if Item == None:
540            CheckDict = {'LibraryClass':''}
541            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
542
543    XmlTreeLevel = TopXmlTreeLevel + ['LibraryClassDefinitions', 'LibraryClass']
544
545    IsLibraryModule = False
546    LibrarySupModList = []
547    for Item in Module.GetLibraryClassList():
548        CheckDict = {'Keyword':Item.GetLibraryClass(),
549                     'Usage':Item.GetUsage()}
550        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
551        #
552        # If the LibraryClass:SupModList is not "UNDEFINED" the LIBRARY_CLASS entry must have the list
553        # appended using the format:
554        # LIBRARY_CLASS = <ClassName> ["|" <Edk2ModuleTypeList>]
555        #
556        # Edk2ModuleTypeList ::= <ModuleType> [" " <ModuleType>]{0,}
557        # <ModuleTypes>      ::= {"BASE"} {"SEC"} {"PEI_CORE"} {"PEIM"}
558        #                       {"DXE_CORE"} {"DXE_DRIVER"} {"SMM_CORE"}
559        #                       {"DXE_SMM_DRIVER"} {"DXE_RUNTIME_DRIVER"}
560        #                       {"DXE_SAL_DRIVER"} {"UEFI_DRIVER"}
561        #                       {"UEFI_APPLICATION"} {"USER_DEFINED"}
562        #
563        if len(Item.SupModuleList) > 0:
564            for SupModule in Item.SupModuleList:
565                if not IsValidInfMoudleType(SupModule):
566                    Logger.Error('\nUPT',
567                                 PARSER_ERROR,
568                                 ERR_XML_INVALID_LIB_SUPMODLIST % (Item.LibraryClass, str(SupModule)),
569                                 RaiseError=True)
570
571        if Item.Usage == 'PRODUCES' or Item.Usage == 'SOMETIMES_PRODUCES':
572            IsLibraryModule = True
573            LibrarySupModList = Item.SupModuleList
574
575
576    #
577    # For Library modules (indicated by a LIBRARY_CLASS statement in the [Defines] section)
578    # If the SupModList attribute of the CONSTRUCTOR or DESTRUCTOR element does not match the Supported Module
579    # Types listed after "LIBRARY_CLASS = <Keyword> |", the tool should gracefully exit with an error message
580    # stating that there is a conflict in the module types the CONSTRUCTOR/DESTRUCTOR is to be used with and
581    # the Module types this Library supports.
582    #
583    if IsLibraryModule:
584        for Item in Module.GetExternList():
585            if Item.Constructor or Item.Destructor:
586                if hasattr(Item, 'SupModList') and len(Item.SupModList) > 0 and \
587                   not IsEqualList(Item.SupModList, LibrarySupModList):
588                    Logger.Error('\nUPT',
589                         PARSER_ERROR,
590                         ERR_XML_INVALID_EXTERN_SUPMODLIST % (str(Item.SupModList), str(LibrarySupModList)),
591                         RaiseError=True)
592
593    #
594    # If the module is not a library module, the MODULE_TYPE listed in the ModuleSurfaceArea.Header must match the
595    # SupModList attribute.  If these conditions cannot be met, the tool must exit gracefully, informing the user
596    # that the EDK II Build system does not currently support the features required by this Module.
597    #
598    if not IsLibraryModule:
599        for Item in Module.GetExternList():
600            if hasattr(Item, 'SupModList') and len(Item.SupModList) > 0 and \
601               not IsEqualList(Item.SupModList, [Module.ModuleType]):
602                Logger.Error('\nUPT',
603                     PARSER_ERROR,
604                     ERR_XML_INVALID_EXTERN_SUPMODLIST_NOT_LIB % (str(Module.ModuleType), str(Item.SupModList)),
605                     RaiseError=True)
606    #
607    # Check SourceFiles
608    #
609    XmlTreeLevel = TopXmlTreeLevel + ['SourceFiles']
610    for Item in Module.GetSourceFileList():
611        if Item == None:
612            CheckDict = {'Filename':''}
613            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
614
615    XmlTreeLevel = TopXmlTreeLevel + ['SourceFiles']
616    for Item in Module.GetSourceFileList():
617        CheckDict = {'Filename':Item.GetSourceFile()}
618        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
619
620    for ItemCount in range(len(Module.GetBinaryFileList())):
621        Item = Module.GetBinaryFileList()[ItemCount]
622        if Item and len(Item.FileNamList) > 0 and Item.FileNamList[0].FileType == 'FREEFORM':
623            Item.FileNamList[0].FileType = 'SUBTYPE_GUID'
624            Module.GetBinaryFileList()[ItemCount] = Item
625
626## ValidateMS3
627#
628# Check if any required item is missing in ModuleSurfaceArea
629#
630# @param Module: The ModuleSurfaceArea to be checked
631# @param XmlTreeLevel: The top level of Module
632#
633def ValidateMS3(Module, TopXmlTreeLevel):
634    #
635    # Check PackageDependencies -> Package
636    #
637    XmlTreeLevel = TopXmlTreeLevel + ['PackageDependencies']
638    for Item in Module.GetPackageDependencyList():
639        if Item == None:
640            CheckDict = {'Package':''}
641            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
642
643    XmlTreeLevel = TopXmlTreeLevel + ['PackageDependencies', 'Package']
644    for Item in Module.GetPackageDependencyList():
645        CheckDict = {'GUID':Item.GetGuid()}
646        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
647
648    #
649    # Check BinaryFiles -> BinaryFile
650    #
651    for Item in Module.GetBinaryFileList():
652        if Item == None:
653            XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles']
654            CheckDict = {'BinaryFile':''}
655            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
656        if not Item.GetFileNameList():
657            XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile']
658            CheckDict = {'Filename':''}
659            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
660
661        XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile']
662        for File in Item.GetFileNameList():
663            CheckDict = {'Filename':File.GetFilename(),
664                         'FileType':File.GetFileType()}
665            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
666        for AsBuilt in Item.GetAsBuiltList():
667            #
668            # Check LibInstance
669            #
670            if len(AsBuilt.LibraryInstancesList) == 1 and not AsBuilt.LibraryInstancesList[0]:
671                CheckDict = {'GUID':''}
672                XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt', 'LibraryInstances']
673                IsRequiredItemListNull(CheckDict, XmlTreeLevel)
674
675            for LibItem in AsBuilt.LibraryInstancesList:
676                CheckDict = {'Guid':LibItem.Guid,
677                             'Version':LibItem.Version}
678                XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt', 'LibraryInstances']
679                IsRequiredItemListNull(CheckDict, XmlTreeLevel)
680
681            #
682            # Check PatchPcd
683            #
684            for PatchPcdItem in AsBuilt.PatchPcdList:
685                CheckDict = {'TokenSpaceGuidValue':PatchPcdItem.TokenSpaceGuidValue,
686                             'PcdCName':PatchPcdItem.PcdCName,
687                             'Token':PatchPcdItem.Token,
688                             'DatumType':PatchPcdItem.DatumType,
689                             'Value':PatchPcdItem.DefaultValue,
690                             'Offset':PatchPcdItem.Offset}
691                XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt', 'PatchPcdValue']
692                IsRequiredItemListNull(CheckDict, XmlTreeLevel)
693                #
694                # Check PcdError
695                #
696                for PcdErrorItem in PatchPcdItem.PcdErrorsList:
697                    CheckDict = {'ErrorNumber':PcdErrorItem.ErrorNumber}
698                    XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt',
699                                                      'PatchPcdValue', 'PcdError']
700                    IsRequiredItemListNull(CheckDict, XmlTreeLevel)
701            #
702            # Check PcdEx
703            #
704            for PcdExItem in AsBuilt.PcdExValueList:
705                CheckDict = {'TokenSpaceGuidValue':PcdExItem.TokenSpaceGuidValue,
706                             'Token':PcdExItem.Token,
707                             'DatumType':PcdExItem.DatumType}
708                XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt', 'PcdExValue']
709                IsRequiredItemListNull(CheckDict, XmlTreeLevel)
710                #
711                # Check PcdError
712                #
713                for PcdErrorItem in PcdExItem.PcdErrorsList:
714                    CheckDict = {'ErrorNumber':PcdErrorItem.ErrorNumber}
715                    XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt',
716                                                      'PcdExValue', 'PcdError']
717                    IsRequiredItemListNull(CheckDict, XmlTreeLevel)
718    #
719    # Check SmmDepex
720    #
721    XmlTreeLevel = TopXmlTreeLevel + ['SmmDepex']
722    for Item in Module.GetSmmDepex():
723        CheckDict = {'Expression':Item.GetDepex()}
724        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
725
726    #
727    # Check PeiDepex
728    #
729    XmlTreeLevel = TopXmlTreeLevel + ['PeiDepex']
730    for Item in Module.GetPeiDepex():
731        CheckDict = {'Expression':Item.GetDepex()}
732        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
733
734    #
735    # Check DxeDepex
736    #
737    XmlTreeLevel = TopXmlTreeLevel + ['DxeDepex']
738    for Item in Module.GetDxeDepex():
739        CheckDict = {'Expression':Item.GetDepex()}
740        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
741
742    #
743    # Check <UserExtensions>
744    #
745    XmlTreeLevel = TopXmlTreeLevel + ['UserExtensions']
746    for Item in Module.GetUserExtensionList():
747        CheckDict = {'UserId':Item.GetUserID(), 'Identifier':Item.GetIdentifier()}
748        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
749
750## ValidatePS1
751#
752# ValidatePS1
753#
754def ValidatePS1(Package):
755    #
756    # Check DistributionPackage -> PackageSurfaceArea -> Header
757    #
758    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'Header']
759    CheckDict = Sdict()
760    CheckDict['Name'] = Package.GetName()
761    CheckDict['BaseName'] = Package.GetBaseName()
762    CheckDict['GUID'] = Package.GetGuid()
763    CheckDict['Version'] = Package.GetVersion()
764    CheckDict['PackagePath'] = Package.GetPackagePath()
765
766    IsRequiredItemListNull(CheckDict, XmlTreeLevel)
767    if not IsValidInstallPath(Package.GetPackagePath()):
768        Logger.Error("UPT", FORMAT_INVALID, ERR_FILE_NAME_INVALIDE % Package.GetPackagePath())
769
770    #
771    # Check DistributionPackage -> PackageSurfaceArea -> ClonedFrom
772    #
773    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'ClonedFrom']
774    for Item in Package.GetClonedFromList():
775        if Item == None:
776            CheckDict = Sdict()
777            CheckDict['GUID'] = ''
778            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
779        CheckDict = Sdict()
780        CheckDict['GUID'] = Item.GetPackageGuid()
781        CheckDict['Version'] = Item.GetPackageVersion()
782
783        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
784
785    #
786    # Check DistributionPackage -> PackageSurfaceArea -> LibraryClassDeclarations -> LibraryClass
787    #
788    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'LibraryClassDeclarations']
789    for Item in Package.GetLibraryClassList():
790        if Item == None:
791            CheckDict = {'LibraryClass':''}
792            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
793
794    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'LibraryClassDeclarations', 'LibraryClass']
795    for Item in Package.GetLibraryClassList():
796        CheckDict = {'Keyword':Item.GetLibraryClass(),
797                     'HeaderFile':Item.GetIncludeHeader()}
798        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
799
800    #
801    # Check DistributionPackage -> PackageSurfaceArea -> IndustryStandardIncludes -> IndustryStandardHeader
802    #
803    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'IndustryStandardIncludes']
804    for Item in Package.GetStandardIncludeFileList():
805        if Item == None:
806            CheckDict = {'IndustryStandardHeader':''}
807            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
808
809    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'IndustryStandardIncludes', 'IndustryStandardHeader']
810    for Item in Package.GetStandardIncludeFileList():
811        CheckDict = {'HeaderFile':Item.GetFilePath()}
812        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
813
814    #
815    # Check DistributionPackage -> PackageSurfaceArea -> PackageIncludes -> PackageHeader
816    #
817    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PackageIncludes']
818    for Item in Package.GetPackageIncludeFileList():
819        if Item == None:
820            CheckDict = {'PackageHeader':''}
821            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
822
823    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PackageIncludes', 'PackageHeader']
824    for Item in Package.GetPackageIncludeFileList():
825        CheckDict = {'HeaderFile':Item.GetFilePath()}
826        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
827
828## ValidatePS2
829#
830# ValidatePS2
831#
832def ValidatePS2(Package):
833    #
834    # Check DistributionPackage -> PackageSurfaceArea -> Modules -> ModuleSurfaceArea
835    #
836    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'Modules', 'ModuleSurfaceArea']
837    for Item in Package.GetModuleDict().values():
838        ValidateMS(Item, XmlTreeLevel)
839
840    #
841    # Check DistributionPackage -> PackageSurfaceArea -> GuidDeclarations Entry
842    #
843    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'GuidDeclarations']
844    for Item in Package.GetGuidList():
845        if Item == None:
846            CheckDict = {'Entry':''}
847            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
848
849    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'GuidDeclarations', 'Entry']
850    for Item in Package.GetGuidList():
851        CheckDict = {'CName':Item.GetCName(),
852                     'GuidValue':Item.GetGuid()}
853        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
854
855    #
856    # Check DistributionPackage -> PackageSurfaceArea -> ProtocolDeclarations -> Entry
857    #
858    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'ProtocolDeclarations']
859    for Item in Package.GetProtocolList():
860        if Item == None:
861            CheckDict = {'Entry':''}
862            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
863
864    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'ProtocolDeclarations', 'Entry']
865    for Item in Package.GetProtocolList():
866        CheckDict = {'CName':Item.GetCName(),
867                     'GuidValue':Item.GetGuid()}
868        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
869
870    #
871    # Check DistributionPackage -> PackageSurfaceArea -> PpiDeclarations -> Entry
872    #
873    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PpiDeclarations']
874    for Item in Package.GetPpiList():
875        if Item == None:
876            CheckDict = {'Entry':''}
877            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
878
879    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PpiDeclarations', 'Entry']
880    for Item in Package.GetPpiList():
881        CheckDict = {'CName':Item.GetCName(),
882                     'GuidValue':Item.GetGuid()}
883        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
884
885    #
886    # Check DistributionPackage -> PackageSurfaceArea -> PcdDeclarations -> Entry
887    #
888    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PcdDeclarations']
889    for Item in Package.GetPcdList():
890        if Item == None:
891            CheckDict = {'PcdEntry':''}
892            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
893
894    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PcdDeclarations', 'PcdEntry']
895    for Item in Package.GetPcdList():
896        CheckDict = {'TokenSpaceGuidCname':Item.GetTokenSpaceGuidCName(),
897                     'Token':Item.GetToken(),
898                     'CName':Item.GetCName(),
899                     'DatumType':Item.GetDatumType(),
900                     'ValidUsage':Item.GetValidUsage(),
901                     'DefaultValue':Item.GetDefaultValue()}
902        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
903
904    #
905    # Check DistributionPackage -> PackageSurfaceArea -> UserExtensions
906    #
907    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'UserExtensions']
908    for Item in Package.GetUserExtensionList():
909        CheckDict = {'UserId':Item.GetUserID(), 'Identifier':Item.GetIdentifier()}
910        IsRequiredItemListNull(CheckDict, XmlTreeLevel)
911
912    #
913    # Check DistributionPackage -> PackageSurfaceArea -> MiscellaneousFiles -> Filename
914    #
915    XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'MiscellaneousFiles']
916    for Item in Package.GetMiscFileList():
917        if not Item.GetFileList():
918            CheckDict = {'Filename':'', }
919            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
920        for File in Item.GetFileList():
921            CheckDict = {'Filename':File.GetURI(), }
922            IsRequiredItemListNull(CheckDict, XmlTreeLevel)
923
924## ValidatePackageSurfaceArea
925#
926# Check if any required item is missing in  PackageSurfaceArea
927#
928# @param Package: The PackageSurfaceArea to be checked
929#
930def ValidatePackageSurfaceArea(Package):
931    ValidatePS1(Package)
932    ValidatePS2(Package)
933