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