From nobody Fri May 3 20:34:49 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1521096367069640.65916659271; Wed, 14 Mar 2018 23:46:07 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 55A1B2202E4BF; Wed, 14 Mar 2018 23:39:41 -0700 (PDT) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 9069520956061 for ; Wed, 14 Mar 2018 23:39:39 -0700 (PDT) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Mar 2018 23:46:02 -0700 Received: from shwdeopenpsi168.ccr.corp.intel.com ([10.239.158.129]) by fmsmga002.fm.intel.com with ESMTP; 14 Mar 2018 23:45:53 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.136; helo=mga12.intel.com; envelope-from=yonghong.zhu@intel.com; receiver=edk2-devel@lists.01.org X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.48,308,1517904000"; d="scan'208";a="28058797" From: Yonghong Zhu To: edk2-devel@lists.01.org Date: Thu, 15 Mar 2018 14:45:51 +0800 Message-Id: <1521096351-17908-1-git-send-email-yonghong.zhu@intel.com> X-Mailer: git-send-email 2.6.1.windows.1 Subject: [edk2] [Patch] BaseTools: Add PackageDocumentTools into Scripts folder X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Liming Gao , Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This tool is used to generate the document for edk2 packages. The generated document will be in UDK release. For example, UDK2017 document can be found in: https://github.com/tianocore/tianocore.github.io/wiki/UDK2017#documentation Cc: Star Zeng Cc: Liming Gao Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Yonghong Zhu Reviewed-by: Star Zeng --- BaseTools/Scripts/PackageDocumentTools/Readme.md | 19 + BaseTools/Scripts/PackageDocumentTools/__init__.py | 12 + .../Scripts/PackageDocumentTools/packagedoc_cli.py | 429 ++++++++ .../Scripts/PackageDocumentTools/packagedocapp.pyw | 1066 ++++++++++++++++= +++ .../plugins/EdkPlugins/__init__.py | 12 + .../plugins/EdkPlugins/basemodel/__init__.py | 12 + .../plugins/EdkPlugins/basemodel/doxygen.py | 449 ++++++++ .../plugins/EdkPlugins/basemodel/efibinary.py | 611 +++++++++++ .../plugins/EdkPlugins/basemodel/ini.py | 480 +++++++++ .../plugins/EdkPlugins/basemodel/inidocview.py | 23 + .../plugins/EdkPlugins/basemodel/message.py | 52 + .../plugins/EdkPlugins/edk2/__init__.py | 12 + .../plugins/EdkPlugins/edk2/model/__init__.py | 12 + .../plugins/EdkPlugins/edk2/model/baseobject.py | 934 +++++++++++++++++ .../plugins/EdkPlugins/edk2/model/dec.py | 319 ++++++ .../plugins/EdkPlugins/edk2/model/doxygengen.py | 1089 ++++++++++++++++= +++ .../EdkPlugins/edk2/model/doxygengen_spec.py | 1092 ++++++++++++++++= ++++ .../plugins/EdkPlugins/edk2/model/dsc.py | 201 ++++ .../plugins/EdkPlugins/edk2/model/inf.py | 341 ++++++ .../PackageDocumentTools/plugins/__init__.py | 12 + 20 files changed, 7177 insertions(+) create mode 100644 BaseTools/Scripts/PackageDocumentTools/Readme.md create mode 100644 BaseTools/Scripts/PackageDocumentTools/__init__.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/packagedoc_cli.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/packagedocapp.pyw create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/__init__.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/basemodel/__init__.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/basemodel/doxygen.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/basemodel/efibinary.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/basemodel/ini.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/basemodel/inidocview.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/basemodel/message.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/edk2/__init__.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/edk2/model/__init__.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/edk2/model/baseobject.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/edk2/model/dec.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/edk2/model/doxygengen.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/edk2/model/doxygengen_spec.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/edk2/model/dsc.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/edk2/model/inf.py create mode 100644 BaseTools/Scripts/PackageDocumentTools/plugins/__init__= .py diff --git a/BaseTools/Scripts/PackageDocumentTools/Readme.md b/BaseTools/S= cripts/PackageDocumentTools/Readme.md new file mode 100644 index 0000000..dfc2892 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/Readme.md @@ -0,0 +1,19 @@ +Prerequisite Tools: +1. Install Python 2.7.3 from https://www.python.org/download/releases/2.7.= 3/ +2. Install wxPython 2.8.12.1 from https://sourceforge.net/projects/wxpytho= n/files/wxPython/2.8.12.1/ + generally the libraries will be installed at python's subfolder, for ex= ample in windows: c:\python27\Lib\site-packages\ +3. Install DoxyGen 1.8.6 from https://sourceforge.net/projects/doxygen/fil= es/rel-1.8.6/ +4. (Windows only) Install Htmlhelp tool from https://msdn.microsoft.com/en= -us/library/windows/desktop/ms669985(v=3Dvs.85).aspx + +Limitation: +1. Current tool doesn't work on latest wxPython and DoxyGen tool. Please u= se the sepecific version in above. + +Run the Tool: +a) Run with GUI: + 1. Enter src folder, double click "packagedocapp.pyw" or run command "py= thon packagedocapp.pyw" to open the GUI. + 2. Make sure all the information in blank are correct. + 3. Click "Generate Package Document!" +b) Run with command line: + 1. Open command line window + 2. Enter src folder, for example: "cd C:\PackageDocumentTools\src" + 3. Run "python packagedoc_cli.py --help" for detail command. diff --git a/BaseTools/Scripts/PackageDocumentTools/__init__.py b/BaseTools= /Scripts/PackageDocumentTools/__init__.py new file mode 100644 index 0000000..3e4ee53 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/__init__.py @@ -0,0 +1,12 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# diff --git a/BaseTools/Scripts/PackageDocumentTools/packagedoc_cli.py b/Bas= eTools/Scripts/PackageDocumentTools/packagedoc_cli.py new file mode 100644 index 0000000..92ee699 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/packagedoc_cli.py @@ -0,0 +1,429 @@ +## @file +# This module provide command line entry for generating package document! +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# + +import os, sys, logging, traceback, subprocess +from optparse import OptionParser + +import plugins.EdkPlugins.edk2.model.baseobject as baseobject +import plugins.EdkPlugins.edk2.model.doxygengen as doxygengen + +gArchMarcoDict =3D {'ALL' : 'MDE_CPU_IA32 MDE_CPU_X64 MDE_CPU_EBC MDE= _CPU_IPF _MSC_EXTENSIONS __GNUC__ __INTEL_COMPILER', + 'IA32_MSFT': 'MDE_CPU_IA32 _MSC_EXTENSIONS', + 'IA32_GNU' : 'MDE_CPU_IA32 __GNUC__', + 'X64_MSFT' : 'MDE_CPU_X64 _MSC_EXTENSIONS ASM_PFX=3D OP= TIONAL=3D ', + 'X64_GNU' : 'MDE_CPU_X64 __GNUC__ ASM_PFX=3D OPTIONAL= =3D ', + 'IPF_MSFT' : 'MDE_CPU_IPF _MSC_EXTENSIONS ASM_PFX=3D OP= TIONAL=3D ', + 'IPF_GNU' : 'MDE_CPU_IPF __GNUC__ ASM_PFX=3D OPTIONAL= =3D ', + 'EBC_INTEL': 'MDE_CPU_EBC __INTEL_COMPILER ASM_PFX=3D O= PTIONAL=3D '} + +def parseCmdArgs(): + parser =3D OptionParser(version=3D"Package Document Generation Tools -= Version 0.1") + parser.add_option('-w', '--workspace', action=3D'store', type=3D'strin= g', dest=3D'WorkspacePath', + help=3D'Specify workspace absolute path. For example= : c:\\tianocore') + parser.add_option('-p', '--decfile', action=3D'store', dest=3D'Package= Path', + help=3D'Specify the absolute path for package DEC fi= le. For example: c:\\tianocore\\MdePkg\\MdePkg.dec') + parser.add_option('-x', '--doxygen', action=3D'store', dest=3D'Doxygen= Path', + help=3D'Specify the absolute path of doxygen tools i= nstallation. For example: C:\\Program Files\\doxygen\bin\doxygen.exe') + parser.add_option('-o', '--output', action=3D'store', dest=3D'OutputPa= th', + help=3D'Specify the document output path. For exampl= e: c:\\docoutput') + parser.add_option('-a', '--arch', action=3D'store', dest=3D'Arch', cho= ices=3DgArchMarcoDict.keys(), + help=3D'Specify the architecture used in preprocess = package\'s source. For example: -a IA32_MSFT') + parser.add_option('-m', '--mode', action=3D'store', dest=3D'DocumentMo= de', choices=3D['CHM', 'HTML'], + help=3D'Specify the document mode from : CHM or HTML= ') + parser.add_option('-i', '--includeonly', action=3D'store_true', dest= =3D'IncludeOnly', + help=3D'Only generate document for package\'s public= interfaces produced by include folder. ') + parser.add_option('-c', '--htmlworkshop', dest=3D'HtmlWorkshopPath', + help=3D'Specify the absolute path for Microsoft HTML= Workshop\'s hhc.exe file. For example: C:\\Program Files\\HTML Help Worksh= op\\hhc.exe') + (options, args) =3D parser.parse_args() + + # validate the options + errors =3D [] + if options.WorkspacePath =3D=3D None: + errors.append('- Please specify workspace path via option -w!') + elif not os.path.exists(options.WorkspacePath): + errors.append("- Invalid workspace path %s! The workspace path sho= uld be exist in absolute path!" % options.WorkspacePath) + + if options.PackagePath =3D=3D None: + errors.append('- Please specify package DEC file path via option -= p!') + elif not os.path.exists(options.PackagePath): + errors.append("- Invalid package's DEC file path %s! The DEC path = should be exist in absolute path!" % options.PackagePath) + + default =3D "C:\\Program Files\\doxygen\\bin\\doxygen.exe" + if options.DoxygenPath =3D=3D None: + if os.path.exists(default): + print "Warning: Assume doxygen tool is installed at %s. If not= , please specify via -x" % default + options.DoxygenPath =3D default + else: + errors.append('- Please specify the path of doxygen tool insta= llation via option -x! or install it in default path %s' % default) + elif not os.path.exists(options.DoxygenPath): + errors.append("- Invalid doxygen tool path %s! The doxygen tool pa= th should be exist in absolute path!" % options.DoxygenPath) + + if options.OutputPath !=3D None: + if not os.path.exists(options.OutputPath): + # create output + try: + os.makedirs(options.OutputPath) + except: + errors.append('- Fail to create the output directory %s' %= options.OutputPath) + else: + if options.PackagePath !=3D None and os.path.exists(options.Packag= ePath): + dirpath =3D os.path.dirname(options.PackagePath) + default =3D os.path.join (dirpath, "Document") + print 'Warning: Assume document output at %s. If not, please s= pecify via option -o' % default + options.OutputPath =3D default + if not os.path.exists(default): + try: + os.makedirs(default) + except: + errors.append('- Fail to create default output directo= ry %s! Please specify document output diretory via option -o' % default) + else: + errors.append('- Please specify document output path via optio= n -o!') + + if options.Arch =3D=3D None: + options.Arch =3D 'ALL' + print "Warning: Assume arch is \"ALL\". If not, specify via -a" + + if options.DocumentMode =3D=3D None: + options.DocumentMode =3D "HTML" + print "Warning: Assume document mode is \"HTML\". If not, specify = via -m" + + if options.IncludeOnly =3D=3D None: + options.IncludeOnly =3D False + print "Warning: Assume generate package document for all package\'= s source including publich interfaces and implementation libraries and modu= les." + + if options.DocumentMode.lower() =3D=3D 'chm': + default =3D "C:\\Program Files\\HTML Help Workshop\\hhc.exe" + if options.HtmlWorkshopPath =3D=3D None: + if os.path.exists(default): + print 'Warning: Assume the installation path of Microsoft = HTML Workshop is %s. If not, specify via option -c.' % default + options.HtmlWorkshopPath =3D default + else: + errors.append('- Please specify the installation path of M= icrosoft HTML Workshop via option -c!') + elif not os.path.exists(options.HtmlWorkshopPath): + errors.append('- The installation path of Microsoft HTML Works= hop %s does not exists. ' % options.HtmlWorkshopPath) + + if len(errors) !=3D 0: + print '\n' + parser.error('Fail to start due to following reasons: \n%s' %'\n'.= join(errors)) + return (options.WorkspacePath, options.PackagePath, options.DoxygenPat= h, options.OutputPath, + options.Arch, options.DocumentMode, options.IncludeOnly, optio= ns.HtmlWorkshopPath) + +def createPackageObject(wsPath, pkgPath): + try: + pkgObj =3D baseobject.Package(None, wsPath) + pkgObj.Load(pkgPath) + except: + logging.getLogger().error ('Fail to create package object!') + return None + + return pkgObj + +def callbackLogMessage(msg, level): + print msg.strip() + +def callbackCreateDoxygenProcess(doxPath, configPath): + if sys.platform =3D=3D 'win32': + cmd =3D '"%s" %s' % (doxPath, configPath) + else: + cmd =3D '%s %s' % (doxPath, configPath) + print cmd + subprocess.call(cmd, shell=3DTrue) + + +def DocumentFixup(outPath, arch): + # find BASE_LIBRARY_JUMP_BUFFER structure reference page + + print '\n >>> Start fixup document \n' + + for root, dirs, files in os.walk(outPath): + for dir in dirs: + if dir.lower() in ['.svn', '_svn', 'cvs']: + dirs.remove(dir) + for file in files: + if not file.lower().endswith('.html'): continue + fullpath =3D os.path.join(outPath, root, file) + try: + f =3D open(fullpath, 'r') + text =3D f.read() + f.close() + except: + logging.getLogger().error('\nFail to open file %s\n' % ful= lpath) + continue + if arch.lower() =3D=3D 'all': + if text.find('BASE_LIBRARY_JUMP_BUFFER Struct Reference') = !=3D -1: + FixPageBASE_LIBRARY_JUMP_BUFFER(fullpath, text) + if text.find('MdePkg/Include/Library/BaseLib.h File Refere= nce') !=3D -1: + FixPageBaseLib(fullpath, text) + if text.find('IA32_IDT_GATE_DESCRIPTOR Union Reference') != =3D -1: + FixPageIA32_IDT_GATE_DESCRIPTOR(fullpath, text) + if text.find('MdePkg/Include/Library/UefiDriverEntryPoint.h Fi= le Reference') !=3D -1: + FixPageUefiDriverEntryPoint(fullpath, text) + if text.find('MdePkg/Include/Library/UefiApplicationEntryPoint= .h File Reference') !=3D -1: + FixPageUefiApplicationEntryPoint(fullpath, text) + + print ' >>> Finish all document fixing up! \n' + +def FixPageBaseLib(path, text): + print ' >>> Fixup BaseLib file page at file %s \n' % path + lines =3D text.split('\n') + lastBaseJumpIndex =3D -1 + lastIdtGateDescriptor =3D -1 + for index in range(len(lines) - 1, -1, -1): + line =3D lines[index] + if line.strip() =3D=3D '#define BASE_LIBRARY= _JUMP_BUFFER_ALIGNMENT   4 ': + lines[index] =3D '#define BASE_LIBRARY_J= UMP_BUFFER_ALIGNMENT   4 [IA32] ' + if line.strip() =3D=3D '#define BASE_LIBRARY= _JUMP_BUFFER_ALIGNMENT   0x10 ': + lines[index] =3D '#define BASE_LIBRARY_J= UMP_BUFFER_ALIGNMENT   0x10 [IPF] ' + if line.strip() =3D=3D '#define BASE_LIBRARY= _JUMP_BUFFER_ALIGNMENT   8 ': + lines[index] =3D '#define BASE_LIBRARY_J= UMP_BUFFER_ALIGNMENT   9 [EBC, x64] ' + if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT  &n= bsp;4') !=3D -1: + lines[index] =3D lines[index].replace('BASE_LIBRARY_JUMP_BUFFE= R_ALIGNMENT   4', + 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT&n= bsp;  4 [IA32]') + if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT  &n= bsp;0x10') !=3D -1: + lines[index] =3D lines[index].replace('BASE_LIBRARY_JUMP_BUFFE= R_ALIGNMENT   0x10', + 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT&n= bsp;  0x10 [IPF]') + if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT  &n= bsp;8') !=3D -1: + lines[index] =3D lines[index].replace('BASE_LIBRARY_JUMP_BUFFE= R_ALIGNMENT   8', + 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT&n= bsp;  8 [x64, EBC]') + if line.find('>BASE_LIBRARY_JUMP_BUFFER') !=3D -1: + if lastBaseJumpIndex !=3D -1: + del lines[lastBaseJumpIndex] + lastBaseJumpIndex =3D index + if line.find('>IA32_IDT_GATE_DESCRIPTOR') !=3D -1: + if lastIdtGateDescriptor !=3D -1: + del lines[lastIdtGateDescriptor] + lastIdtGateDescriptor =3D index + try: + f =3D open(path, 'w') + f.write('\n'.join(lines)) + f.close() + except: + logging.getLogger().error(" <<< Fail to fixup file %s\n" % pat= h) + return + print " <<< Finish to fixup file %s\n" % path + +def FixPageIA32_IDT_GATE_DESCRIPTOR(path, text): + print ' >>> Fixup structure reference IA32_IDT_GATE_DESCRIPTOR at f= ile %s \n' % path + lines =3D text.split('\n') + for index in range(len(lines) - 1, -1, -1): + line =3D lines[index].strip() + if line.find('struct {') !=3D -1 and lines[index - 2].find('>= Uint64') !=3D -1: + lines.insert(index, '

Data Fields= For X64

') + if line.find('struct {') !=3D -1 and lines[index - 1].find('D= ata Fields') !=3D -1: + lines.insert(index, '

Data Fields= For IA32

') + try: + f =3D open(path, 'w') + f.write('\n'.join(lines)) + f.close() + except: + logging.getLogger().error(" <<< Fail to fixup file %s\n" % pat= h) + return + print " <<< Finish to fixup file %s\n" % path + +def FixPageBASE_LIBRARY_JUMP_BUFFER(path, text): + print ' >>> Fixup structure reference BASE_LIBRARY_JUMP_BUFFER at f= ile %s \n' % path + lines =3D text.split('\n') + bInDetail =3D True + bNeedRemove =3D False + for index in range(len(lines) - 1, -1, -1): + line =3D lines[index] + if line.find('Detailed Description') !=3D -1: + bInDetail =3D False + if line.startswith('EBC context buffer used by') and lines[index -= 1].startswith('x64 context buffer'): + lines[index] =3D "IA32/IPF/X64/" + line + bNeedRemove =3D True + if line.startswith("x64 context buffer") or line.startswith('IPF c= ontext buffer used by') or \ + line.startswith('IA32 context buffer used by'): + if bNeedRemove: + lines.remove(line) + if line.find('>R0') !=3D -1 and not bInDetail: + if lines[index - 1] !=3D '

Data F= ields For EBC

': + lines.insert(index, '

Data Fi= elds For EBC

') + if line.find('>Rbx') !=3D -1 and not bInDetail: + if lines[index - 1] !=3D '

Data F= ields For X64

': + lines.insert(index, '

Data Fi= elds For X64

') + if line.find('>F2') !=3D -1 and not bInDetail: + if lines[index - 1] !=3D '

Data F= ields For IPF

': + lines.insert(index, '

Data Fi= elds For IPF

') + if line.find('>Ebx') !=3D -1 and not bInDetail: + if lines[index - 1] !=3D '

Data F= ields For IA32

': + lines.insert(index, '

Data Fi= elds For IA32

') + try: + f =3D open(path, 'w') + f.write('\n'.join(lines)) + f.close() + except: + logging.getLogger().error(" <<< Fail to fixup file %s" % path) + return + print " <<< Finish to fixup file %s\n" % path + +def FixPageUefiDriverEntryPoint(path, text): + print ' >>> Fixup file reference MdePkg/Include/Library/UefiDriverE= ntryPoint.h at file %s \n' % path + lines =3D text.split('\n') + bInModuleEntry =3D False + bInEfiMain =3D False + ModuleEntryDlCount =3D 0 + ModuleEntryDelStart =3D 0 + ModuleEntryDelEnd =3D 0 + EfiMainDlCount =3D 0 + EfiMainDelStart =3D 0 + EfiMainDelEnd =3D 0 + + for index in range(len(lines)): + line =3D lines[index].strip() + if line.find('EFI_STATUS EFIAPI _ModuleEntryPoint ') !=3D -1: + bInModuleEntry =3D True + if line.find('EFI_STATUS EFIAPI EfiMain ') !=3D= -1: + bInEfiMain =3D True + if line.startswith('

References '): + ModuleEntryDlCount =3D ModuleEntryDlCount + 1 + if ModuleEntryDlCount =3D=3D 1: + ModuleEntryDelStart =3D index + 1 + if bInEfiMain: + if line.startswith(''): + EfiMainDlCount =3D EfiMainDlCount + 1 + if EfiMainDlCount =3D=3D 1: + EfiMainDelStart =3D index + 1 + + if EfiMainDelEnd > EfiMainDelStart: + for index in range(EfiMainDelEnd, EfiMainDelStart, -1): + del lines[index] + if ModuleEntryDelEnd > ModuleEntryDelStart: + for index in range(ModuleEntryDelEnd, ModuleEntryDelStart, -1): + del lines[index] + + try: + f =3D open(path, 'w') + f.write('\n'.join(lines)) + f.close() + except: + logging.getLogger().error(" <<< Fail to fixup file %s" % path) + return + print " <<< Finish to fixup file %s\n" % path + + +def FixPageUefiApplicationEntryPoint(path, text): + print ' >>> Fixup file reference MdePkg/Include/Library/UefiApplica= tionEntryPoint.h at file %s \n' % path + lines =3D text.split('\n') + bInModuleEntry =3D False + bInEfiMain =3D False + ModuleEntryDlCount =3D 0 + ModuleEntryDelStart =3D 0 + ModuleEntryDelEnd =3D 0 + EfiMainDlCount =3D 0 + EfiMainDelStart =3D 0 + EfiMainDelEnd =3D 0 + + for index in range(len(lines)): + line =3D lines[index].strip() + if line.find('EFI_STATUS EFIAPI _ModuleEntryPoint ') !=3D -1: + bInModuleEntry =3D True + if line.find('EFI_STATUS EFIAPI EfiMain ') !=3D= -1: + bInEfiMain =3D True + if line.startswith('

References '): + ModuleEntryDlCount =3D ModuleEntryDlCount + 1 + if ModuleEntryDlCount =3D=3D 1: + ModuleEntryDelStart =3D index + 1 + if bInEfiMain: + if line.startswith(''): + EfiMainDlCount =3D EfiMainDlCount + 1 + if EfiMainDlCount =3D=3D 1: + EfiMainDelStart =3D index + 1 + + if EfiMainDelEnd > EfiMainDelStart: + for index in range(EfiMainDelEnd, EfiMainDelStart, -1): + del lines[index] + if ModuleEntryDelEnd > ModuleEntryDelStart: + for index in range(ModuleEntryDelEnd, ModuleEntryDelStart, -1): + del lines[index] + + try: + f =3D open(path, 'w') + f.write('\n'.join(lines)) + f.close() + except: + logging.getLogger().error(" <<< Fail to fixup file %s" % path) + return + print " <<< Finish to fixup file %s\n" % path + +if __name__ =3D=3D '__main__': + wspath, pkgpath, doxpath, outpath, archtag, docmode, isinc, hwpath =3D= parseCmdArgs() + + # configure logging system + logfilepath =3D os.path.join(outpath, 'log.txt') + logging.basicConfig(format=3D'%(levelname)-8s %(message)s', level=3Dlo= gging.DEBUG) + + # create package model object firstly + pkgObj =3D createPackageObject(wspath, pkgpath) + if pkgObj =3D=3D None: + sys.exit(-1) + + # create doxygen action model + arch =3D None + tooltag =3D None + if archtag.lower() !=3D 'all': + arch =3D archtag.split('_')[0] + tooltag =3D archtag.split('_')[1] + else: + arch =3D 'all' + tooltag =3D 'all' + + # preprocess package and call doxygen + try: + action =3D doxygengen.PackageDocumentAction(doxpath, + hwpath, + outpath, + pkgObj, + docmode, + callbackLogMessage, + arch, + tooltag, + isinc, + True) + action.RegisterCallbackDoxygenProcess(callbackCreateDoxygenProcess) + action.Generate() + except: + message =3D traceback.format_exception(*sys.exc_info()) + logging.getLogger().error('Fail to create doxygen action! \n%s' % = ''.join(message)) + sys.exit(-1) + + DocumentFixup(outpath, arch) + + # generate CHM is necessary + if docmode.lower() =3D=3D 'chm': + indexpath =3D os.path.join(outpath, 'html', 'index.hhp') + if sys.platform =3D=3D 'win32': + cmd =3D '"%s" %s' % (hwpath, indexpath) + else: + cmd =3D '%s %s' % (hwpath, indexpath) + subprocess.call(cmd) + print '\nFinish to generate package document! Please open %s for r= eview' % os.path.join(outpath, 'html', 'index.chm') + else: + print '\nFinish to generate package document! Please open %s for r= eview' % os.path.join(outpath, 'html', 'index.html') diff --git a/BaseTools/Scripts/PackageDocumentTools/packagedocapp.pyw b/Bas= eTools/Scripts/PackageDocumentTools/packagedocapp.pyw new file mode 100644 index 0000000..28f6f9b --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/packagedocapp.pyw @@ -0,0 +1,1066 @@ +## @file +# This file is used to define common string related functions used in pars= ing +# process +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# + +import os, sys, wx, logging + +import wx.stc +import wx.lib.newevent +import wx.lib.agw.genericmessagedialog as GMD +import plugins.EdkPlugins.edk2.model.baseobject as baseobject +import plugins.EdkPlugins.edk2.model.doxygengen as doxygengen + +if hasattr(sys, "frozen"): + appPath =3D os.path.abspath(os.path.dirname(sys.executable)) +else: + appPath =3D os.path.abspath(os.path.dirname(__file__)) + +AppCallBackEvent, EVT_APP_CALLBACK =3D wx.lib.newevent.NewEvent() +LogEvent, EVT_LOG =3D wx.lib.newevent.NewEvent() + +class PackageDocApp(wx.App): + + def OnInit(self): + logfile =3D os.path.join(appPath, 'log.txt') + logging.basicConfig(format=3D'%(name)-8s %(levelname)-8s %(message= )s', + filename=3Dlogfile, level=3Dlogging.ERROR) + + self.SetAppName('Package Doxygen Generate Application') + frame =3D PackageDocMainFrame(None, "Package Document Generation A= pplication!") + self.SetTopWindow(frame) + + frame.Show(True) + + EVT_APP_CALLBACK( self, self.OnAppCallBack) + return True + + def GetLogger(self): + return logging.getLogger('') + + def ForegroundProcess(self, function, args): + wx.PostEvent(self, AppCallBackEvent(callback=3Dfunction, args=3Dar= gs)) + + def OnAppCallBack(self, event): + try: + event.callback(*event.args) + except: + self._logger.exception( 'OnAppCallBack<%s.%s>\n' % + (event.callback.__module__, event.callback.__name__ )) + +class PackageDocMainFrame(wx.Frame): + def __init__(self, parent, title): + wx.Frame.__init__(self, parent, -1, title, size=3D(550, 290), styl= e=3Dwx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.CAPTION|wx.CLOSE_BOX ) + + panel =3D wx.Panel(self) + sizer =3D wx.BoxSizer(wx.VERTICAL) + + subsizer =3D wx.GridBagSizer(5, 10) + subsizer.AddGrowableCol(1) + subsizer.Add(wx.StaticText(panel, -1, "Workspace Location : "), (0= , 0), flag=3Dwx.ALIGN_CENTER_VERTICAL) + self._workspacePathCtrl =3D wx.ComboBox(panel, -1) + list =3D self.GetConfigure("WorkspacePath") + if len(list) !=3D 0: + for item in list: + self._workspacePathCtrl.Append(item) + self._workspacePathCtrl.SetValue(list[len(list) - 1]) + + subsizer.Add(self._workspacePathCtrl, (0, 1), flag=3Dwx.ALIGN_CENT= ER_VERTICAL|wx.EXPAND) + self._workspacePathBt =3D wx.BitmapButton(panel, -1, bitmap=3Dwx.A= rtProvider_GetBitmap(wx.ART_FILE_OPEN)) + subsizer.Add(self._workspacePathBt, (0, 2), flag=3Dwx.ALIGN_CENTER= _VERTICAL) + wx.EVT_BUTTON(self._workspacePathBt, self._workspacePathBt.GetId()= , self.OnBrowsePath) + + subsizer.Add(wx.StaticText(panel, -1, "Package DEC Location : "), = (1, 0), flag=3Dwx.ALIGN_CENTER_VERTICAL|wx.EXPAND) + self._packagePathCtrl =3D wx.ComboBox(panel, -1) + list =3D self.GetConfigure("PackagePath") + if len(list) !=3D 0: + for item in list: + self._packagePathCtrl.Append(item) + self._packagePathCtrl.SetValue(list[len(list) - 1]) + subsizer.Add(self._packagePathCtrl, (1, 1), flag=3Dwx.ALIGN_CENTER= _VERTICAL|wx.EXPAND) + self._packagePathBt =3D wx.BitmapButton(panel, -1, bitmap=3Dwx.Art= Provider_GetBitmap(wx.ART_FILE_OPEN)) + subsizer.Add(self._packagePathBt, (1, 2), flag=3Dwx.ALIGN_CENTER_V= ERTICAL) + wx.EVT_BUTTON(self._packagePathBt, self._packagePathBt.GetId(), se= lf.OnBrowsePath) + + subsizer.Add(wx.StaticText(panel, -1, "Doxygen Tool Location : "),= (2, 0), flag=3Dwx.ALIGN_CENTER_VERTICAL) + self._doxygenPathCtrl =3D wx.TextCtrl(panel, -1) + list =3D self.GetConfigure('DoxygenPath') + if len(list) !=3D 0: + self._doxygenPathCtrl.SetValue(list[0]) + else: + if wx.Platform =3D=3D '__WXMSW__': + self._doxygenPathCtrl.SetValue('C:\\Program Files\\Doxygen= \\bin\\doxygen.exe') + else: + self._doxygenPathCtrl.SetValue('/usr/bin/doxygen') + + self._doxygenPathBt =3D wx.BitmapButton(panel, -1, bitmap=3Dwx.Art= Provider_GetBitmap(wx.ART_FILE_OPEN)) + subsizer.Add(self._doxygenPathCtrl, (2, 1), flag=3Dwx.ALIGN_CENTER= _VERTICAL|wx.EXPAND) + subsizer.Add(self._doxygenPathBt, (2, 2), flag=3Dwx.ALIGN_CENTER_V= ERTICAL) + wx.EVT_BUTTON(self._doxygenPathBt, self._doxygenPathBt.GetId(), se= lf.OnBrowsePath) + + subsizer.Add(wx.StaticText(panel, -1, "CHM Tool Location : "), (3,= 0), flag=3Dwx.ALIGN_CENTER_VERTICAL) + self._chmPathCtrl =3D wx.TextCtrl(panel, -1) + list =3D self.GetConfigure('CHMPath') + if len(list) !=3D 0: + self._chmPathCtrl.SetValue(list[0]) + else: + self._chmPathCtrl.SetValue('C:\\Program Files\\HTML Help Works= hop\\hhc.exe') + + self._chmPathBt =3D wx.BitmapButton(panel, -1, bitmap=3Dwx.ArtProv= ider_GetBitmap(wx.ART_FILE_OPEN)) + subsizer.Add(self._chmPathCtrl, (3, 1), flag=3Dwx.ALIGN_CENTER_VER= TICAL|wx.EXPAND) + subsizer.Add(self._chmPathBt, (3, 2), flag=3Dwx.ALIGN_CENTER_VERTI= CAL) + wx.EVT_BUTTON(self._chmPathBt, self._chmPathBt.GetId(), self.OnBro= wsePath) + + subsizer.Add(wx.StaticText(panel, -1, "Output Location : "), (4, 0= ), flag=3Dwx.ALIGN_CENTER_VERTICAL) + self._outputPathCtrl =3D wx.ComboBox(panel, -1) + list =3D self.GetConfigure("OutputPath") + if len(list) !=3D 0: + for item in list: + self._outputPathCtrl.Append(item) + self._outputPathCtrl.SetValue(list[len(list) - 1]) + + subsizer.Add(self._outputPathCtrl, (4, 1), flag=3Dwx.ALIGN_CENTER_= VERTICAL|wx.EXPAND) + self._outputPathBt =3D wx.BitmapButton(panel, -1, bitmap=3Dwx.ArtP= rovider_GetBitmap(wx.ART_FILE_OPEN)) + subsizer.Add(self._outputPathBt, (4, 2), flag=3Dwx.ALIGN_CENTER_VE= RTICAL|wx.EXPAND) + wx.EVT_BUTTON(self._outputPathBt, self._outputPathBt.GetId(), self= .OnBrowsePath) + + subsizer.Add(wx.StaticText(panel, -1, "Architecture Specified : ")= , (5, 0), flag=3Dwx.ALIGN_CENTER_VERTICAL) + self._archCtrl =3D wx.ComboBox(panel, -1, value=3D'ALL', choices= =3D['ALL', 'IA32/MSFT', 'IA32/GNU', 'X64/INTEL', 'X64/GNU', 'IPF/MSFT', 'IP= F/GNU', 'EBC/INTEL'], + style=3Dwx.CB_READONLY) + self._archCtrl.Bind(wx.EVT_COMBOBOX, self.OnArchtectureSelectChang= ed) + subsizer.Add(self._archCtrl, (5, 1), (1, 2), flag=3Dwx.ALIGN_CENTE= R_VERTICAL|wx.EXPAND) + sizer.Add(subsizer, 0, wx.EXPAND|wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT= , 5) + + sizer6 =3D wx.BoxSizer(wx.HORIZONTAL) + self._modesel =3D wx.RadioBox(panel, -1, 'Generated Document Mode'= , majorDimension=3D2, choices=3D['CHM', 'HTML'], style=3Dwx.RA_SPECIFY_COLS) + self._modesel.SetStringSelection('HTML') + + self._includeonlysel =3D wx.CheckBox(panel, -1, 'Only document pub= lic include') + + sizer6.Add(self._modesel, 0 , wx.EXPAND) + sizer6.Add(self._includeonlysel, 0, wx.EXPAND|wx.LEFT, 5) + + sizer.Add(sizer6, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5) + + self._generateBt =3D wx.Button(panel, -1, "Generate Package Docume= nt!") + self._generateBt.Bind(wx.EVT_BUTTON, self.OnGenerate) + sizer.Add(self._generateBt, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, = 5) + + panel.SetSizer(sizer) + panel.Layout() + panel.SetAutoLayout(True) + self.CenterOnScreen() + + def SaveConfigure(self, name, value): + if value =3D=3DNone or len(value) =3D=3D 0: + return + config =3D wx.ConfigBase_Get() + oldvalues =3D config.Read(name, '').split(';') + if len(oldvalues) >=3D 10: + oldvalues.remove(oldvalues[0]) + if value not in oldvalues: + oldvalues.append(value) + else: + oldvalues.remove(value) + oldvalues.append(value) + + config.Write(name, ';'.join(oldvalues)) + + def GetConfigure(self, name): + config =3D wx.ConfigBase_Get() + values =3D config.Read(name, '').split(';') + list =3D [] + for item in values: + if len(item) !=3D 0: + list.append(item) + return list + + def OnBrowsePath(self, event): + id =3D event.GetId() + editctrl =3D None + startdir =3D '' + isFile =3D False + if id =3D=3D self._packagePathBt.GetId(): + dlgTitle =3D "Choose package path:" + editctrl =3D self._packagePathCtrl + isFile =3D True + if os.path.exists(self.GetWorkspace()): + startdir =3D self.GetWorkspace() + elif id =3D=3D self._workspacePathBt.GetId(): + dlgTitle =3D "Choose workspace path:" + editctrl =3D self._workspacePathCtrl + startdir =3D editctrl.GetValue() + elif id =3D=3D self._doxygenPathBt.GetId(): + isFile =3D True + dlgTitle =3D "Choose doxygen installation path:" + editctrl =3D self._doxygenPathCtrl + startdir =3D editctrl.GetValue() + elif id =3D=3D self._outputPathBt.GetId(): + dlgTitle =3D "Choose document output path:" + editctrl =3D self._outputPathCtrl + if os.path.exists(self.GetWorkspace()): + startdir =3D self.GetWorkspace() + startdir =3D editctrl.GetValue() + elif id =3D=3D self._chmPathBt.GetId(): + isFile =3D True + dlgTitle =3D "Choose installation path for Microsoft HTML work= shop software" + editctrl =3D self._chmPathCtrl + startdir =3D editctrl.GetValue() + else: + return + + if not isFile: + dlg =3D wx.DirDialog(self, dlgTitle, defaultPath=3Dstartdir) + else: + dlg =3D wx.FileDialog(self, dlgTitle, defaultDir=3Dstartdir) + + if dlg.ShowModal() =3D=3D wx.ID_OK: + editctrl.SetValue(dlg.GetPath()) + dlg.Destroy() + + def OnArchtectureSelectChanged(self, event): + str =3D '' + selarch =3D self._archCtrl.GetValue() + if selarch =3D=3D 'ALL': + str +=3D 'MDE_CPU_IA32 MDE_CPU_X64 MDE_CPU_EBC MDE_CPU_IPF _MS= C_EXTENSIONS __GNUC__ __INTEL_COMPILER' + elif selarch =3D=3D 'IA32/MSFT': + str +=3D 'MDE_CPU_IA32 _MSC_EXTENSIONS' + elif selarch =3D=3D 'IA32/GNU': + str +=3D 'MDE_CPU_IA32 __GNUC__' + elif selarch =3D=3D 'X64/MSFT': + str +=3D 'MDE_CPU_X64 _MSC_EXTENSIONS' + elif selarch =3D=3D 'X64/GNU': + str +=3D 'MDE_CPU_X64 __GNUC__' + elif selarch =3D=3D 'IPF/MSFT': + str +=3D 'MDE_CPU_IPF _MSC_EXTENSIONS' + elif selarch =3D=3D 'IPF/GNU': + str +=3D 'MDE_CPU_IPF __GNUC__' + elif selarch =3D=3D 'EBC/INTEL': + str +=3D 'MDE_CPU_EBC __INTEL_COMPILER' + + str +=3D ' ASM_PFX=3D OPTIONAL=3D ' + + def OnMacroText(self, event): + str =3D '' + selarch =3D self._archCtrl.GetValue() + if selarch =3D=3D 'ALL': + str +=3D 'MDE_CPU_IA32 MDE_CPU_X64 MDE_CPU_EBC MDE_CPU_IPF _MS= C_EXTENSIONS __GNUC__ __INTEL_COMPILER' + elif selarch =3D=3D 'IA32/MSFT': + str +=3D 'MDE_CPU_IA32 _MSC_EXTENSIONS' + elif selarch =3D=3D 'IA32/GNU': + str +=3D 'MDE_CPU_IA32 __GNUC__' + elif selarch =3D=3D 'X64/MSFT': + str +=3D 'MDE_CPU_X64 _MSC_EXTENSIONS' + elif selarch =3D=3D 'X64/GNU': + str +=3D 'MDE_CPU_X64 __GNUC__' + elif selarch =3D=3D 'IPF/MSFT': + str +=3D 'MDE_CPU_IPF _MSC_EXTENSIONS' + elif selarch =3D=3D 'IPF/GNU': + str +=3D 'MDE_CPU_IPF __GNUC__' + elif selarch =3D=3D 'EBC/INTEL': + str +=3D 'MDE_CPU_EBC __INTEL_COMPILER' + + str +=3D ' ASM_PFX=3D OPTIONAL=3D ' + + def OnGenerate(self, event): + if not self.CheckInput(): return + + dlg =3D ProgressDialog(self) + dlg.ShowModal() + dlg.Destroy() + + def CheckInput(self): + pPath =3D self.GetPackagePath() + wPath =3D self.GetWorkspace() + dPath =3D self.GetDoxygenToolPath() + cPath =3D self.GetChmToolPath() + oPath =3D self.GetOutputPath() + + if len(wPath) =3D=3D 0 or not os.path.exists(wPath): + self._Error("Please input existing workspace path!") + return False + else: + self.SaveConfigure('WorkspacePath', wPath) + + if len(pPath) =3D=3D 0 or not os.path.exists(pPath) or not pPath.l= ower().endswith('.dec'): + self._Error("Please input existing package file location!") + return False + elif pPath.lower().find(wPath.lower()) =3D=3D -1: + self._Error("Package patch should starts with workspace path, = such as if workspace path is c:\\edk2, package patch could be c:\\edk2\MdeP= kg") + return False + else: + self.SaveConfigure('PackagePath', pPath) + + if len(dPath) =3D=3D 0 or not os.path.exists(dPath): + self._Error("Can not find doxygen tool from path %s! Please do= wnload it from www.stack.nl/~dimitri/doxygen/download.html" % dPath) + return False + else: + self.SaveConfigure('DoxygenPath', dPath) + + if self._modesel.GetStringSelection() =3D=3D 'CHM': + if (len(cPath) =3D=3D 0 or not os.path.exists(cPath)): + self._Error("You select CHM mode to generate document, but= can not find software of Microsoft HTML Help Workshop.\nPlease\ + download it from http://www.microsoft.com/downloads/details.aspx?FamilyID= =3D00535334-c8a6-452f-9aa0-d597d16580cc&displaylang=3Den\n\ +and install!") + return False + else: + self.SaveConfigure('CHMPath', cPath) + + if len(oPath) =3D=3D 0: + self._Error("You must specific document output path") + return False + else: + self.SaveConfigure('OutputPath', oPath) + + if os.path.exists(oPath): + # add checking whether there is old doxygen config file he= re + files =3D os.listdir(oPath) + for file in files: + if os.path.isfile(os.path.join(oPath,file)): + basename, ext =3D os.path.splitext(file) + if ext.lower() =3D=3D '.doxygen_config': + dlg =3D GMD.GenericMessageDialog(self, "Existi= ng doxygen document in output directory will be overwritten\n, Are you sure= ?", + "Info", wx.ICON= _WARNING|wx.YES_NO) + if dlg.ShowModal() =3D=3D wx.ID_YES: + break + else: + return False + else: + try: + os.makedirs(oPath) + except: + self._Error("Fail to create output directory, please s= elect another output directory!") + return False + + return True + + def _Error(self, message): + dlg =3D GMD.GenericMessageDialog(self, message, + "Error", wx.ICON_ERROR|wx.OK) + dlg.ShowModal() + dlg.Destroy() + + def GetWorkspace(self): + return os.path.normpath(self._workspacePathCtrl.GetValue()) + + def GetPackagePath(self): + return os.path.normpath(self._packagePathCtrl.GetValue()) + + def GetOutputPath(self): + return os.path.normpath(self._outputPathCtrl.GetValue()) + + def GetDoxygenToolPath(self): + return os.path.normpath(self._doxygenPathCtrl.GetValue()) + + def GetChmToolPath(self): + return os.path.normpath(self._chmPathCtrl.GetValue()) + + def GetDocumentMode(self): + return self._modesel.GetStringSelection() + + def GetArchitecture(self): + value =3D self._archCtrl.GetValue() + return value.split('/')[0] + + def GetToolTag(self): + value =3D self._archCtrl.GetValue() + if value =3D=3D 'ALL': + return 'ALL' + return value.split('/')[1] + + def GetIsOnlyDocumentInclude(self): + return self._includeonlysel.IsChecked() + +class ProgressDialog(wx.Dialog): + def __init__(self, parent, id=3Dwx.ID_ANY): + title =3D "Generate Document for " + parent.GetPackagePath() + wx.Dialog.__init__(self, parent, id, title=3Dtitle, style=3Dwx.CAP= TION, size=3D(600, 300)) + self.Freeze() + sizer =3D wx.BoxSizer(wx.VERTICAL) + self._textCtrl =3D wx.StaticText(self, -1, "Start launching!") + self._gaugeCtrl =3D wx.Gauge(self, -1, 100, size=3D(-1, 10)) + self._resultCtrl =3D wx.stc.StyledTextCtrl(self, -1) + self._closeBt =3D wx.Button(self, -1, "Close") + self._gotoOuputBt =3D wx.Button(self, -1, "Goto Output") + + # clear all margin + self._resultCtrl.SetMarginWidth(0, 0) + self._resultCtrl.SetMarginWidth(1, 0) + self._resultCtrl.SetMarginWidth(2, 0) + + sizer.Add(self._textCtrl, 0, wx.EXPAND|wx.LEFT|wx.TOP|wx.RIGHT, 5) + sizer.Add(self._gaugeCtrl, 0, wx.EXPAND|wx.LEFT|wx.TOP|wx.RIGHT, 5) + sizer.Add(self._resultCtrl, 1, wx.EXPAND|wx.LEFT|wx.TOP|wx.RIGHT, = 5) + btsizer =3D wx.BoxSizer(wx.HORIZONTAL) + btsizer.Add(self._gotoOuputBt, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.LE= FT|wx.TOP|wx.LEFT|wx.BOTTOM, 5) + btsizer.Add(self._closeBt, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.LEFT|w= x.TOP|wx.LEFT|wx.BOTTOM, 5) + sizer.Add(btsizer, 0, wx.ALIGN_CENTER_HORIZONTAL) + + self.SetSizer(sizer) + self.CenterOnScreen() + self.Thaw() + + self._logger =3D logging.getLogger('') + self._loghandle =3D ResultHandler(self) + logging.getLogger('edk').addHandler(self._loghandle) + logging.getLogger('').addHandler(self._loghandle) + logging.getLogger('app').addHandler(self._loghandle) + + wx.EVT_BUTTON(self._closeBt, self._closeBt.GetId(), self.OnButtonC= lose) + wx.EVT_UPDATE_UI(self, self._closeBt.GetId(), self.OnUpdateCloseBu= tton) + wx.EVT_BUTTON(self._gotoOuputBt, self._gotoOuputBt.GetId(), self.O= nGotoOutput) + EVT_LOG(self, self.OnPostLog) + + self._process =3D None + self._pid =3D None + self._input =3D None + self._output =3D None + self._error =3D None + self._inputThread =3D None + self._errorThread =3D None + self._isBusy =3D True + self._pObj =3D None + + wx.CallAfter(self.GenerateAction) + + def OnUpdateCloseButton(self, event): + self._closeBt.Enable(not self._isBusy) + return True + + def OnButtonClose(self, event): + if self._isBusy: + self._InfoDialog("Please don't close in progressing...") + return + + if self._process !=3D None: + self._process.CloseOutput() + + if self._inputThread: + self._inputThread.Terminate() + if self._errorThread: + self._errorThread.Terminate() + + if self._pid !=3D None: + wx.Process.Kill(self._pid, wx.SIGKILL, wx.KILL_CHILDREN) + + logging.getLogger('edk').removeHandler(self._loghandle) + logging.getLogger('').removeHandler(self._loghandle) + logging.getLogger('app').removeHandler(self._loghandle) + + if self._pObj !=3D None: + self._pObj.Destroy() + + self.EndModal(0) + + def OnGotoOutput(self, event): + output =3D self.GetParent().GetOutputPath() + if os.path.exists(output): + if wx.Platform =3D=3D '__WXMSW__': + os.startfile(self.GetParent().GetOutputPath()) + else: + import webbrowser + webbrowser.open(self.GetParent().GetOutputPath()) + else: + self._ErrorDialog("Output directory does not exist!") + + def _ErrorDialog(self, message): + dlg =3D GMD.GenericMessageDialog(self, message, + "Error", wx.ICON_ERROR|wx.OK) + dlg.ShowModal() + dlg.Destroy() + + def _InfoDialog(self, message): + dlg =3D GMD.GenericMessageDialog(self, message, + "Info", wx.ICON_INFORMATION|wx.OK) + dlg.ShowModal() + dlg.Destroy() + + def _LogStep(self, index, message): + stepstr =3D "Step %d: %s" % (index, message) + self._textCtrl.SetLabel(stepstr) + self.LogMessage(os.linesep + stepstr + os.linesep) + self._gaugeCtrl.SetValue(index * 100 / 6 ) + + def OnPostLog(self, event): + self.LogMessage(event.message) + + def GenerateAction(self): + self._LogStep(1, "Create Package Object Model") + wsPath =3D self.GetParent().GetWorkspace() + pkPath =3D self.GetParent().GetPackagePath()[len(wsPath) + 1:] + + try: + pObj =3D baseobject.Package(None, self.GetParent().GetWorkspac= e()) + pObj.Load(pkPath) + except: + self._ErrorDialog("Fail to create package object model! Please= check log.txt under this application folder!") + self._isBusy =3D False + return + self._pObj =3D pObj + + self.LogMessage(str(pObj.GetPcds())) + + self._LogStep(2, "Preprocess and Generate Doxygen Config File") + try: + action =3D doxygengen.PackageDocumentAction(self.GetParent().G= etDoxygenToolPath(), + self.GetParent().Get= ChmToolPath(), + self.GetParent().Get= OutputPath(), + pObj, + self.GetParent().Get= DocumentMode(), + self.LogMessage, + self.GetParent().Get= Architecture(), + self.GetParent().Get= ToolTag(), + self.GetParent().Get= IsOnlyDocumentInclude(), + True) + except: + self._ErrorDialog("Fail to preprocess! Please check log.txt un= der this application folder!") + self._isBusy =3D False + return + + action.RegisterCallbackDoxygenProcess(self.CreateDoxygeProcess) + + try: + if not action.Generate(): + self._isBusy =3D False + self.LogMessage("Fail to generate package document! Please= check log.txt under this application folder!", 'error') + except: + import traceback + message =3D traceback.format_exception(*sys.exc_info()) + logging.getLogger('').error(''.join(message)) + self._isBusy =3D False + self._ErrorDialog("Fail to generate package document! Please c= heck log.txt under this application folder!") + + def LogMessage(self, message, level=3D'info'): + self._resultCtrl.DocumentEnd() + self._resultCtrl.SetReadOnly(False) + self._resultCtrl.AppendText(message) + self._resultCtrl.Home() + self._resultCtrl.Home() + self._resultCtrl.SetReadOnly(True) + if level =3D=3D 'error': + wx.GetApp().GetLogger().error(message) + + def CreateDoxygeProcess(self, doxPath, configFile): + self._LogStep(3, "Launch Doxygen Tool and Generate Package Documen= t") + + cmd =3D '"%s" %s' % (doxPath, configFile) + try: + self._process =3D DoxygenProcess() + self._process.SetParent(self) + self._process.Redirect() + self._pid =3D wx.Execute(cmd, wx.EXEC_ASYNC, self._process) + self._input =3D self._process.GetInputStream() + self._output =3D self._process.GetOutputStream() + self._error =3D self._process.GetErrorStream() + except: + self._ErrorDialog('Fail to launch doxygen cmd %s! Please check= log.txt under this application folder!' % cmd) + self._isBusy =3D False + return False + + self._inputThread =3D MonitorThread(self._input, self.LogMessage) + self._errorThread =3D MonitorThread(self._error, self.LogMessage) + self._inputThread.start() + self._errorThread.start() + return True + + def OnTerminateDoxygenProcess(self): + if self._inputThread: + self._inputThread.Terminate() + self._inputThread =3D None + if self._errorThread: + self._errorThread.Terminate() + self._errorThread =3D None + + if self._error: + while self._error.CanRead(): + text =3D self._error.read() + self.LogMessage(text) + + if self._input: + while self._input.CanRead(): + text =3D self._input.read() + self.LogMessage(text) + self._process.Detach() + + self._process.CloseOutput() + self._process =3D None + self._pid =3D None + + self.DocumentFixup() + + if self.GetParent().GetDocumentMode().lower() =3D=3D 'chm': + hhcfile =3D os.path.join(self.GetParent().GetOutputPath(), 'ht= ml', 'index.hhc') + hhpfile =3D os.path.join(self.GetParent().GetOutputPath(), 'ht= ml', 'index.hhp') + self.FixDecDoxygenFileLink(hhcfile, None) + if not self.CreateCHMProcess(self.GetParent().GetChmToolPath()= , hhpfile): + self._ErrorDialog("Fail to Create %s process for %s" % (se= lf.GetParent().GetChmToolPath(), hhpfile)) + self._isBusy =3D False + else: + self._LogStep(6, "Finished Document Generation!") + self._isBusy =3D False + indexpath =3D os.path.realpath(os.path.join(self.GetParent().G= etOutputPath(), 'html', 'index.html')) + if wx.Platform =3D=3D '__WXMSW__': + os.startfile(indexpath) + else: + import webbrowser + webbrowser.open(indexpath) + + self._InfoDialog('Success create HTML doxgen document %s' % in= dexpath) + + def CreateCHMProcess(self, chmPath, hhpfile): + self.LogMessage(" >>>>>> Start Microsoft HTML workshop process.= ..Zzz...\n") + cmd =3D '"%s" %s' % (chmPath, hhpfile) + try: + self._process =3D CHMProcess() + self._process.SetParent(self) + self._process.Redirect() + self._pid =3D wx.Execute(cmd, wx.EXEC_ASYNC, self._process) + self._input =3D self._process.GetInputStream() + self._output =3D self._process.GetOutputStream() + self._error =3D self._process.GetErrorStream() + except: + self.LogMessage('\nFail to launch hhp cmd %s!\n' % cmd) + self._isBusy =3D False + return False + self._inputThread =3D MonitorThread(self._input, self.LogMessage) + self._errorThread =3D MonitorThread(self._error, self.LogMessage) + self._inputThread.start() + self._errorThread.start() + return True + + def OnTerminateCHMProcess(self): + if self._inputThread: + self._inputThread.Terminate() + self._inputThread =3D None + if self._errorThread: + self._errorThread.Terminate() + self._errorThread =3D None + + if self._error: + while self._error.CanRead(): + text =3D self._error.read() + self.LogMessage(text) + if self._input: + while self._input.CanRead(): + text =3D self._input.read() + self.LogMessage(text) + self._process.Detach() + + self._process.CloseOutput() + self._process =3D None + self._pid =3D None + self._isBusy =3D False + indexpath =3D os.path.realpath(os.path.join(self.GetParent().GetOu= tputPath(), 'html', 'index.chm')) + if os.path.exists(indexpath): + if wx.Platform =3D=3D '__WXMSW__': + os.startfile(indexpath) + else: + import webbrowser + webbrowser.open(indexpath) + + self._LogStep(6, "Finished Document Generation!") + self.LogMessage('\nSuccess create CHM doxgen document %s\n' % inde= xpath) + self._InfoDialog('Success create CHM doxgen document %s' % indexpa= th) + + def DocumentFixup(self): + # find BASE_LIBRARY_JUMP_BUFFER structure reference page + self._LogStep(4, "Fixup Package Document!") + self.LogMessage('\n >>> Start fixup document \n') + + for root, dirs, files in os.walk(os.path.join(self.GetParent().Get= OutputPath(), 'html')): + for dir in dirs: + if dir.lower() in ['.svn', '_svn', 'cvs']: + dirs.remove(dir) + for file in files: + wx.YieldIfNeeded() + if not file.lower().endswith('.html'): continue + fullpath =3D os.path.join(self.GetParent().GetOutputPath()= , root, file) + try: + f =3D open(fullpath, 'r') + text =3D f.read() + f.close() + except: + self.LogMessage('\nFail to open file %s\n' % fullpath) + continue + if text.find('BASE_LIBRARY_JUMP_BUFFER Struct Reference') = !=3D -1 and self.GetParent().GetArchitecture() =3D=3D 'ALL': + self.FixPageBASE_LIBRARY_JUMP_BUFFER(fullpath, text) + if text.find('MdePkg/Include/Library/BaseLib.h File Refere= nce') !=3D -1 and self.GetParent().GetArchitecture() =3D=3D 'ALL': + self.FixPageBaseLib(fullpath, text) + if text.find('IA32_IDT_GATE_DESCRIPTOR Union Reference') != =3D -1 and self.GetParent().GetArchitecture() =3D=3D 'ALL': + self.FixPageIA32_IDT_GATE_DESCRIPTOR(fullpath, text) + if text.find('MdePkg/Include/Library/UefiDriverEntryPoint.= h File Reference') !=3D -1: + self.FixPageUefiDriverEntryPoint(fullpath, text) + if text.find('MdePkg/Include/Library/UefiApplicationEntryP= oint.h File Reference') !=3D -1: + self.FixPageUefiApplicationEntryPoint(fullpath, text) + if text.lower().find('.s.dox') !=3D -1 or \ + text.lower().find('.asm.dox') !=3D -1 or \ + text.lower().find('.uni.dox') !=3D -1: + self.FixDoxFileLink(fullpath, text) + + self.RemoveFileList() + self.LogMessage(' >>> Finish all document fixing up! \n') + + def RemoveFileList(self): + path_html =3D os.path.join(self.GetParent().GetOutputPath(), "html= ", "tree.html") + path_chm =3D os.path.join(self.GetParent().GetOutputPath(), "html= ", "index.hhc") + if os.path.exists(path_html): + self.LogMessage(' >>>Remove FileList item from generated HT= ML document.\n'); + lines =3D [] + f =3D open (path_html, "r") + lines =3D f.readlines() + f.close() + bfound =3D False + for index in xrange(len(lines)): + if lines[index].find('File List') !=3D -1: + lines[index] =3D "" % lines[index] + break + if bfound: + f =3D open(path_html, "w") + f.write("".join(lines)) + f.close() + else: + self.LogMessage (' !!!Can not found FileList item in HT= ML document!\n') + + if os.path.exists(path_chm): + self.LogMessage(" >>>Warning: Can not remove FileList for C= HM files!\n"); + """ + self.LogMessage(' >>>Remove FileList item from generated CH= M document!\n'); + lines =3D [] + f =3D open (path_chm, "r") + lines =3D f.readlines() + f.close() + bfound =3D False + for index in xrange(len(lines)): + if not bfound: + if lines[index].find('') !=3D -1: + lines[index] =3D '\n' % lines[index].rstrip() + break + if bfound: + f =3D open(path_chm, "w") + f.write("".join(lines)) + f.close() + import time + time.sleep(2) + else: + self.LogMessage(' !!!Can not found the FileList item in = CHM document!') + """ + def FixPageBaseLib(self, path, text): + self.LogMessage(' >>> Fixup BaseLib file page at file %s \n' % = path) + lines =3D text.split('\n') + lastBaseJumpIndex =3D -1 + lastIdtGateDescriptor =3D -1 + for index in range(len(lines) - 1, -1, -1): + line =3D lines[index] + if line.strip() =3D=3D '#define BASE_LIB= RARY_JUMP_BUFFER_ALIGNMENT   4 ': + lines[index] =3D '#define BASE_LIBRA= RY_JUMP_BUFFER_ALIGNMENT   4 [IA32] ' + if line.strip() =3D=3D '#define BASE_LIB= RARY_JUMP_BUFFER_ALIGNMENT   0x10 ': + lines[index] =3D '#define BASE_LIBRA= RY_JUMP_BUFFER_ALIGNMENT   0x10 [IPF] ' + if line.strip() =3D=3D '#define BASE_LIB= RARY_JUMP_BUFFER_ALIGNMENT   8 ': + lines[index] =3D '#define BASE_LIBRA= RY_JUMP_BUFFER_ALIGNMENT   9 [EBC, x64] ' + if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT &nbs= p; 4') !=3D -1: + lines[index] =3D lines[index].replace('BASE_LIBRARY_JUMP_B= UFFER_ALIGNMENT   4', + 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT   4 [IA32]') + if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT &nbs= p; 0x10') !=3D -1: + lines[index] =3D lines[index].replace('BASE_LIBRARY_JUMP_B= UFFER_ALIGNMENT   0x10', + 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT   0x10 [IPF]') + if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT &nbs= p; 8') !=3D -1: + lines[index] =3D lines[index].replace('BASE_LIBRARY_JUMP_B= UFFER_ALIGNMENT   8', + 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT   8 [x64, EBC]') + if line.find('>BASE_LIBRARY_JUMP_BUFFER') !=3D -1: + if lastBaseJumpIndex !=3D -1: + del lines[lastBaseJumpIndex] + lastBaseJumpIndex =3D index + if line.find('>IA32_IDT_GATE_DESCRIPTOR') !=3D -1: + if lastIdtGateDescriptor !=3D -1: + del lines[lastIdtGateDescriptor] + lastIdtGateDescriptor =3D index + try: + f =3D open(path, 'w') + f.write('\n'.join(lines)) + f.close() + except: + self._isBusy =3D False + self.LogMessage(" <<< Fail to fixup file %s\n" % path) + self.LogMessage(" <<< Finish to fixup file %s\n" % path) + + def FixPageIA32_IDT_GATE_DESCRIPTOR(self, path, text): + self.LogMessage(' >>> Fixup structure reference IA32_IDT_GATE_D= ESCRIPTOR at file %s \n' % path) + lines =3D text.split('\n') + for index in range(len(lines) - 1, -1, -1): + line =3D lines[index].strip() + if line.find('struct {') !=3D -1 and lines[index - 2].fin= d('>Uint64') !=3D -1: + lines.insert(index, '

Data Fi= elds For X64

') + if line.find('struct {') !=3D -1 and lines[index - 1].fin= d('Data Fields') !=3D -1: + lines.insert(index, '

Data Fi= elds For IA32

') + try: + f =3D open(path, 'w') + f.write('\n'.join(lines)) + f.close() + except: + self._isBusy =3D False + self.LogMessage(" <<< Fail to fixup file %s\n" % path) + self.LogMessage(" <<< Finish to fixup file %s\n" % path) + + def FixPageBASE_LIBRARY_JUMP_BUFFER(self, path, text): + self.LogMessage(' >>> Fixup structure reference BASE_LIBRARY_JU= MP_BUFFER at file %s \n' % path) + lines =3D text.split('\n') + bInDetail =3D True + bNeedRemove =3D False + for index in range(len(lines) - 1, -1, -1): + line =3D lines[index] + if line.find('Detailed Description') !=3D -1: + bInDetail =3D False + if line.startswith('EBC context buffer used by') and lines[ind= ex - 1].startswith('x64 context buffer'): + lines[index] =3D "IA32/IPF/X64/" + line + bNeedRemove =3D True + if line.startswith("x64 context buffer") or line.startswith('I= PF context buffer used by') or \ + line.startswith('IA32 context buffer used by'): + if bNeedRemove: + lines.remove(line) + if line.find('>R0') !=3D -1 and not bInDetail: + if lines[index - 1] !=3D '

Da= ta Fields For EBC

': + lines.insert(index, '

Dat= a Fields For EBC

') + if line.find('>Rbx') !=3D -1 and not bInDetail: + if lines[index - 1] !=3D '

Da= ta Fields For X64

': + lines.insert(index, '

Dat= a Fields For X64

') + if line.find('>F2') !=3D -1 and not bInDetail: + if lines[index - 1] !=3D '

Da= ta Fields For IPF

': + lines.insert(index, '

Dat= a Fields For IPF

') + if line.find('>Ebx') !=3D -1 and not bInDetail: + if lines[index - 1] !=3D '

Da= ta Fields For IA32

': + lines.insert(index, '

Dat= a Fields For IA32

') + try: + f =3D open(path, 'w') + f.write('\n'.join(lines)) + f.close() + except: + self._isBusy =3D False + self.LogMessage(" <<< Fail to fixup file %s" % path) + self.LogMessage(" <<< Finish to fixup file %s\n" % path) + + def FixPageUefiDriverEntryPoint(self, path, text): + self.LogMessage(' >>> Fixup file reference MdePkg/Include/Libra= ry/UefiDriverEntryPoint.h at file %s \n' % path) + lines =3D text.split('\n') + bInModuleEntry =3D False + bInEfiMain =3D False + ModuleEntryDlCount =3D 0 + ModuleEntryDelStart =3D 0 + ModuleEntryDelEnd =3D 0 + EfiMainDlCount =3D 0 + EfiMainDelStart =3D 0 + EfiMainDelEnd =3D 0 + + for index in range(len(lines)): + line =3D lines[index].strip() + if line.find('EFI_STATUS EFIAPI _ModuleEntryPoint = ') !=3D -1: + bInModuleEntry =3D True + if line.find('EFI_STATUS EFIAPI EfiMain ') = !=3D -1: + bInEfiMain =3D True + if line.startswith('

References '): + ModuleEntryDlCount =3D ModuleEntryDlCount + 1 + if ModuleEntryDlCount =3D=3D 1: + ModuleEntryDelStart =3D index + 1 + if bInEfiMain: + if line.startswith(''): + EfiMainDlCount =3D EfiMainDlCount + 1 + if EfiMainDlCount =3D=3D 1: + EfiMainDelStart =3D index + 1 + + if EfiMainDelEnd > EfiMainDelStart: + for index in range(EfiMainDelEnd, EfiMainDelStart, -1): + del lines[index] + if ModuleEntryDelEnd > ModuleEntryDelStart: + for index in range(ModuleEntryDelEnd, ModuleEntryDelStart, -1): + del lines[index] + + try: + f =3D open(path, 'w') + f.write('\n'.join(lines)) + f.close() + except: + self._isBusy =3D False + self.LogMessage(" <<< Fail to fixup file %s" % path) + self.LogMessage(" <<< Finish to fixup file %s\n" % path) + + def FixPageUefiApplicationEntryPoint(self, path, text): + self.LogMessage(' >>> Fixup file reference MdePkg/Include/Libra= ry/UefiApplicationEntryPoint.h at file %s \n' % path) + lines =3D text.split('\n') + bInModuleEntry =3D False + bInEfiMain =3D False + ModuleEntryDlCount =3D 0 + ModuleEntryDelStart =3D 0 + ModuleEntryDelEnd =3D 0 + EfiMainDlCount =3D 0 + EfiMainDelStart =3D 0 + EfiMainDelEnd =3D 0 + + for index in range(len(lines)): + line =3D lines[index].strip() + if line.find('EFI_STATUS EFIAPI _ModuleEntryPoint = ') !=3D -1: + bInModuleEntry =3D True + if line.find('EFI_STATUS EFIAPI EfiMain ') = !=3D -1: + bInEfiMain =3D True + if line.startswith('

References '): + ModuleEntryDlCount =3D ModuleEntryDlCount + 1 + if ModuleEntryDlCount =3D=3D 1: + ModuleEntryDelStart =3D index + 1 + if bInEfiMain: + if line.startswith(''): + EfiMainDlCount =3D EfiMainDlCount + 1 + if EfiMainDlCount =3D=3D 1: + EfiMainDelStart =3D index + 1 + + if EfiMainDelEnd > EfiMainDelStart: + for index in range(EfiMainDelEnd, EfiMainDelStart, -1): + del lines[index] + if ModuleEntryDelEnd > ModuleEntryDelStart: + for index in range(ModuleEntryDelEnd, ModuleEntryDelStart, -1): + del lines[index] + + try: + f =3D open(path, 'w') + f.write('\n'.join(lines)) + f.close() + except: + self._isBusy =3D False + self.LogMessage(" <<< Fail to fixup file %s" % path) + self.LogMessage(" <<< Finish to fixup file %s\n" % path) + + + def FixDoxFileLink(self, path, text): + self.LogMessage(' >>> Fixup .dox postfix for file %s \n' % path) + try: + fd =3D open(path, 'r') + text =3D fd.read() + fd.close() + except Exception, e: + self.LogMessage (" <<>> Finish to fixup .dox postfix for file %s = \n' % path) + + def FixDecDoxygenFileLink(self, path, text): + self.LogMessage(' >>> Fixup .decdoxygen postfix for file %s \n'= % path) + try: + fd =3D open(path, 'r') + lines =3D fd.readlines() + fd.close() + except Exception, e: + self.LogMessage (" <<>> Finish to fixup .decdoxygen postfix for f= ile %s \n' % path) + +import threading +class MonitorThread(threading.Thread): + def __init__(self, pipe, callback): + threading.Thread.__init__(self) + self._pipe =3D pipe + self._callback =3D callback + self._isCancel =3D False + + def run(self): + while (not self._isCancel): + self._pipe.Peek() + if self._pipe.LastRead() =3D=3D 0: + break + text =3D self._pipe.read() + if len(text.strip()) !=3D 0: + wx.GetApp().ForegroundProcess(self._callback, (text,)) + + def Terminate(self): + self._pipe.flush() + self._isCancel =3D True + +class DoxygenProcess(wx.Process): + def OnTerminate(self, id, status): + self._parent.OnTerminateDoxygenProcess() + + def SetParent(self, parent): + self._parent =3D parent + +class CHMProcess(wx.Process): + def OnTerminate(self, id, status): + self._parent.OnTerminateCHMProcess() + + def SetParent(self, parent): + self._parent =3D parent + +class ResultHandler: + def __init__(self, parent): + self._parent =3D parent + self.level =3D 0 + + def emit(self, record): + self._parent.LogMessage(record) + + def handle(self, record): + wx.PostEvent(self._parent, LogEvent(message=3Drecord.getMessage())) + + def acquire(self): + pass + + def release(self): + pass + +if __name__ =3D=3D '__main__': + app =3D PackageDocApp(redirect=3DFalse) + app.MainLoop() diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/__in= it__.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/__init_= _.py new file mode 100644 index 0000000..3e4ee53 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/__init__.py @@ -0,0 +1,12 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/base= model/__init__.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugi= ns/basemodel/__init__.py new file mode 100644 index 0000000..3e4ee53 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/_= _init__.py @@ -0,0 +1,12 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/base= model/doxygen.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugin= s/basemodel/doxygen.py new file mode 100644 index 0000000..2d0cc9d --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/d= oxygen.py @@ -0,0 +1,449 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# + +import os + +from message import * + +class BaseDoxygeItem: + def __init__(self, name, tag=3D''): + self.mName =3D name + self.mTag =3D tag + self.mDescription =3D '' + self.mText =3D [] + + def AddDescription(self, desc): + self.mDescription =3D '%s%s' % (self.mDescription, desc) + + def __str__(self): + return '\n'.join(self.mText) + + def Generate(self): + """This interface need to be override""" + +class Section(BaseDoxygeItem): + def Generate(self): + """This interface need to be override""" + if len(self.mTag) !=3D 0: + self.mText.append(' \section %s %s' % (self.mName, self.mTag)) + else: + self.mText.append(' \section %s' % self.mName) + + self.mText.append(self.mDescription) + return self.mText + +class Page(BaseDoxygeItem): + def __init__(self, name, tag=3DNone, isSort=3DTrue): + BaseDoxygeItem.__init__(self, name, tag) + self.mSubPages =3D [] + self.mIsMainPage =3D False + self.mSections =3D [] + self.mIsSort =3D isSort + + def GetSubpageCount(self): + return len(self.mSubPages) + + def AddPage(self, subpage): + self.mSubPages.append(subpage) + return subpage + + def AddPages(self, pageArray): + if pageArray =3D=3D None: + return + for page in pageArray: + self.AddPage(page) + + def AddSection(self, section): + self.mSections.append(section) + self.mSections.sort(cmp=3Dlambda x,y: cmp(x.mName.lower(), y.mName= .lower())) + + def Generate(self): + if self.mIsMainPage: + self.mText.append('/** \mainpage %s' % self.mName) + self.mIsSort =3D False + else: + self.mText.append('/** \page %s %s' % (self.mTag, self.mName)) + + if len(self.mDescription) !=3D 0: + self.mText.append(self.mDescription) + endIndex =3D len(self.mText) + + self.mSections.sort() + for sect in self.mSections: + self.mText +=3D sect.Generate() + + endIndex =3D len(self.mText) + + if len(self.mSubPages) !=3D 0: + self.mText.insert(endIndex, "

\section content_index INDEX") + endIndex =3D len(self.mText) + self.mText.insert(endIndex, '

    ') + endIndex +=3D 1 + if self.mIsSort: + self.mSubPages.sort(cmp=3Dlambda x,y: cmp(x.mName.lower(),= y.mName.lower())) + for page in self.mSubPages: + self.mText.insert(endIndex, '
  • \subpage %s \"%s\"
  • '= % (page.mTag, page.mName)) + endIndex +=3D 1 + self.mText +=3D page.Generate() + self.mText.insert(endIndex, '
') + endIndex +=3D 1 + self.mText.insert(endIndex, ' **/') + return self.mText + +class DoxygenFile(Page): + def __init__(self, name, file): + Page.__init__(self, name) + self.mFilename =3D file + self.mIsMainPage =3D True + + def GetFilename(self): + return self.mFilename.replace('/', '\\') + + def Save(self): + str =3D self.Generate() + try: + f =3D open(self.mFilename, 'w') + f.write('\n'.join(str)) + f.close() + except IOError, e: + ErrorMsg ('Fail to write file %s' % self.mFilename) + return False + + return True + +doxygenConfigTemplate =3D """ +DOXYFILE_ENCODING =3D UTF-8 +PROJECT_NAME =3D %(ProjectName)s +PROJECT_NUMBER =3D %(ProjectVersion)s +OUTPUT_DIRECTORY =3D %(OutputDir)s +CREATE_SUBDIRS =3D YES +OUTPUT_LANGUAGE =3D English +BRIEF_MEMBER_DESC =3D YES +REPEAT_BRIEF =3D YES +ABBREVIATE_BRIEF =3D "The $name class " \\ + "The $name widget " \\ + "The $name file " \\ + is \\ + provides \\ + specifies \\ + contains \\ + represents \\ + a \\ + an \\ + the +ALWAYS_DETAILED_SEC =3D NO +INLINE_INHERITED_MEMB =3D NO +FULL_PATH_NAMES =3D YES +STRIP_FROM_PATH =3D %(StripPath)s +STRIP_FROM_INC_PATH =3D +SHORT_NAMES =3D YES +JAVADOC_AUTOBRIEF =3D NO +QT_AUTOBRIEF =3D NO +MULTILINE_CPP_IS_BRIEF =3D NO +DETAILS_AT_TOP =3D YES +INHERIT_DOCS =3D YES +SEPARATE_MEMBER_PAGES =3D NO +TAB_SIZE =3D 1 +ALIASES =3D +OPTIMIZE_OUTPUT_FOR_C =3D YES +OPTIMIZE_OUTPUT_JAVA =3D NO +BUILTIN_STL_SUPPORT =3D NO +CPP_CLI_SUPPORT =3D NO +SIP_SUPPORT =3D NO +DISTRIBUTE_GROUP_DOC =3D YES +SUBGROUPING =3D YES +TYPEDEF_HIDES_STRUCT =3D NO + +EXTRACT_ALL =3D YES +EXTRACT_PRIVATE =3D NO +EXTRACT_STATIC =3D NO +EXTRACT_LOCAL_CLASSES =3D NO +EXTRACT_LOCAL_METHODS =3D NO +EXTRACT_ANON_NSPACES =3D NO +HIDE_UNDOC_MEMBERS =3D NO +HIDE_UNDOC_CLASSES =3D NO +HIDE_FRIEND_COMPOUNDS =3D NO +HIDE_IN_BODY_DOCS =3D NO +INTERNAL_DOCS =3D NO +CASE_SENSE_NAMES =3D NO +HIDE_SCOPE_NAMES =3D NO +SHOW_INCLUDE_FILES =3D NO +INLINE_INFO =3D YES +SORT_MEMBER_DOCS =3D YES +SORT_BRIEF_DOCS =3D NO +SORT_BY_SCOPE_NAME =3D YES +GENERATE_TODOLIST =3D YES +GENERATE_TESTLIST =3D YES +GENERATE_BUGLIST =3D YES +GENERATE_DEPRECATEDLIST=3D YES +ENABLED_SECTIONS =3D +MAX_INITIALIZER_LINES =3D 30 +SHOW_USED_FILES =3D NO +SHOW_DIRECTORIES =3D NO +FILE_VERSION_FILTER =3D + +QUIET =3D NO +WARNINGS =3D YES +WARN_IF_UNDOCUMENTED =3D YES +WARN_IF_DOC_ERROR =3D YES +WARN_NO_PARAMDOC =3D YES +WARN_FORMAT =3D "$file:$line: $text " +WARN_LOGFILE =3D %(WarningFile)s + +INPUT =3D %(FileList)s +INPUT_ENCODING =3D UTF-8 +FILE_PATTERNS =3D %(Pattern)s +RECURSIVE =3D NO +EXCLUDE =3D *.svn +EXCLUDE_SYMLINKS =3D NO +EXCLUDE_PATTERNS =3D .svn +EXCLUDE_SYMBOLS =3D +EXAMPLE_PATH =3D %(ExamplePath)s +EXAMPLE_PATTERNS =3D * +EXAMPLE_RECURSIVE =3D NO +IMAGE_PATH =3D +INPUT_FILTER =3D +FILTER_PATTERNS =3D +FILTER_SOURCE_FILES =3D NO + +SOURCE_BROWSER =3D NO +INLINE_SOURCES =3D NO +STRIP_CODE_COMMENTS =3D YES +REFERENCED_BY_RELATION =3D YES +REFERENCES_RELATION =3D YES +REFERENCES_LINK_SOURCE =3D NO +USE_HTAGS =3D NO +VERBATIM_HEADERS =3D NO + +ALPHABETICAL_INDEX =3D NO +COLS_IN_ALPHA_INDEX =3D 5 +IGNORE_PREFIX =3D + +GENERATE_HTML =3D YES +HTML_OUTPUT =3D html +HTML_FILE_EXTENSION =3D .html +HTML_HEADER =3D +HTML_FOOTER =3D +HTML_STYLESHEET =3D +HTML_ALIGN_MEMBERS =3D YES +GENERATE_HTMLHELP =3D %(WhetherGenerateHtmlHelp)s +HTML_DYNAMIC_SECTIONS =3D NO +CHM_FILE =3D index.chm +HHC_LOCATION =3D +GENERATE_CHI =3D NO +BINARY_TOC =3D NO +TOC_EXPAND =3D NO +DISABLE_INDEX =3D NO +ENUM_VALUES_PER_LINE =3D 4 +GENERATE_TREEVIEW =3D %(WhetherGenerateTreeView)s +TREEVIEW_WIDTH =3D 250 + +GENERATE_LATEX =3D NO +LATEX_OUTPUT =3D latex +LATEX_CMD_NAME =3D latex +MAKEINDEX_CMD_NAME =3D makeindex +COMPACT_LATEX =3D NO +PAPER_TYPE =3D a4wide +EXTRA_PACKAGES =3D +LATEX_HEADER =3D +PDF_HYPERLINKS =3D YES +USE_PDFLATEX =3D YES +LATEX_BATCHMODE =3D NO +LATEX_HIDE_INDICES =3D NO + +GENERATE_RTF =3D NO +RTF_OUTPUT =3D rtf +COMPACT_RTF =3D NO +RTF_HYPERLINKS =3D NO +RTF_STYLESHEET_FILE =3D +RTF_EXTENSIONS_FILE =3D + +GENERATE_MAN =3D NO +MAN_OUTPUT =3D man +MAN_EXTENSION =3D .3 +MAN_LINKS =3D NO + +GENERATE_XML =3D NO +XML_OUTPUT =3D xml +XML_SCHEMA =3D +XML_DTD =3D +XML_PROGRAMLISTING =3D YES + +GENERATE_AUTOGEN_DEF =3D NO + +GENERATE_PERLMOD =3D NO +PERLMOD_LATEX =3D NO +PERLMOD_PRETTY =3D YES +PERLMOD_MAKEVAR_PREFIX =3D + +ENABLE_PREPROCESSING =3D YES +MACRO_EXPANSION =3D YES +EXPAND_ONLY_PREDEF =3D YES +SEARCH_INCLUDES =3D YES +INCLUDE_PATH =3D %(IncludePath)s +INCLUDE_FILE_PATTERNS =3D *.h +PREDEFINED =3D %(PreDefined)s +EXPAND_AS_DEFINED =3D +SKIP_FUNCTION_MACROS =3D NO + +TAGFILES =3D +GENERATE_TAGFILE =3D +ALLEXTERNALS =3D NO +EXTERNAL_GROUPS =3D YES +PERL_PATH =3D /usr/bin/perl + +CLASS_DIAGRAMS =3D NO +MSCGEN_PATH =3D +HIDE_UNDOC_RELATIONS =3D YES +HAVE_DOT =3D NO +CLASS_GRAPH =3D YES +COLLABORATION_GRAPH =3D YES +GROUP_GRAPHS =3D YES +UML_LOOK =3D NO +TEMPLATE_RELATIONS =3D NO +INCLUDE_GRAPH =3D YES +INCLUDED_BY_GRAPH =3D YES +CALL_GRAPH =3D NO +CALLER_GRAPH =3D NO +GRAPHICAL_HIERARCHY =3D YES +DIRECTORY_GRAPH =3D YES +DOT_IMAGE_FORMAT =3D png +DOT_PATH =3D +DOTFILE_DIRS =3D +DOT_GRAPH_MAX_NODES =3D 50 +MAX_DOT_GRAPH_DEPTH =3D 1000 +DOT_TRANSPARENT =3D YES +DOT_MULTI_TARGETS =3D NO +GENERATE_LEGEND =3D YES +DOT_CLEANUP =3D YES + +SEARCHENGINE =3D NO + +""" +class DoxygenConfigFile: + def __init__(self): + self.mProjectName =3D '' + self.mOutputDir =3D '' + self.mFileList =3D [] + self.mIncludeList =3D [] + self.mStripPath =3D '' + self.mExamplePath =3D '' + self.mPattern =3D ['*.c', '*.h', + '*.asm', '*.s', '.nasm', '*.html', '*.dox'] + self.mMode =3D 'HTML' + self.mWarningFile =3D '' + self.mPreDefined =3D [] + self.mProjectVersion =3D 0.1 + + def SetChmMode(self): + self.mMode =3D 'CHM' + + def SetHtmlMode(self): + self.mMode =3D 'HTML' + + def SetProjectName(self, str): + self.mProjectName =3D str + + def SetProjectVersion(self, str): + self.mProjectVersion =3D str + + def SetOutputDir(self, str): + self.mOutputDir =3D str + + def SetStripPath(self, str): + self.mStripPath =3D str + + def SetExamplePath(self, str): + self.mExamplePath =3D str + + def SetWarningFilePath(self, str): + self.mWarningFile =3D str.replace('\\', '/') + + def FileExists(self, path): + if path =3D=3D None: + return False + if len(path) =3D=3D 0: + return False + + for p in self.mFileList: + if path.lower() =3D=3D p.lower(): + return True + + return False + + def AddFile(self, path): + if path =3D=3D None: + return + + if len(path) =3D=3D 0: + return + path =3D path.replace('\\', '/') + if not self.FileExists(path): + self.mFileList.append(path) + + def AddIncludePath(self, path): + path =3D path.replace('\\', '/') + if path not in self.mIncludeList: + self.mIncludeList.append(path) + + def AddPattern(self, pattern): + self.mPattern.append(pattern) + + def AddPreDefined(self, macro): + self.mPreDefined.append(macro) + + def Generate(self, path): + files =3D ' \\\n'.join(self.mFileList) + includes =3D ' \\\n'.join(self.mIncludeList) + patterns =3D ' \\\n'.join(self.mPattern) + if self.mMode.lower() =3D=3D 'html': + sHtmlHelp =3D 'NO' + sTreeView =3D 'YES' + else: + sHtmlHelp =3D 'YES' + sTreeView =3D 'NO' + + text =3D doxygenConfigTemplate % {'ProjectName':self.mProjectName, + 'OutputDir':self.mOutputDir, + 'StripPath':self.mStripPath, + 'ExamplePath':self.mExamplePath, + 'FileList':files, + 'Pattern':patterns, + 'WhetherGenerateHtmlHelp':sHtmlHel= p, + 'WhetherGenerateTreeView':sTreeVie= w, + 'IncludePath':includes, + 'WarningFile':self.mWarningFile, + 'PreDefined':' '.join(self.mPreDef= ined), + 'ProjectVersion':self.mProjectVers= ion} + try: + f =3D open(path, 'w') + f.write(text) + f.close() + except IOError, e: + ErrorMsg ('Fail to generate doxygen config file %s' % path) + return False + + return True + +######################################################################## +# TEST CODE +######################################################################## +if __name__=3D=3D '__main__': + df =3D DoxygenFile('Platform Document', 'm:\tree') + df.AddPage(Page('Module', 'module')) + p =3D df.AddPage(Page('Library', 'library')) + p.AddDescription(desc) + p.AddPage(Page('PCD', 'pcds')) + + df.Generate() + print df diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/base= model/efibinary.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlug= ins/basemodel/efibinary.py new file mode 100644 index 0000000..72beced --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/e= fibinary.py @@ -0,0 +1,611 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# + +import array +import uuid +import re +import os +import logging +import core.pe as pe + +def GetLogger(): + return logging.getLogger('EFI Binary File') + +class EFIBinaryError(Exception): + def __init__(self, message): + Exception.__init__(self) + self._message =3D message + + def GetMessage(self): + return self._message + +class EfiFd(object): + EFI_FV_HEADER_SIZE =3D 0x48 + + def __init__(self): + self._fvs =3D [] + + def Load(self, fd, size): + index =3D fd.tell() + while (index + self.EFI_FV_HEADER_SIZE < size): + fv =3D EfiFv(self) + fv.Load(fd) + self._fvs.append(fv) + index +=3D fv.GetHeader().GetFvLength() + index =3D align(index, 8) + fd.seek(index) + + def GetFvs(self): + return self._fvs + +class EfiFv(object): + FILE_SYSTEM_GUID =3D uuid.UUID('{8c8ce578-8a3d-4f1c-9935-896185c32dd3}= ') + + def __init__(self, parent=3DNone): + self._size =3D 0 + self._filename =3D None + self._fvheader =3D None + self._blockentries =3D [] + self._ffs =3D [] + + # following field is for FV in FD + self._parent =3D parent + self._offset =3D 0 + self._raw =3D array.array('B') + + def Load(self, fd): + self._offset =3D fd.tell() + self._filename =3D fd.name + + # get file header + self._fvheader =3D EfiFirmwareVolumeHeader.Read(fd) + #self._fvheader.Dump() + + self._size =3D self._fvheader.GetFvLength() + + if self._fvheader.GetFileSystemGuid() !=3D self.FILE_SYSTEM_GUID: + fd.seek(self._offset) + self._raw.fromfile(fd, self.GetHeader().GetFvLength()) + return + + # read block map + blockentry =3D BlockMapEntry.Read(fd) + self._blockentries.append(blockentry) + while (blockentry.GetNumberBlocks() !=3D 0 and blockentry.GetLengt= h() !=3D 0): + self._blockentries.append(blockentry) + blockentry =3D BlockMapEntry.Read(fd) + + + if self._fvheader.GetSize() + (len(self._blockentries)) * 8 !=3D \ + self._fvheader.GetHeaderLength(): + raise EFIBinaryError("Volume Header length not consistent with= block map!") + + index =3D align(fd.tell(), 8) + count =3D 0 + while ((index + EfiFfs.FFS_HEADER_SIZE) < self._size): + ffs =3D EfiFfs.Read(fd, self) + if not isValidGuid(ffs.GetNameGuid()): + break + self._ffs.append(ffs) + count +=3D 1 + index =3D align(fd.tell(), 8) + + fd.seek(self._offset) + self._raw.fromfile(fd, self.GetHeader().GetFvLength()) + + def GetFfs(self): + return self._ffs + + def GetHeader(self): + return self._fvheader + + def GetBlockEntries(self): + return self._blockentries + + def GetHeaderRawData(self): + ret =3D [] + ret +=3D self._fvheader.GetRawData() + for block in self._blockentries: + ret +=3D block.GetRawData() + return ret + + def GetOffset(self): + return 0 + + def GetRawData(self): + return self._raw.tolist() + +class BinaryItem(object): + def __init__(self, parent=3DNone): + self._size =3D 0 + self._arr =3D array.array('B') + self._parent =3D parent + + @classmethod + def Read(cls, fd, parent=3DNone): + item =3D cls(parent) + item.fromfile(fd) + return item + + def Load(self, fd): + self.fromfile(fd) + + def GetSize(self): + """should be implemented by inherited class""" + + def fromfile(self, fd): + self._arr.fromfile(fd, self.GetSize()) + + def GetParent(self): + return self._parent + +class EfiFirmwareVolumeHeader(BinaryItem): + def GetSize(self): + return 56 + + def GetSigunature(self): + list =3D self._arr.tolist() + sig =3D '' + for x in list[40:44]: + sig +=3D chr(x) + return sig + + def GetAttribute(self): + return list2int(self._arr.tolist()[44:48]) + + def GetErasePolarity(self): + list =3D self.GetAttrStrings() + if 'EFI_FVB2_ERASE_POLARITY' in list: + return True + return False + + def GetAttrStrings(self): + list =3D [] + value =3D self.GetAttribute() + if (value & 0x01) !=3D 0: + list.append('EFI_FVB2_READ_DISABLED_CAP') + if (value & 0x02) !=3D 0: + list.append('EFI_FVB2_READ_ENABLED_CAP') + if (value & 0x04) !=3D 0: + list.append('EFI_FVB2_READ_STATUS') + if (value & 0x08) !=3D 0: + list.append('EFI_FVB2_WRITE_DISABLED_CAP') + if (value & 0x10) !=3D 0: + list.append('EFI_FVB2_WRITE_ENABLED_CAP') + if (value & 0x20) !=3D 0: + list.append('EFI_FVB2_WRITE_STATUS') + if (value & 0x40) !=3D 0: + list.append('EFI_FVB2_LOCK_CAP') + if (value & 0x80) !=3D 0: + list.append('EFI_FVB2_LOCK_STATUS') + if (value & 0x200) !=3D 0: + list.append('EFI_FVB2_STICKY_WRITE') + if (value & 0x400) !=3D 0: + list.append('EFI_FVB2_MEMORY_MAPPED') + if (value & 0x800) !=3D 0: + list.append('EFI_FVB2_ERASE_POLARITY') + if (value & 0x1000) !=3D 0: + list.append('EFI_FVB2_READ_LOCK_CAP') + if (value & 0x00002000) !=3D 0: + list.append('EFI_FVB2_READ_LOCK_STATUS') + if (value & 0x00004000) !=3D 0: + list.append('EFI_FVB2_WRITE_LOCK_CAP') + if (value & 0x00008000) !=3D 0: + list.append('EFI_FVB2_WRITE_LOCK_STATUS') + + if (value =3D=3D 0): + list.append('EFI_FVB2_ALIGNMENT_1') + if (value & 0x001F0000) =3D=3D 0x00010000: + list.append('EFI_FVB2_ALIGNMENT_2') + if (value & 0x001F0000) =3D=3D 0x00020000: + list.append('EFI_FVB2_ALIGNMENT_4') + if (value & 0x001F0000) =3D=3D 0x00030000: + list.append('EFI_FVB2_ALIGNMENT_8') + if (value & 0x001F0000) =3D=3D 0x00040000: + list.append('EFI_FVB2_ALIGNMENT_16') + if (value & 0x001F0000) =3D=3D 0x00050000: + list.append('EFI_FVB2_ALIGNMENT_32') + if (value & 0x001F0000) =3D=3D 0x00060000: + list.append('EFI_FVB2_ALIGNMENT_64') + if (value & 0x001F0000) =3D=3D 0x00070000: + list.append('EFI_FVB2_ALIGNMENT_128') + if (value & 0x001F0000) =3D=3D 0x00080000: + list.append('EFI_FVB2_ALIGNMENT_256') + if (value & 0x001F0000) =3D=3D 0x00090000: + list.append('EFI_FVB2_ALIGNMENT_512') + if (value & 0x001F0000) =3D=3D 0x000A0000: + list.append('EFI_FVB2_ALIGNMENT_1K') + if (value & 0x001F0000) =3D=3D 0x000B0000: + list.append('EFI_FVB2_ALIGNMENT_2K') + if (value & 0x001F0000) =3D=3D 0x000C0000: + list.append('EFI_FVB2_ALIGNMENT_4K') + if (value & 0x001F0000) =3D=3D 0x000D0000: + list.append('EFI_FVB2_ALIGNMENT_8K') + if (value & 0x001F0000) =3D=3D 0x000E0000: + list.append('EFI_FVB2_ALIGNMENT_16K') + if (value & 0x001F0000) =3D=3D 0x000F0000: + list.append('EFI_FVB2_ALIGNMENT_32K') + if (value & 0x001F0000) =3D=3D 0x00100000: + list.append('EFI_FVB2_ALIGNMENT_64K') + if (value & 0x001F0000) =3D=3D 0x00110000: + list.append('EFI_FVB2_ALIGNMENT_128K') + if (value & 0x001F0000) =3D=3D 0x00120000: + list.append('EFI_FVB2_ALIGNMENT_256K') + if (value & 0x001F0000) =3D=3D 0x00130000: + list.append('EFI_FVB2_ALIGNMENT_512K') + + return list + + def GetHeaderLength(self): + return list2int(self._arr.tolist()[48:50]) + + def Dump(self): + print 'Signature: %s' % self.GetSigunature() + print 'Attribute: 0x%X' % self.GetAttribute() + print 'Header Length: 0x%X' % self.GetHeaderLength() + print 'File system Guid: ', self.GetFileSystemGuid() + print 'Revision: 0x%X' % self.GetRevision() + print 'FvLength: 0x%X' % self.GetFvLength() + + def GetFileSystemGuid(self): + list =3D self._arr.tolist() + return list2guid(list[16:32]) + + def GetRevision(self): + list =3D self._arr.tolist() + return int(list[55]) + + def GetFvLength(self): + list =3D self._arr.tolist() + return list2int(list[32:40]) + + def GetRawData(self): + return self._arr.tolist() + +class BlockMapEntry(BinaryItem): + def GetSize(self): + return 8 + + def GetNumberBlocks(self): + list =3D self._arr.tolist() + return list2int(list[0:4]) + + def GetLength(self): + list =3D self._arr.tolist() + return list2int(list[4:8]) + + def GetRawData(self): + return self._arr.tolist() + + def __str__(self): + return '[BlockEntry] Number =3D 0x%X, length=3D0x%X' % (self.GetNu= mberBlocks(), self.GetLength()) + +class EfiFfs(object): + FFS_HEADER_SIZE =3D 24 + + def __init__(self, parent=3DNone): + self._header =3D None + + # following field is for FFS in FV file. + self._parent =3D parent + self._offset =3D 0 + self._sections =3D [] + + def Load(self, fd): + self._offset =3D align(fd.tell(), 8) + + self._header =3D EfiFfsHeader.Read(fd, self) + + if not isValidGuid(self.GetNameGuid()): + return + + index =3D self._offset + fileend =3D self._offset + self.GetSize() + while (index + EfiSection.EFI_SECTION_HEADER_SIZE < fileend): + section =3D EfiSection(self) + section.Load(fd) + if section.GetSize() =3D=3D 0 and section.GetHeader().GetType(= ) =3D=3D 0: + break + self._sections.append(section) + index =3D fd.tell() + + # rebase file pointer to next ffs file + index =3D self._offset + self._header.GetFfsSize() + index =3D align(index, 8) + fd.seek(index) + + def GetOffset(self): + return self._offset + + def GetSize(self): + return self._header.GetFfsSize() + + @classmethod + def Read(cls, fd, parent=3DNone): + item =3D cls(parent) + item.Load(fd) + return item + + def GetNameGuid(self): + return self._header.GetNameGuid() + + def DumpContent(self): + list =3D self._content.tolist() + line =3D [] + count =3D 0 + for item in list: + if count < 32: + line.append('0x%X' % int(item)) + count +=3D 1 + else: + print ' '.join(line) + count =3D 0 + line =3D [] + line.append('0x%X' % int(item)) + count +=3D 1 + + def GetHeader(self): + return self._header + + def GetParent(self): + return self._parent + + def GetSections(self): + return self._sections + +class EfiFfsHeader(BinaryItem): + ffs_state_map =3D {0x01:'EFI_FILE_HEADER_CONSTRUCTION', + 0x02:'EFI_FILE_HEADER_VALID', + 0x04:'EFI_FILE_DATA_VALID', + 0x08:'EFI_FILE_MARKED_FOR_UPDATE', + 0x10:'EFI_FILE_DELETED', + 0x20:'EFI_FILE_HEADER_INVALID'} + + def GetSize(self): + return 24 + + def GetNameGuid(self): + list =3D self._arr.tolist() + return list2guid(list[0:16]) + + def GetType(self): + list =3D self._arr.tolist() + return int(list[18]) + + + def GetTypeString(self): + value =3D self.GetType() + if value =3D=3D 0x01: + return 'EFI_FV_FILETYPE_RAW' + if value =3D=3D 0x02: + return 'EFI_FV_FILETYPE_FREEFORM' + if value =3D=3D 0x03: + return 'EFI_FV_FILETYPE_SECURITY_CORE' + if value =3D=3D 0x04: + return 'EFI_FV_FILETYPE_PEI_CORE' + if value =3D=3D 0x05: + return 'EFI_FV_FILETYPE_DXE_CORE' + if value =3D=3D 0x06: + return 'EFI_FV_FILETYPE_PEIM' + if value =3D=3D 0x07: + return 'EFI_FV_FILETYPE_DRIVER' + if value =3D=3D 0x08: + return 'EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER' + if value =3D=3D 0x09: + return 'EFI_FV_FILETYPE_APPLICATION' + if value =3D=3D 0x0B: + return 'EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE' + if value =3D=3D 0xc0: + return 'EFI_FV_FILETYPE_OEM_MIN' + if value =3D=3D 0xdf: + return 'EFI_FV_FILETYPE_OEM_MAX' + if value =3D=3D 0xe0: + return 'EFI_FV_FILETYPE_DEBUG_MIN' + if value =3D=3D 0xef: + return 'EFI_FV_FILETYPE_DEBUG_MAX' + if value =3D=3D 0xf0: + return 'EFI_FV_FILETYPE_FFS_PAD' + if value =3D=3D 0xff: + return 'EFI_FV_FILETYPE_FFS_MAX' + return 'Unknown FFS Type' + + def GetAttributes(self): + list =3D self._arr.tolist() + return int(list[19]) + + def GetFfsSize(self): + list =3D self._arr.tolist() + return list2int(list[20:23]) + + def GetState(self): + list =3D self._arr.tolist() + state =3D int(list[23]) + polarity =3D self.GetParent().GetParent().GetHeader().GetErasePola= rity() + if polarity: + state =3D (~state) & 0xFF + HighestBit =3D 0x80 + while (HighestBit !=3D 0) and (HighestBit & state) =3D=3D 0: + HighestBit =3D HighestBit >> 1 + return HighestBit + + def GetStateString(self): + state =3D self.GetState() + if state in self.ffs_state_map.keys(): + return self.ffs_state_map[state] + return 'Unknown Ffs State' + + def Dump(self): + print "FFS name: ", self.GetNameGuid() + print "FFS type: ", self.GetType() + print "FFS attr: 0x%X" % self.GetAttributes() + print "FFS size: 0x%X" % self.GetFfsSize() + print "FFS state: 0x%X" % self.GetState() + + def GetRawData(self): + return self._arr.tolist() + + +class EfiSection(object): + EFI_SECTION_HEADER_SIZE =3D 4 + + def __init__(self, parent=3DNone): + self._size =3D 0 + self._parent =3D parent + self._offset =3D 0 + self._contents =3D array.array('B') + + def Load(self, fd): + self._offset =3D align(fd.tell(), 4) + + self._header =3D EfiSectionHeader.Read(fd, self) + + if self._header.GetTypeString() =3D=3D "EFI_SECTION_PE32": + pefile =3D pe.PEFile(self) + pefile.Load(fd, self.GetContentSize()) + + fd.seek(self._offset) + self._contents.fromfile(fd, self.GetContentSize()) + + # rebase file pointer to next section + index =3D self._offset + self.GetSize() + index =3D align(index, 4) + fd.seek(index) + + def GetContentSize(self): + return self.GetSize() - self.EFI_SECTION_HEADER_SIZE + + def GetContent(self): + return self._contents.tolist() + + def GetSize(self): + return self._header.GetSectionSize() + + def GetHeader(self): + return self._header + + def GetSectionOffset(self): + return self._offset + self.EFI_SECTION_HEADER_SIZE + +class EfiSectionHeader(BinaryItem): + section_type_map =3D {0x01: 'EFI_SECTION_COMPRESSION', + 0x02: 'EFI_SECTION_GUID_DEFINED', + 0x10: 'EFI_SECTION_PE32', + 0x11: 'EFI_SECTION_PIC', + 0x12: 'EFI_SECTION_TE', + 0x13: 'EFI_SECTION_DXE_DEPEX', + 0x14: 'EFI_SECTION_VERSION', + 0x15: 'EFI_SECTION_USER_INTERFACE', + 0x16: 'EFI_SECTION_COMPATIBILITY16', + 0x17: 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE', + 0x18: 'EFI_SECTION_FREEFORM_SUBTYPE_GUID', + 0x19: 'EFI_SECTION_RAW', + 0x1B: 'EFI_SECTION_PEI_DEPEX'} + def GetSize(self): + return 4 + + def GetSectionSize(self): + list =3D self._arr.tolist() + return list2int(list[0:3]) + + def GetType(self): + list =3D self._arr.tolist() + return int(list[3]) + + def GetTypeString(self): + type =3D self.GetType() + if type not in self.section_type_map.keys(): + return 'Unknown Section Type' + return self.section_type_map[type] + + def Dump(self): + print 'size =3D 0x%X' % self.GetSectionSize() + print 'type =3D 0x%X' % self.GetType() + + + +rMapEntry =3D re.compile('^(\w+)[ \(\w\)]* \(BaseAddress=3D([0-9a-fA-F]+),= EntryPoint=3D([0-9a-fA-F]+), GUID=3D([0-9a-fA-F\-]+)') +class EfiFvMapFile(object): + def __init__(self): + self._mapentries =3D {} + + def Load(self, path): + if not os.path.exists(path): + return False + + try: + file =3D open(path, 'r') + lines =3D file.readlines() + file.close() + except: + return False + + for line in lines: + if line[0] !=3D ' ': + # new entry + ret =3D rMapEntry.match(line) + if ret !=3D None: + name =3D ret.groups()[0] + baseaddr =3D int(ret.groups()[1], 16) + entry =3D int(ret.groups()[2], 16) + guidstr =3D '{' + ret.groups()[3] + '}' + guid =3D uuid.UUID(guidstr) + self._mapentries[guid] =3D EfiFvMapFileEntry(name, bas= eaddr, entry, guid) + return True + + def GetEntry(self, guid): + if guid in self._mapentries.keys(): + return self._mapentries[guid] + return None + +class EfiFvMapFileEntry(object): + def __init__(self, name, baseaddr, entry, guid): + self._name =3D name + self._baseaddr =3D baseaddr + self._entry =3D entry + self._guid =3D guid + + def GetName(self): + return self._name + + def GetBaseAddress(self): + return self._baseaddr + + def GetEntryPoint(self): + return self._entry + +def list2guid(list): + val1 =3D list2int(list[0:4]) + val2 =3D list2int(list[4:6]) + val3 =3D list2int(list[6:8]) + val4 =3D 0 + for item in list[8:16]: + val4 =3D (val4 << 8) | int(item) + + val =3D val1 << 12 * 8 | val2 << 10 * 8 | val3 << 8 * 8 | val4 + guid =3D uuid.UUID(int=3Dval) + return guid + +def list2int(list): + val =3D 0 + for index in range(len(list) - 1, -1, -1): + val =3D (val << 8) | int(list[index]) + return val + +def align(value, alignment): + return (value + ((alignment - value) & (alignment - 1))) + +gInvalidGuid =3D uuid.UUID(int=3D0xffffffffffffffffffffffffffffffff) +def isValidGuid(guid): + if guid =3D=3D gInvalidGuid: + return False + return True diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/base= model/ini.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/ba= semodel/ini.py new file mode 100644 index 0000000..515e7a4 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/i= ni.py @@ -0,0 +1,480 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# + +from message import * +import re +import os + +section_re =3D re.compile(r'^\[([\w., "]+)\]') + +class BaseINIFile(object): + _objs =3D {} + def __new__(cls, *args, **kwargs): + """Maintain only a single instance of this object + @return: instance of this class + + """ + if len(args) =3D=3D 0: return object.__new__(cls, *args, **kwargs) + filename =3D args[0] + parent =3D None + if len(args) > 1: + parent =3D args[1] + + key =3D os.path.normpath(filename) + if key not in cls._objs.keys(): + cls._objs[key] =3D object.__new__(cls, *args, **kwargs) + + if parent !=3D None: + cls._objs[key].AddParent(parent) + + return cls._objs[key] + + def __init__(self, filename=3DNone, parent=3DNone): + self._lines =3D [] + self._sections =3D {} + self._filename =3D filename + self._globals =3D [] + self._isModify =3D True + + def AddParent(self, parent): + if parent =3D=3D None: return + if not hasattr(self, "_parents"): + self._parents =3D [] + + if parent in self._parents: + ErrorMsg("Duplicate parent is found for INI file %s" % self._f= ilename) + return + self._parents.append(parent) + + def GetFilename(self): + return os.path.normpath(self._filename) + + def IsModified(self): + return self._isModify + + def Modify(self, modify=3DTrue, obj=3DNone): + if modify =3D=3D self._isModify: return + self._isModify =3D modify + if modify: + for parent in self._parents: + parent.Modify(True, self) + + def _ReadLines(self, filename): + # + # try to open file + # + if not os.path.exists(filename): + return False + + try: + handle =3D open(filename, 'r') + self._lines =3D handle.readlines() + handle.close() + except: + raise EdkException("Fail to open file %s" % filename) + + return True + + def GetSectionInstance(self, parent, name, isCombined=3DFalse): + return BaseINISection(parent, name, isCombined) + + def GetSectionByName(self, name): + arr =3D [] + for key in self._sections.keys(): + if '.private' in key: + continue + for item in self._sections[key]: + if item.GetBaseName().lower().find(name.lower()) !=3D -1: + arr.append(item) + return arr + + def GetSectionObjectsByName(self, name): + arr =3D [] + sects =3D self.GetSectionByName(name) + for sect in sects: + for obj in sect.GetObjects(): + arr.append(obj) + return arr + + def Parse(self): + if not self._isModify: return True + if not self._ReadLines(self._filename): return False + + sObjs =3D [] + inGlobal =3D True + # process line + for index in range(len(self._lines)): + templine =3D self._lines[index].strip() + # skip comments + if len(templine) =3D=3D 0: continue + if re.match("^\[=3D*\]", templine) or re.match("^#", templine)= or \ + re.match("\*+/", templine): + continue + + m =3D section_re.match(templine) + if m!=3D None: # found a section + inGlobal =3D False + # Finish the latest section first + if len(sObjs) !=3D 0: + for sObj in sObjs: + sObj._end =3D index - 1 + if not sObj.Parse(): + ErrorMsg("Fail to parse section %s" % sObj.Get= BaseName(), + self._filename, + sObj._start) + + # start new section + sname_arr =3D m.groups()[0].split(',') + sObjs =3D [] + for name in sname_arr: + sObj =3D self.GetSectionInstance(self, name, (len(snam= e_arr) > 1)) + sObj._start =3D index + sObjs.append(sObj) + if not self._sections.has_key(name.lower()): + self._sections[name.lower()] =3D [sObj] + else: + self._sections[name.lower()].append(sObj) + elif inGlobal: # not start any section and find global object + gObj =3D BaseINIGlobalObject(self) + gObj._start =3D index + gObj.Parse() + self._globals.append(gObj) + + # Finish the last section + if len(sObjs) !=3D 0: + for sObj in sObjs: + sObj._end =3D index + if not sObj.Parse(): + ErrorMsg("Fail to parse section %s" % sObj.GetBaseName= (), + self._filename, + sObj._start) + + self._isModify =3D False + return True + + def Destroy(self, parent): + + # check referenced parent + if parent !=3D None: + assert parent in self._parents, "when destory ini object, can = not found parent reference!" + self._parents.remove(parent) + + if len(self._parents) !=3D 0: return + + for sects in self._sections.values(): + for sect in sects: + sect.Destroy() + + # dereference from _objs array + assert self.GetFilename() in self._objs.keys(), "When destroy ini = object, can not find obj reference!" + assert self in self._objs.values(), "When destroy ini object, can = not find obj reference!" + del self._objs[self.GetFilename()] + + # dereference self + self.Clear() + + def GetDefine(self, name): + sects =3D self.GetSectionByName('Defines') + for sect in sects: + for obj in sect.GetObjects(): + line =3D obj.GetLineByOffset(obj._start).split('#')[0].str= ip() + arr =3D line.split('=3D') + if arr[0].strip().lower() =3D=3D name.strip().lower(): + return arr[1].strip() + return None + + def Clear(self): + for sects in self._sections.values(): + for sect in sects: + del sect + self._sections.clear() + for gObj in self._globals: + del gObj + + del self._globals[:] + del self._lines[:] + + def Reload(self): + self.Clear() + ret =3D self.Parse() + if ret: + self._isModify =3D False + return ret + + def AddNewSection(self, sectName): + if sectName.lower() in self._sections.keys(): + ErrorMsg('Section %s can not be created for conflict with exis= ting section') + return None + + sectionObj =3D self.GetSectionInstance(self, sectName) + sectionObj._start =3D len(self._lines) + sectionObj._end =3D len(self._lines) + 1 + self._lines.append('[%s]\n' % sectName) + self._lines.append('\n\n') + self._sections[sectName.lower()] =3D sectionObj + return sectionObj + + def CopySectionsByName(self, oldDscObj, nameStr): + sects =3D oldDscObj.GetSectionByName(nameStr) + for sect in sects: + sectObj =3D self.AddNewSection(sect.GetName()) + sectObj.Copy(sect) + + def __str__(self): + return ''.join(self._lines) + + ## Get file header's comment from basic INI file. + # The file comments has two style: + # 1) #/** @file + # 2) ## @file + # + def GetFileHeader(self): + desc =3D [] + lineArr =3D self._lines + inHeader =3D False + for num in range(len(self._lines)): + line =3D lineArr[num].strip() + if not inHeader and (line.startswith("#/**") or line.startswit= h("##")) and \ + line.find("@file") !=3D -1: + inHeader =3D True + continue + if inHeader and (line.startswith("#**/") or line.startswith('#= #')): + inHeader =3D False + break + if inHeader: + prefixIndex =3D line.find('#') + if prefixIndex =3D=3D -1: + desc.append(line) + else: + desc.append(line[prefixIndex + 1:]) + return '
\n'.join(desc) + +class BaseINISection(object): + def __init__(self, parent, name, isCombined=3DFalse): + self._parent =3D parent + self._name =3D name + self._isCombined =3D isCombined + self._start =3D 0 + self._end =3D 0 + self._objs =3D [] + + def __del__(self): + for obj in self._objs: + del obj + del self._objs[:] + + def GetName(self): + return self._name + + def GetObjects(self): + return self._objs + + def GetParent(self): + return self._parent + + def GetStartLinenumber(self): + return self._start + + def GetEndLinenumber(self): + return self._end + + def GetLine(self, linenumber): + return self._parent._lines[linenumber] + + def GetFilename(self): + return self._parent.GetFilename() + + def GetSectionINIObject(self, parent): + return BaseINISectionObject(parent) + + def Parse(self): + # skip first line in section, it is used by section name + visit =3D self._start + 1 + iniObj =3D None + while (visit <=3D self._end): + line =3D self.GetLine(visit).strip() + if re.match("^\[=3D*\]", line) or re.match("^#", line) or len(= line) =3D=3D 0: + visit +=3D 1 + continue + line =3D line.split('#')[0].strip() + if iniObj !=3D None: + if line.endswith('}'): + iniObj._end =3D visit - self._start + if not iniObj.Parse(): + ErrorMsg("Fail to parse ini object", + self.GetFilename(), + iniObj.GetStartLinenumber()) + else: + self._objs.append(iniObj) + iniObj =3D None + else: + iniObj =3D self.GetSectionINIObject(self) + iniObj._start =3D visit - self._start + if not line.endswith('{'): + iniObj._end =3D visit - self._start + if not iniObj.Parse(): + ErrorMsg("Fail to parse ini object", + self.GetFilename(), + iniObj.GetStartLinenumber()) + else: + self._objs.append(iniObj) + iniObj =3D None + visit +=3D 1 + return True + + def Destroy(self): + for obj in self._objs: + obj.Destroy() + + def GetBaseName(self): + return self._name + + def AddLine(self, line): + end =3D self.GetEndLinenumber() + self._parent._lines.insert(end, line) + self._end +=3D 1 + + def Copy(self, sectObj): + index =3D sectObj.GetStartLinenumber() + 1 + while index < sectObj.GetEndLinenumber(): + line =3D sectObj.GetLine(index) + if not line.strip().startswith('#'): + self.AddLine(line) + index +=3D 1 + + def AddObject(self, obj): + lines =3D obj.GenerateLines() + for line in lines: + self.AddLine(line) + + def GetComment(self): + comments =3D [] + start =3D self._start - 1 + bFound =3D False + + while (start > 0): + line =3D self.GetLine(start).strip() + if len(line) =3D=3D 0: + start -=3D 1 + continue + if line.startswith('##'): + bFound =3D True + index =3D line.rfind('#') + if (index + 1) < len(line): + comments.append(line[index + 1:]) + break + if line.startswith('#'): + start -=3D 1 + continue + break + if bFound: + end =3D start + 1 + while (end < self._start): + line =3D self.GetLine(end).strip() + if len(line) =3D=3D 0: break + if not line.startswith('#'): break + index =3D line.rfind('#') + if (index + 1) < len(line): + comments.append(line[index + 1:]) + end +=3D 1 + return comments + +class BaseINIGlobalObject(object): + def __init__(self, parent): + self._start =3D 0 + self._end =3D 0 + + def Parse(self): + return True + + def __str__(self): + return parent._lines[self._start] + + def __del__(self): + pass + +class BaseINISectionObject(object): + def __init__(self, parent): + self._start =3D 0 + self._end =3D 0 + self._parent =3D parent + + def __del__(self): + self._parent =3D None + + def GetParent(self): + return self._parent + + def GetFilename(self): + return self.GetParent().GetFilename() + + def GetPackageName(self): + return self.GetFilename() + + def GetFileObj(self): + return self.GetParent().GetParent() + + def GetStartLinenumber(self): + return self.GetParent()._start + self._start + + def GetLineByOffset(self, offset): + sect_start =3D self._parent.GetStartLinenumber() + linenumber =3D sect_start + offset + return self._parent.GetLine(linenumber) + + def GetLinenumberByOffset(self, offset): + return offset + self._parent.GetStartLinenumber() + + def Parse(self): + return True + + def Destroy(self): + pass + + def __str__(self): + return self.GetLineByOffset(self._start).strip() + + def GenerateLines(self): + return ['default setion object string\n'] + + def GetComment(self): + comments =3D [] + start =3D self.GetStartLinenumber() - 1 + bFound =3D False + + while (start > 0): + line =3D self.GetParent().GetLine(start).strip() + if len(line) =3D=3D 0: + start -=3D 1 + continue + if line.startswith('##'): + bFound =3D True + index =3D line.rfind('#') + if (index + 1) < len(line): + comments.append(line[index + 1:]) + break + if line.startswith('#'): + start -=3D 1 + continue + break + if bFound: + end =3D start + 1 + while (end <=3D self.GetStartLinenumber() - 1): + line =3D self.GetParent().GetLine(end).strip() + if len(line) =3D=3D 0: break + if not line.startswith('#'): break + index =3D line.rfind('#') + if (index + 1) < len(line): + comments.append(line[index + 1:]) + end +=3D 1 + return comments diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/base= model/inidocview.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlu= gins/basemodel/inidocview.py new file mode 100644 index 0000000..f062f09 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/i= nidocview.py @@ -0,0 +1,23 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# + +import core.editor + +class INIDoc(core.editor.EditorDocument): + def __init__(self): + core.editor.EditorDocument.__init__(self) + self._iniobj =3D None + + +class INIView(core.editor.EditorView): + pass diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/base= model/message.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugin= s/basemodel/message.py new file mode 100644 index 0000000..5cf2028 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/m= essage.py @@ -0,0 +1,52 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# + +def GetEdkLogger(): + import logging + return logging.getLogger('edk') + +class EdkException(Exception): + def __init__(self, message, fName=3DNone, fNo=3DNone): + self._message =3D message + ErrorMsg(message, fName, fNo) + + def GetMessage(self): + return '[EDK Failure]: %s' %self._message + +def ErrorMsg(mess, fName=3DNone, fNo=3DNone): + GetEdkLogger().error(NormalMessage('#ERR#', mess, fName, fNo)) + +def LogMsg(mess, fName=3DNone, fNo=3DNone): + GetEdkLogger().info(NormalMessage('@LOG@', mess, fName, fNo)) + +def WarnMsg(mess, fName=3DNone, fNo=3DNone): + GetEdkLogger().warning(NormalMessage('!WAR!', mess, fName, fNo)) + +def NormalMessage(type, mess, fName=3DNone, fNo=3DNone): + strMsg =3D type + + if fName !=3D None: + strMsg +=3D ' %s' % fName.replace('/', '\\') + if fNo !=3D None: + strMsg +=3D '(%d):' % fNo + else: + strMsg +=3D ' :' + + if fName =3D=3D None and fNo =3D=3D None: + strMsg +=3D ' ' + strMsg +=3D mess + + return strMsg + + + diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2= /__init__.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/ed= k2/__init__.py new file mode 100644 index 0000000..3e4ee53 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2/__init= __.py @@ -0,0 +1,12 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2= /model/__init__.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlug= ins/edk2/model/__init__.py new file mode 100644 index 0000000..3e4ee53 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2/model/= __init__.py @@ -0,0 +1,12 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2= /model/baseobject.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPl= ugins/edk2/model/baseobject.py new file mode 100644 index 0000000..05fa252 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2/model/= baseobject.py @@ -0,0 +1,934 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +import plugins.EdkPlugins.basemodel.ini as ini +import plugins.EdkPlugins.edk2.model.dsc as dsc +import plugins.EdkPlugins.edk2.model.inf as inf +import plugins.EdkPlugins.edk2.model.dec as dec +import os +from plugins.EdkPlugins.basemodel.message import * + +class SurfaceObject(object): + _objs =3D {} + + def __new__(cls, *args, **kwargs): + """Maintain only a single instance of this object + @return: instance of this class + + """ + obj =3D object.__new__(cls, *args, **kwargs) + if not cls._objs.has_key("None"): + cls._objs["None"] =3D [] + cls._objs["None"].append(obj) + + return obj + + def __init__(self, parent, workspace): + self._parent =3D parent + self._fileObj =3D None + self._workspace =3D workspace + self._isModify =3D False + self._modifiedObjs =3D [] + + def __del__(self): + pass + + def Destroy(self): + key =3D self.GetRelativeFilename() + self.GetFileObj().Destroy(self) + del self._fileObj + # dereference self from _objs arrary + assert self._objs.has_key(key), "when destory, object is not in ob= j list" + assert self in self._objs[key], "when destory, object is not in ob= j list" + self._objs[key].remove(self) + if len(self._objs[key]) =3D=3D 0: + del self._objs[key] + + def GetParent(self): + return self._parent + + def GetWorkspace(self): + return self._workspace + + def GetFileObjectClass(self): + return ini.BaseINIFile + + def GetFilename(self): + return self.GetFileObj().GetFilename() + + def GetFileObj(self): + return self._fileObj + + def GetRelativeFilename(self): + fullPath =3D self.GetFilename() + return fullPath[len(self._workspace) + 1:] + + def Load(self, relativePath): + # if has been loaded, directly return + if self._fileObj !=3D None: return True + + relativePath =3D os.path.normpath(relativePath) + fullPath =3D os.path.join(self._workspace, relativePath) + fullPath =3D os.path.normpath(fullPath) + + if not os.path.exists(fullPath): + ErrorMsg("file does not exist!", fullPath) + return False + + self._fileObj =3D self.GetFileObjectClass()(fullPath, self) + + if not self._fileObj.Parse(): + ErrorMsg("Fail to parse file!", fullPath) + return False + + # remove self from None list to list with filename as key + cls =3D self.__class__ + if self not in cls._objs["None"]: + ErrorMsg("Sufrace object does not be create into None list") + cls._objs["None"].remove(self) + if not cls._objs.has_key(relativePath): + cls._objs[relativePath] =3D [] + cls._objs[relativePath].append(self) + + return True + + def Reload(self, force=3DFalse): + ret =3D True + # whether require must be update + if force: + ret =3D self.GetFileObj().Reload(True) + else: + if self.IsModified(): + if self.GetFileObj().IsModified(): + ret =3D self.GetFileObj().Reload() + return ret + + def Modify(self, modify=3DTrue, modifiedObj=3DNone): + if modify: + #LogMsg("%s is modified, modified object is %s" % (self.GetFil= ename(), modifiedObj)) + if issubclass(modifiedObj.__class__, ini.BaseINIFile) and self= ._isModify: + return + self._isModify =3D modify + self.GetParent().Modify(modify, self) + else: + self._isModify =3D modify + + def IsModified(self): + return self._isModify + + def GetModifiedObjs(self): + return self._modifiedObjs + + def FilterObjsByArch(self, objs, arch): + arr =3D [] + for obj in objs: + if obj.GetArch().lower() =3D=3D 'common': + arr.append(obj) + continue + if obj.GetArch().lower() =3D=3D arch.lower(): + arr.append(obj) + continue + return arr + +class Platform(SurfaceObject): + def __init__(self, parent, workspace): + SurfaceObject.__init__(self, parent, workspace) + self._modules =3D [] + self._packages =3D [] + + def Destroy(self): + for module in self._modules: + module.Destroy() + del self._modules[:] + + del self._packages[:] + SurfaceObject.Destroy(self) + + def GetName(self): + return self.GetFileObj().GetDefine("PLATFORM_NAME") + + def GetFileObjectClass(self): + return dsc.DSCFile + + def GetModuleCount(self): + if self.GetFileObj() =3D=3D None: + ErrorMsg("Fail to get module count because DSC file has not be= en load!") + + return len(self.GetFileObj().GetComponents()) + + def GetSupportArchs(self): + return self.GetFileObj().GetDefine("SUPPORTED_ARCHITECTURES").stri= p().split('#')[0].split('|') + + def LoadModules(self, precallback=3DNone, postcallback=3DNone): + for obj in self.GetFileObj().GetComponents(): + mFilename =3D obj.GetFilename() + if precallback !=3D None: + precallback(self, mFilename) + arch =3D obj.GetArch() + if arch.lower() =3D=3D 'common': + archarr =3D self.GetSupportArchs() + else: + archarr =3D [arch] + for arch in archarr: + module =3D Module(self, self.GetWorkspace()) + if module.Load(mFilename, arch, obj.GetOveridePcds(), obj.= GetOverideLibs()): + self._modules.append(module) + if postcallback !=3D None: + postcallback(self, module) + else: + del module + ErrorMsg("Fail to load module %s" % mFilename) + + def GetModules(self): + return self._modules + + def GetLibraryPath(self, classname, arch, type): + objs =3D self.GetFileObj().GetSectionObjectsByName("libraryclasses= ") + + for obj in objs: + if classname.lower() !=3D obj.GetClass().lower(): + continue + if obj.GetArch().lower() !=3D 'common' and \ + obj.GetArch().lower() !=3D arch.lower(): + continue + + if obj.GetModuleType().lower() !=3D 'common' and \ + obj.GetModuleType().lower() !=3D type.lower(): + continue + + return obj.GetInstance() + + ErrorMsg("Fail to get library class %s [%s][%s] from platform %s" = % (classname, arch, type, self.GetFilename())) + return None + + def GetPackage(self, path): + package =3D self.GetParent().GetPackage(path) + if package not in self._packages: + self._packages.append(package) + return package + + def GetPcdBuildObjs(self, name, arch=3DNone): + arr =3D [] + objs =3D self.GetFileObj().GetSectionObjectsByName('pcds') + for obj in objs: + if obj.GetPcdName().lower() =3D=3D name.lower(): + arr.append(obj) + if arch !=3D None: + arr =3D self.FilterObjsByArch(arr, arch) + return arr + + def Reload(self, callback=3DNone): + # do not care force paramter for platform object + isFileChanged =3D self.GetFileObj().IsModified() + ret =3D SurfaceObject.Reload(self, False) + if not ret: return False + if isFileChanged: + # destroy all modules and reload them again + for obj in self._modules: + obj.Destroy() + del self._modules[:] + del self._packages[:] + self.LoadModules(callback) + else: + for obj in self._modules: + callback(self, obj.GetFilename()) + obj.Reload() + + self.Modify(False) + return True + + def Modify(self, modify=3DTrue, modifiedObj=3DNone): + if modify: + #LogMsg("%s is modified, modified object is %s" % (self.GetFil= ename(), modifiedObj)) + if issubclass(modifiedObj.__class__, ini.BaseINIFile) and self= ._isModify: + return + self._isModify =3D modify + self.GetParent().Modify(modify, self) + else: + if self.GetFileObj().IsModified(): + return + for obj in self._modules: + if obj.IsModified(): + return + + self._isModify =3D modify + self.GetParent().Modify(modify, self) + + def GetModuleObject(self, relativePath, arch): + path =3D os.path.normpath(relativePath) + for obj in self._modules: + if obj.GetRelativeFilename() =3D=3D path: + if arch.lower() =3D=3D 'common': + return obj + if obj.GetArch() =3D=3D arch: + return obj + return None + + def GenerateFullReferenceDsc(self): + oldDsc =3D self.GetFileObj() + newDsc =3D dsc.DSCFile() + newDsc.CopySectionsByName(oldDsc, 'defines') + newDsc.CopySectionsByName(oldDsc, 'SkuIds') + + # + # Dynamic common section should also be copied + # + newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicDefault') + newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicHii') + newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicVpd') + newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicEx') + + sects =3D oldDsc.GetSectionByName('Components') + for oldSect in sects: + newSect =3D newDsc.AddNewSection(oldSect.GetName()) + for oldComObj in oldSect.GetObjects(): + module =3D self.GetModuleObject(oldComObj.GetFilename(), o= ldSect.GetArch()) + if module =3D=3D None: continue + + newComObj =3D dsc.DSCComponentObject(newSect) + newComObj.SetFilename(oldComObj.GetFilename()) + + # add all library instance for override section + libdict =3D module.GetLibraries() + for libclass in libdict.keys(): + if libdict[libclass] !=3D None: + newComObj.AddOverideLib(libclass, libdict[libclass= ].GetRelativeFilename().replace('\\', '/')) + + # add all pcds for override section + pcddict =3D module.GetPcds() + for pcd in pcddict.values(): + buildPcd =3D pcd.GetBuildObj() + buildType =3D buildPcd.GetPcdType() + buildValue =3D None + if buildType.lower() =3D=3D 'pcdsdynamichii' or \ + buildType.lower() =3D=3D 'pcdsdynamicvpd' or \ + buildType.lower() =3D=3D 'pcdsdynamicdefault': + buildType =3D 'PcdsDynamic' + if buildType !=3D 'PcdsDynamic': + buildValue =3D buildPcd.GetPcdValue() + newComObj.AddOveridePcd(buildPcd.GetPcdName(), + buildType, + buildValue) + newSect.AddObject(newComObj) + return newDsc + +class Module(SurfaceObject): + def __init__(self, parent, workspace): + SurfaceObject.__init__(self, parent, workspace) + self._arch =3D 'common' + self._parent =3D parent + self._overidePcds =3D {} + self._overideLibs =3D {} + self._libs =3D {} + self._pcds =3D {} + self._ppis =3D [] + self._protocols =3D [] + self._depexs =3D [] + self._guids =3D [] + self._packages =3D [] + + def Destroy(self): + for lib in self._libs.values(): + if lib !=3D None: + lib.Destroy() + self._libs.clear() + + for pcd in self._pcds.values(): + pcd.Destroy() + self._pcds.clear() + + for ppi in self._ppis: + ppi.DeRef(self) + del self._ppis[:] + + for protocol in self._protocols: + if protocol !=3D None: + protocol.DeRef(self) + del self._protocols[:] + + for guid in self._guids: + if guid !=3D None: + guid.DeRef(self) + del self._guids[:] + + del self._packages[:] + del self._depexs[:] + SurfaceObject.Destroy(self) + + def GetFileObjectClass(self): + return inf.INFFile + + def GetLibraries(self): + return self._libs + + def Load(self, filename, arch=3D'common', overidePcds=3DNone, overideL= ibs=3DNone): + if not SurfaceObject.Load(self, filename): + return False + + self._arch =3D arch + if overidePcds !=3D None: + self._overideLibs =3D overideLibs + if overideLibs !=3D None: + self._overidePcds =3D overidePcds + + self._SearchLibraries() + self._SearchPackage() + self._SearchSurfaceItems() + return True + + def GetArch(self): + return self._arch + + def GetModuleName(self): + return self.GetFileObj().GetDefine("BASE_NAME") + + def GetModuleType(self): + return self.GetFileObj().GetDefine("MODULE_TYPE") + + def GetPlatform(self): + return self.GetParent() + + def GetModuleObj(self): + return self + + def GetPcds(self): + pcds =3D self._pcds.copy() + for lib in self._libs.values(): + if lib =3D=3D None: continue + for name in lib._pcds.keys(): + pcds[name] =3D lib._pcds[name] + return pcds + + def GetPpis(self): + ppis =3D [] + ppis +=3D self._ppis + for lib in self._libs.values(): + if lib =3D=3D None: continue + ppis +=3D lib._ppis + return ppis + + def GetProtocols(self): + pros =3D [] + pros =3D self._protocols + for lib in self._libs.values(): + if lib =3D=3D None: continue + pros +=3D lib._protocols + return pros + + def GetGuids(self): + guids =3D [] + guids +=3D self._guids + for lib in self._libs.values(): + if lib =3D=3D None: continue + guids +=3D lib._guids + return guids + + def GetDepexs(self): + deps =3D [] + deps +=3D self._depexs + for lib in self._libs.values(): + if lib =3D=3D None: continue + deps +=3D lib._depexs + return deps + + def IsLibrary(self): + return self.GetFileObj().GetDefine("LIBRARY_CLASS") !=3D None + + def GetLibraryInstance(self, classname, arch, type): + if classname not in self._libs.keys(): + # find in overide lib firstly + if classname in self._overideLibs.keys(): + self._libs[classname] =3D Library(self, self.GetWorkspace(= )) + self._libs[classname].Load(self._overideLibs[classname]) + return self._libs[classname] + + parent =3D self.GetParent() + if issubclass(parent.__class__, Platform): + path =3D parent.GetLibraryPath(classname, arch, type) + if path =3D=3D None: + ErrorMsg('Fail to get library instance for %s' % class= name, self.GetFilename()) + return None + self._libs[classname] =3D Library(self, self.GetWorkspace(= )) + if not self._libs[classname].Load(path, self.GetArch()): + self._libs[classname] =3D None + else: + self._libs[classname] =3D parent.GetLibraryInstance(classn= ame, arch, type) + return self._libs[classname] + + def GetSourceObjs(self): + return self.GetFileObj().GetSectionObjectsByName('source') + + def _SearchLibraries(self): + objs =3D self.GetFileObj().GetSectionObjectsByName('libraryclasses= ') + arch =3D self.GetArch() + type =3D self.GetModuleType() + for obj in objs: + if obj.GetArch().lower() !=3D 'common' and \ + obj.GetArch().lower() not in self.GetPlatform().GetSupportA= rchs(): + continue + classname =3D obj.GetClass() + instance =3D self.GetLibraryInstance(classname, arch, type) + if not self.IsLibrary() and instance !=3D None: + instance._isInherit =3D False + + if classname not in self._libs.keys(): + self._libs[classname] =3D instance + + def _SearchSurfaceItems(self): + # get surface item from self's inf + pcds =3D [] + ppis =3D [] + pros =3D [] + deps =3D [] + guids =3D [] + if self.GetFileObj() !=3D None: + pcds =3D self.FilterObjsByArch(self.GetFileObj().GetSectionObj= ectsByName('pcd'), + self.GetArch()) + for pcd in pcds: + if pcd.GetPcdName() not in self._pcds.keys(): + pcdItem =3D PcdItem(pcd.GetPcdName(), self, pcd) + self._pcds[pcd.GetPcdName()] =3D ModulePcd(self, + pcd.GetPcdNam= e(), + pcd, + pcdItem) + + ppis +=3D self.FilterObjsByArch(self.GetFileObj().GetSectionOb= jectsByName('ppis'), + self.GetArch()) + + for ppi in ppis: + item =3D PpiItem(ppi.GetName(), self, ppi) + if item not in self._ppis: + self._ppis.append(item) + + pros +=3D self.FilterObjsByArch(self.GetFileObj().GetSectionOb= jectsByName('protocols'), + self.GetArch()) + + for pro in pros: + item =3D ProtocolItem(pro.GetName(), self, pro) + if item not in self._protocols: + self._protocols.append(item) + + deps +=3D self.FilterObjsByArch(self.GetFileObj().GetSectionOb= jectsByName('depex'), + self.GetArch()) + for dep in deps: + item =3D DepexItem(self, dep) + self._depexs.append(item) + + guids +=3D self.FilterObjsByArch(self.GetFileObj().GetSectionO= bjectsByName('guids'), + self.GetArch()) + for guid in guids: + item =3D GuidItem(guid.GetName(), self, guid) + if item not in self._guids: + self._guids.append(item) + + def _SearchPackage(self): + objs =3D self.GetFileObj().GetSectionObjectsByName('packages') + for obj in objs: + package =3D self.GetPlatform().GetPackage(obj.GetPath()) + if package !=3D None: + self._packages.append(package) + + def GetPackages(self): + return self._packages + + def GetPcdObjects(self): + if self.GetFileObj() =3D=3D None: + return [] + + return self.GetFileObj().GetSectionObjectsByName('pcd') + + def GetLibraryClassHeaderFilePath(self): + lcname =3D self.GetFileObj().GetProduceLibraryClass() + if lcname =3D=3D None: return None + + pkgs =3D self.GetPackages() + for package in pkgs: + path =3D package.GetLibraryClassHeaderPathByName(lcname) + if path !=3D None: + return os.path.realpath(os.path.join(package.GetFileObj().= GetPackageRootPath(), path)) + return None + + def Reload(self, force=3DFalse, callback=3DNone): + if callback !=3D None: + callback(self, "Starting reload...") + + ret =3D SurfaceObject.Reload(self, force) + if not ret: return False + + if not force and not self.IsModified(): + return True + + for lib in self._libs.values(): + if lib !=3D None: + lib.Destroy() + self._libs.clear() + + for pcd in self._pcds.values(): + pcd.Destroy() + self._pcds.clear() + + for ppi in self._ppis: + ppi.DeRef(self) + del self._ppis[:] + + for protocol in self._protocols: + protocol.DeRef(self) + del self._protocols[:] + + for guid in self._guids: + guid.DeRef(self) + del self._guids[:] + + del self._packages[:] + del self._depexs[:] + + if callback !=3D None: + callback(self, "Searching libraries...") + self._SearchLibraries() + if callback !=3D None: + callback(self, "Searching packages...") + self._SearchPackage() + if callback !=3D None: + callback(self, "Searching surface items...") + self._SearchSurfaceItems() + + self.Modify(False) + return True + + def Modify(self, modify=3DTrue, modifiedObj=3DNone): + if modify: + #LogMsg("%s is modified, modified object is %s" % (self.GetFil= ename(), modifiedObj)) + if issubclass(modifiedObj.__class__, ini.BaseINIFile) and self= ._isModify: + return + self._isModify =3D modify + self.GetParent().Modify(modify, self) + else: + if self.GetFileObj().IsModified(): + return + + self._isModify =3D modify + self.GetParent().Modify(modify, self) + +class Library(Module): + def __init__(self, parent, workspace): + Module.__init__(self, parent, workspace) + self._isInherit =3D True + + def IsInherit(self): + return self._isInherit + + def GetModuleType(self): + return self.GetParent().GetModuleType() + + def GetPlatform(self): + return self.GetParent().GetParent() + + def GetModuleObj(self): + return self.GetParent() + + def GetArch(self): + return self.GetParent().GetArch() + + def Destroy(self): + self._libs.clear() + self._pcds.clear() + SurfaceObject.Destroy(self) + +class Package(SurfaceObject): + def __init__(self, parent, workspace): + SurfaceObject.__init__(self, parent, workspace) + self._pcds =3D {} + self._guids =3D {} + self._protocols =3D {} + self._ppis =3D {} + + def GetPcds(self): + return self._pcds + + def GetPpis(self): + return self._ppis.values() + + def GetProtocols(self): + return self._protocols.values() + + def GetGuids(self): + return self._guids.values() + + def Destroy(self): + for pcd in self._pcds.values(): + if pcd !=3D None: + pcd.Destroy() + for guid in self._guids.values(): + if guid !=3D None: + guid.Destroy() + for protocol in self._protocols.values(): + if protocol !=3D None: + protocol.Destroy() + for ppi in self._ppis.values(): + if ppi !=3D None: + ppi.Destroy() + self._pcds.clear() + self._guids.clear() + self._protocols.clear() + self._ppis.clear() + self._pcds.clear() + SurfaceObject.Destroy(self) + + def Load(self, relativePath): + ret =3D SurfaceObject.Load(self, relativePath) + if not ret: return False + pcds =3D self.GetFileObj().GetSectionObjectsByName('pcds') + for pcd in pcds: + if pcd.GetPcdName() in self._pcds.keys(): + if self._pcds[pcd.GetPcdName()] !=3D None: + self._pcds[pcd.GetPcdName()].AddDecObj(pcd) + else: + self._pcds[pcd.GetPcdName()] =3D PcdItem(pcd.GetPcdName(),= self, pcd) + + guids =3D self.GetFileObj().GetSectionObjectsByName('guids') + for guid in guids: + if guid.GetName() not in self._guids.keys(): + self._guids[guid.GetName()] =3D GuidItem(guid.GetName(), s= elf, guid) + else: + WarnMsg("Duplicate definition for %s" % guid.GetName()) + + ppis =3D self.GetFileObj().GetSectionObjectsByName('ppis') + for ppi in ppis: + if ppi.GetName() not in self._ppis.keys(): + self._ppis[ppi.GetName()] =3D PpiItem(ppi.GetName(), self,= ppi) + else: + WarnMsg("Duplicate definition for %s" % ppi.GetName()) + + protocols =3D self.GetFileObj().GetSectionObjectsByName('protocols= ') + for protocol in protocols: + if protocol.GetName() not in self._protocols.keys(): + self._protocols[protocol.GetName()] =3D ProtocolItem(proto= col.GetName(), self, protocol) + else: + WarnMsg("Duplicate definition for %s" % protocol.GetName()) + + return True + + def GetFileObjectClass(self): + return dec.DECFile + + def GetName(self): + return self.GetFileObj().GetDefine("PACKAGE_NAME") + + def GetPcdDefineObjs(self, name=3DNone): + arr =3D [] + objs =3D self.GetFileObj().GetSectionObjectsByName('pcds') + if name =3D=3D None: return objs + + for obj in objs: + if obj.GetPcdName().lower() =3D=3D name.lower(): + arr.append(obj) + return arr + + def GetLibraryClassObjs(self): + return self.GetFileObj().GetSectionObjectsByName('libraryclasses') + + def Modify(self, modify=3DTrue, modifiedObj=3DNone): + if modify: + self._isModify =3D modify + self.GetParent().Modify(modify, self) + else: + if self.GetFileObj().IsModified(): + return + + self._isModify =3D modify + self.GetParent().Modify(modify, self) + + def GetLibraryClassHeaderPathByName(self, clsname): + objs =3D self.GetLibraryClassObjs() + for obj in objs: + if obj.GetClassName() =3D=3D clsname: + return obj.GetHeaderFile() + return None + +class DepexItem(object): + def __init__(self, parent, infObj): + self._parent =3D parent + self._infObj =3D infObj + + def GetDepexString(self): + return str(self._infObj) + + def GetInfObject(self): + return self._infObj + +class ModulePcd(object): + _type_mapping =3D {'FeaturePcd': 'PcdsFeatureFlag', + 'FixedPcd': 'PcdsFixedAtBuild', + 'PatchPcd': 'PcdsPatchableInModule'} + + def __init__(self, parent, name, infObj, pcdItem): + assert issubclass(parent.__class__, Module), "Module's PCD's paren= t must be module!" + assert pcdItem !=3D None, 'Pcd %s does not in some package!' % name + + self._name =3D name + self._parent =3D parent + self._pcdItem =3D pcdItem + self._infObj =3D infObj + + def GetName(self): + return self._name + + def GetParent(self): + return self._name + + def GetArch(self): + return self._parent.GetArch() + + def Destroy(self): + self._pcdItem.DeRef(self._parent) + self._infObj =3D None + + def GetBuildObj(self): + platformInfos =3D self._parent.GetPlatform().GetPcdBuildObjs(self.= _name, self.GetArch()) + modulePcdType =3D self._infObj.GetPcdType() + + # if platform do not gives pcd's value, get default value from pac= kage + if len(platformInfos) =3D=3D 0: + if modulePcdType.lower() =3D=3D 'pcd': + return self._pcdItem.GetDecObject() + else: + for obj in self._pcdItem.GetDecObjects(): + if modulePcdType not in self._type_mapping.keys(): + ErrorMsg("Invalid PCD type %s" % modulePcdType) + return None + + if self._type_mapping[modulePcdType] =3D=3D obj.GetPcd= Type(): + return obj + ErrorMsg ('Module PCD type %s does not in valied range [%s= ] in package!' % \ + (modulePcdType)) + else: + if modulePcdType.lower() =3D=3D 'pcd': + if len(platformInfos) > 1: + WarnMsg("Find more than one value for PCD %s in platfo= rm %s" % \ + (self._name, self._parent.GetPlatform().GetFil= ename())) + return platformInfos[0] + else: + for obj in platformInfos: + if modulePcdType not in self._type_mapping.keys(): + ErrorMsg("Invalid PCD type %s" % modulePcdType) + return None + + if self._type_mapping[modulePcdType] =3D=3D obj.GetPcd= Type(): + return obj + + ErrorMsg('Can not find value for pcd %s in pcd type %s' % \ + (self._name, modulePcdType)) + return None + + +class SurfaceItem(object): + _objs =3D {} + + def __new__(cls, *args, **kwargs): + """Maintain only a single instance of this object + @return: instance of this class + + """ + name =3D args[0] + parent =3D args[1] + fileObj =3D args[2] + if issubclass(parent.__class__, Package): + if name in cls._objs.keys(): + ErrorMsg("%s item is duplicated defined in packages: %s an= d %s" % + (name, parent.GetFilename(), cls._objs[name].GetP= arent().GetFilename())) + return None + obj =3D object.__new__(cls, *args, **kwargs) + cls._objs[name] =3D obj + return obj + elif issubclass(parent.__class__, Module): + if name not in cls._objs.keys(): + ErrorMsg("%s item does not defined in any package! It is u= sed by module %s" % \ + (name, parent.GetFilename())) + return None + return cls._objs[name] + + return None + + + def __init__(self, name, parent, fileObj): + if issubclass(parent.__class__, Package): + self._name =3D name + self._parent =3D parent + self._decObj =3D [fileObj] + self._refMods =3D {} + else: + self.RefModule(parent, fileObj) + + @classmethod + def GetObjectDict(cls): + return cls._objs + + def GetParent(self): + return self._parent + + def GetReference(self): + return self._refMods + + def RefModule(self, mObj, infObj): + if mObj in self._refMods.keys(): + return + self._refMods[mObj] =3D infObj + + def DeRef(self, mObj): + if mObj not in self._refMods.keys(): + WarnMsg("%s is not referenced by module %s" % (self._name, mOb= j.GetFilename())) + return + del self._refMods[mObj] + + def Destroy(self): + self._refMods.clear() + cls =3D self.__class__ + del cls._objs[self._name] + + def GetName(self): + return self._name + + def GetDecObject(self): + return self._decObj[0] + + def GetDecObjects(self): + return self._decObj + +class PcdItem(SurfaceItem): + def AddDecObj(self, fileObj): + for decObj in self._decObj: + if decObj.GetFilename() !=3D fileObj.GetFilename(): + ErrorMsg("Pcd %s defined in more than one packages : %s an= d %s" % \ + (self._name, decObj.GetFilename(), fileObj.GetFil= ename())) + return + if decObj.GetPcdType() =3D=3D fileObj.GetPcdType() and \ + decObj.GetArch().lower() =3D=3D fileObj.GetArch(): + ErrorMsg("Pcd %s is duplicated defined in pcd type %s in p= ackage %s" % \ + (self._name, decObj.GetPcdType(), decObj.GetFilen= ame())) + return + self._decObj.append(fileObj) + + def GetValidPcdType(self): + types =3D [] + for obj in self._decObj: + if obj.GetPcdType() not in types: + types +=3D obj.GetPcdType() + return types + +class GuidItem(SurfaceItem): + pass + +class PpiItem(SurfaceItem): + pass + +class ProtocolItem(SurfaceItem): + pass diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2= /model/dec.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/e= dk2/model/dec.py new file mode 100644 index 0000000..3bd0b7b --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2/model/= dec.py @@ -0,0 +1,319 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# + +import plugins.EdkPlugins.basemodel.ini as ini +import re, os +from plugins.EdkPlugins.basemodel.message import * + +class DECFile(ini.BaseINIFile): + + def GetSectionInstance(self, parent, name, isCombined=3DFalse): + return DECSection(parent, name, isCombined) + + def GetComponents(self): + return self.GetSectionByName('Components') + + def GetPackageRootPath(self): + return os.path.dirname(self.GetFilename()).strip() + + def GetBaseName(self): + return self.GetDefine("PACKAGE_NAME").strip() + + def GetVersion(self): + return self.GetDefine("PACKAGE_VERSION").strip() + + def GetSectionObjectsByName(self, name, arch=3DNone): + arr =3D [] + sects =3D self.GetSectionByName(name) + for sect in sects: + # skip unmatched archtecture content + if not sect.IsArchMatch(arch): + continue + + for obj in sect.GetObjects(): + arr.append(obj) + + return arr + +class DECSection(ini.BaseINISection): + def GetSectionINIObject(self, parent): + type =3D self.GetType() + + if type.lower().find('defines') !=3D -1: + return DECDefineSectionObject(self) + if type.lower().find('includes') !=3D -1: + return DECIncludeObject(self) + if type.lower().find('pcd') !=3D -1: + return DECPcdObject(self) + if type.lower() =3D=3D 'libraryclasses': + return DECLibraryClassObject(self) + if type.lower() =3D=3D 'guids': + return DECGuidObject(self) + if type.lower() =3D=3D 'ppis': + return DECPpiObject(self) + if type.lower() =3D=3D 'protocols': + return DECProtocolObject(self) + + return DECSectionObject(self) + + def GetType(self): + arr =3D self._name.split('.') + return arr[0].strip() + + def GetArch(self): + arr =3D self._name.split('.') + if len(arr) =3D=3D 1: + return 'common' + return arr[1] + + def IsArchMatch(self, arch): + if arch =3D=3D None or self.GetArch() =3D=3D 'common': + return True + + if self.GetArch().lower() !=3D arch.lower(): + return False + + return True + +class DECSectionObject(ini.BaseINISectionObject): + def GetArch(self): + return self.GetParent().GetArch() + +class DECDefineSectionObject(DECSectionObject): + def __init__(self, parent): + DECSectionObject.__init__(self, parent) + self._key =3D None + self._value =3D None + + def Parse(self): + assert (self._start =3D=3D self._end), 'The object in define secti= on must be in single line' + + line =3D self.GetLineByOffset(self._start).strip() + + line =3D line.split('#')[0] + arr =3D line.split('=3D') + if len(arr) !=3D 2: + ErrorMsg('Invalid define section object', + self.GetFilename(), + self.GetParent().GetName() + ) + return False + + self._key =3D arr[0].strip() + self._value =3D arr[1].strip() + + return True + + def GetKey(self): + return self._key + + def GetValue(self): + return self._value + +class DECGuidObject(DECSectionObject): + _objs =3D {} + + def __init__(self, parent): + DECSectionObject.__init__(self, parent) + self._name =3D None + + def Parse(self): + line =3D self.GetLineByOffset(self._start).strip().split('#')[0] + self._name =3D line.split('=3D')[0].strip() + self._guid =3D line.split('=3D')[1].strip() + objdict =3D DECGuidObject._objs + if self._name not in objdict.keys(): + objdict[self._name] =3D [self] + else: + objdict[self._name].append(self) + + return True + + def GetName(self): + return self._name + + def GetGuid(self): + return self._guid + + def Destroy(self): + objdict =3D DECGuidObject._objs + objdict[self._name].remove(self) + if len(objdict[self._name]) =3D=3D 0: + del objdict[self._name] + + @staticmethod + def GetObjectDict(): + return DECGuidObject._objs + +class DECPpiObject(DECSectionObject): + _objs =3D {} + def __init__(self, parent): + DECSectionObject.__init__(self, parent) + self._name =3D None + + def Parse(self): + line =3D self.GetLineByOffset(self._start).strip().split('#')[0] + self._name =3D line.split('=3D')[0].strip() + self._guid =3D line.split('=3D')[1].strip() + objdict =3D DECPpiObject._objs + if self._name not in objdict.keys(): + objdict[self._name] =3D [self] + else: + objdict[self._name].append(self) + + return True + + def GetName(self): + return self._name + + def GetGuid(self): + return self._guid + + def Destroy(self): + objdict =3D DECPpiObject._objs + objdict[self._name].remove(self) + if len(objdict[self._name]) =3D=3D 0: + del objdict[self._name] + + @staticmethod + def GetObjectDict(): + return DECPpiObject._objs + +class DECProtocolObject(DECSectionObject): + _objs =3D {} + + def __init__(self, parent): + DECSectionObject.__init__(self, parent) + self._name =3D None + + def Parse(self): + line =3D self.GetLineByOffset(self._start).strip().split('#')[0] + self._name =3D line.split('=3D')[0].strip() + self._guid =3D line.split('=3D')[1].strip() + objdict =3D DECProtocolObject._objs + if self._name not in objdict.keys(): + objdict[self._name] =3D [self] + else: + objdict[self._name].append(self) + + return True + + def GetName(self): + return self._name + + def GetGuid(self): + return self._guid + + def Destroy(self): + objdict =3D DECProtocolObject._objs + objdict[self._name].remove(self) + if len(objdict[self._name]) =3D=3D 0: + del objdict[self._name] + + + @staticmethod + def GetObjectDict(): + return DECProtocolObject._objs + +class DECLibraryClassObject(DECSectionObject): + _objs =3D {} + + def __init__(self, parent): + DECSectionObject.__init__(self, parent) + self.mClassName =3D None + self.mHeaderFile =3D None + + def Parse(self): + line =3D self.GetLineByOffset(self._start).strip().split('#')[0] + self.mClassName, self.mHeaderFile =3D line.split('|') + objdict =3D DECLibraryClassObject._objs + if self.mClassName not in objdict.keys(): + objdict[self.mClassName] =3D [self] + else: + objdict[self.mClassName].append(self) + return True + + def GetClassName(self): + return self.mClassName + + def GetName(self): + return self.mClassName + + def GetHeaderFile(self): + return self.mHeaderFile + + def Destroy(self): + objdict =3D DECLibraryClassObject._objs + objdict[self.mClassName].remove(self) + if len(objdict[self.mClassName]) =3D=3D 0: + del objdict[self.mClassName] + + @staticmethod + def GetObjectDict(): + return DECLibraryClassObject._objs + +class DECIncludeObject(DECSectionObject): + def __init__(self, parent): + DECSectionObject.__init__(self, parent) + + def GetPath(self): + return self.GetLineByOffset(self._start).split('#')[0].strip() + +class DECPcdObject(DECSectionObject): + _objs =3D {} + + def __init__(self, parent): + DECSectionObject.__init__(self, parent) + self.mPcdName =3D None + self.mPcdDefaultValue =3D None + self.mPcdDataType =3D None + self.mPcdToken =3D None + + def Parse(self): + line =3D self.GetLineByOffset(self._start).strip().split('#')[0] + (self.mPcdName, self.mPcdDefaultValue, self.mPcdDataType, self.mPc= dToken) =3D line.split('|') + objdict =3D DECPcdObject._objs + if self.mPcdName not in objdict.keys(): + objdict[self.mPcdName] =3D [self] + else: + objdict[self.mPcdName].append(self) + + return True + + def Destroy(self): + objdict =3D DECPcdObject._objs + objdict[self.mPcdName].remove(self) + if len(objdict[self.mPcdName]) =3D=3D 0: + del objdict[self.mPcdName] + + def GetPcdType(self): + return self.GetParent().GetType() + + def GetPcdName(self): + return self.mPcdName + + def GetPcdValue(self): + return self.mPcdDefaultValue + + def GetPcdDataType(self): + return self.mPcdDataType + + def GetPcdToken(self): + return self.mPcdToken + + def GetName(self): + return self.GetPcdName().split('.')[1] + + @staticmethod + def GetObjectDict(): + return DECPcdObject._objs diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2= /model/doxygengen.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPl= ugins/edk2/model/doxygengen.py new file mode 100644 index 0000000..268ba5c --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2/model/= doxygengen.py @@ -0,0 +1,1089 @@ +## @file +# +# This file produce action class to generate doxygen document for edk2 cod= ebase. +# The action classes are shared by GUI and command line tools. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +"""This file produce action class to generate doxygen document for edk2 co= debase. + The action classes are shared by GUI and command line tools. +""" +import plugins.EdkPlugins.basemodel.doxygen as doxygen +import os +try: + import wx + gInGui =3D True +except: + gInGui =3D False +import re +import plugins.EdkPlugins.edk2.model.inf as inf +import plugins.EdkPlugins.edk2.model.dec as dec +from plugins.EdkPlugins.basemodel.message import * + +_ignore_dir =3D ['.svn', '_svn', 'cvs'] +_inf_key_description_mapping_table =3D { + 'INF_VERSION':'Version of INF file specification', + #'BASE_NAME':'Module Name', + 'FILE_GUID':'Module Guid', + 'MODULE_TYPE': 'Module Type', + 'VERSION_STRING': 'Module Version', + 'LIBRARY_CLASS': 'Produced Library Class', + 'EFI_SPECIFICATION_VERSION': 'UEFI Specification Version', + 'PI_SPECIFICATION_VERSION': 'PI Specification Version', + 'ENTRY_POINT': 'Module Entry Point Function', + 'CONSTRUCTOR': 'Library Constructor Function' +} + +_dec_key_description_mapping_table =3D { + 'DEC_SPECIFICATION': 'Version of DEC file specification', + 'PACKAGE_GUID': 'Package Guid' +} +class DoxygenAction: + """This is base class for all doxygen action. + """ + + def __init__(self, doxPath, chmPath, outputPath, projname, mode=3D'htm= l', log=3DNone, verbose=3DFalse): + """Constructor function. + @param doxPath the obosolution path of doxygen execute fi= le. + @param outputPath the obosolution output path. + @param log log function for output message + """ + self._doxPath =3D doxPath + self._chmPath =3D chmPath + self._outputPath =3D outputPath + self._projname =3D projname + self._configFile =3D None # doxygen config file is use= d by doxygen exe file + self._indexPageFile =3D None # doxygen page file for inde= x page. + self._log =3D log + self._mode =3D mode + self._verbose =3D verbose + self._doxygenCallback =3D None + self._chmCallback =3D None + + def Log(self, message, level=3D'info'): + if self._log !=3D None: + self._log(message, level) + + def IsVerbose(self): + return self._verbose + + def Generate(self): + """Generate interface called by outer directly""" + self.Log(">>>>>> Start generate doxygen document for %s... Zzz....= \n" % self._projname) + + # create doxygen config file at first + self._configFile =3D doxygen.DoxygenConfigFile() + self._configFile.SetOutputDir(self._outputPath) + + self._configFile.SetWarningFilePath(os.path.join(self._outputPath,= 'warning.txt')) + if self._mode.lower() =3D=3D 'html': + self._configFile.SetHtmlMode() + else: + self._configFile.SetChmMode() + + self.Log(" >>>>>> Initialize doxygen config file...Zzz...\n") + self.InitializeConfigFile() + + self.Log(" >>>>>> Generate doxygen index page file...Zzz...\n") + indexPagePath =3D self.GenerateIndexPage() + if indexPagePath =3D=3D None: + self.Log("Fail to generate index page!\n", 'error') + return False + else: + self.Log("Success to create doxygen index page file %s \n" % i= ndexPagePath) + + # Add index page doxygen file to file list. + self._configFile.AddFile(indexPagePath) + + # save config file to output path + configFilePath =3D os.path.join(self._outputPath, self._projname += '.doxygen_config') + self._configFile.Generate(configFilePath) + self.Log(" <<<<<< Success Save doxygen config file to %s...\n" = % configFilePath) + + # launch doxygen tool to generate document + if self._doxygenCallback !=3D None: + self.Log(" >>>>>> Start doxygen process...Zzz...\n") + if not self._doxygenCallback(self._doxPath, configFilePath): + return False + else: + self.Log("Fail to create doxygen process!", 'error') + return False + + return True + + def InitializeConfigFile(self): + """Initialize config setting for doxygen project. It will be invok= ed after config file + object is created. Inherited class should implement it. + """ + + def GenerateIndexPage(self): + """Generate doxygen index page. Inherited class should implement i= t.""" + return None + + def RegisterCallbackDoxygenProcess(self, callback): + self._doxygenCallback =3D callback + + def RegisterCallbackCHMProcess(self, callback): + self._chmCallback =3D callback + +class PlatformDocumentAction(DoxygenAction): + """Generate platform doxygen document, will be implement at future.""" + +class PackageDocumentAction(DoxygenAction): + """Generate package reference document""" + + def __init__(self, doxPath, chmPath, outputPath, pObj, mode=3D'html', = log=3DNone, arch=3DNone, tooltag=3DNone, + onlyInclude=3DFalse, verbose=3DFalse): + DoxygenAction.__init__(self, doxPath, chmPath, outputPath, pObj.Ge= tName(), mode, log, verbose) + self._pObj =3D pObj + self._arch =3D arch + self._tooltag =3D tooltag + self._onlyIncludeDocument =3D onlyInclude + + def InitializeConfigFile(self): + if self._arch =3D=3D 'IA32': + self._configFile.AddPreDefined('MDE_CPU_IA32') + elif self._arch =3D=3D 'X64': + self._configFile.AddPreDefined('MDE_CPU_X64') + elif self._arch =3D=3D 'IPF': + self._configFile.AddPreDefined('MDE_CPU_IPF') + elif self._arch =3D=3D 'EBC': + self._configFile.AddPreDefined('MDE_CPU_EBC') + else: + self._arch =3D None + self._configFile.AddPreDefined('MDE_CPU_IA32') + self._configFile.AddPreDefined('MDE_CPU_X64') + self._configFile.AddPreDefined('MDE_CPU_IPF') + self._configFile.AddPreDefined('MDE_CPU_EBC') + self._configFile.AddPreDefined('MDE_CPU_ARM') + + namestr =3D self._pObj.GetName() + if self._arch !=3D None: + namestr +=3D '[%s]' % self._arch + if self._tooltag !=3D None: + namestr +=3D '[%s]' % self._tooltag + self._configFile.SetProjectName(namestr) + self._configFile.SetStripPath(self._pObj.GetWorkspace()) + self._configFile.SetProjectVersion(self._pObj.GetFileObj().GetVers= ion()) + self._configFile.AddPattern('*.decdoxygen') + + if self._tooltag.lower() =3D=3D 'msft': + self._configFile.AddPreDefined('_MSC_EXTENSIONS') + elif self._tooltag.lower() =3D=3D 'gnu': + self._configFile.AddPreDefined('__GNUC__') + elif self._tooltag.lower() =3D=3D 'intel': + self._configFile.AddPreDefined('__INTEL_COMPILER') + else: + self._tooltag =3D None + self._configFile.AddPreDefined('_MSC_EXTENSIONS') + self._configFile.AddPreDefined('__GNUC__') + self._configFile.AddPreDefined('__INTEL_COMPILER') + + self._configFile.AddPreDefined('ASM_PFX=3D ') + self._configFile.AddPreDefined('OPTIONAL=3D ') + + def GenerateIndexPage(self): + """Generate doxygen index page. Inherited class should implement i= t.""" + fObj =3D self._pObj.GetFileObj() + pdObj =3D doxygen.DoxygenFile('%s Package Document' % self._pObj.= GetName(), + '%s.decdoxygen' % self._pObj.GetFilen= ame()) + self._configFile.AddFile(pdObj.GetFilename()) + pdObj.AddDescription(fObj.GetFileHeader()) + + defSection =3D fObj.GetSectionByName('defines')[0] + baseSection =3D doxygen.Section('PackageBasicInformation', 'Packag= e Basic Information') + descr =3D '' + for obj in defSection.GetObjects(): + if obj.GetKey() in _dec_key_description_mapping_table.keys(): + descr +=3D '' + descr +=3D '' % _dec_key_description_map= ping_table[obj.GetKey()] + descr +=3D '' % obj.GetValue() + descr +=3D '' + descr +=3D '
%s%s

' + baseSection.AddDescription(descr) + pdObj.AddSection(baseSection) + + knownIssueSection =3D doxygen.Section('Known_Issue_section', 'Know= n Issue') + knownIssueSection.AddDescription('
    ') + knownIssueSection.AddDescription('
  • OPTIONAL macro for function= parameter can not be dealed with doxygen, so it disapear in this document!=
  • ') + knownIssueSection.AddDescription('
') + pdObj.AddSection(knownIssueSection) + + self.AddAllIncludeFiles(self._pObj, self._configFile) + pages =3D self.GenerateIncludesSubPage(self._pObj, self._configFil= e) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + pages =3D self.GenerateLibraryClassesSubPage(self._pObj, self._con= figFile) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + pages =3D self.GeneratePcdSubPages(self._pObj, self._configFile) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + pages =3D self.GenerateGuidSubPages(self._pObj, self._configFile) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + pages =3D self.GeneratePpiSubPages(self._pObj, self._configFile) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + pages =3D self.GenerateProtocolSubPages(self._pObj, self._configFi= le) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + if not self._onlyIncludeDocument: + pdObj.AddPages(self.GenerateModulePages(self._pObj, self._conf= igFile)) + + pdObj.Save() + return pdObj.GetFilename() + + def GenerateIncludesSubPage(self, pObj, configFile): + # by default add following path as include path to config file + pkpath =3D pObj.GetFileObj().GetPackageRootPath() + configFile.AddIncludePath(os.path.join(pkpath, 'Include')) + configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Library= ')) + configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Protoco= l')) + configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Ppi')) + configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Guid')) + configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Industr= yStandard')) + + rootArray =3D [] + pageRoot =3D doxygen.Page("Public Includes", "%s_public_includes" = % pObj.GetName()) + objs =3D pObj.GetFileObj().GetSectionObjectsByName('includes') + if len(objs) =3D=3D 0: return [] + + for obj in objs: + # Add path to include path + path =3D os.path.join(pObj.GetFileObj().GetPackageRootPath(), = obj.GetPath()) + configFile.AddIncludePath(path) + + # only list common folder's include file + if obj.GetArch().lower() !=3D 'common': + continue + + bNeedAddIncludePage =3D False + topPage =3D doxygen.Page(self._ConvertPathToDoxygen(path, pObj= ), 'public_include_top') + + topPage.AddDescription('
    \n') + for file in os.listdir(path): + if file.lower() in _ignore_dir: continue + fullpath =3D os.path.join(path, file) + if os.path.isfile(fullpath): + self.ProcessSourceFileForInclude(fullpath, pObj, confi= gFile) + topPage.AddDescription('
  • \link %s\endlink
  • \n'= % self._ConvertPathToDoxygen(fullpath, pObj)) + else: + if file.lower() in ['library', 'protocol', 'guid', 'pp= i', 'ia32', 'x64', 'ipf', 'ebc', 'arm', 'pi', 'uefi', 'aarch64']: + continue + bNeedAddSubPage =3D False + subpage =3D doxygen.Page(self._ConvertPathToDoxygen(fu= llpath, pObj), 'public_include_%s' % file) + subpage.AddDescription('
      \n') + for subfile in os.listdir(fullpath): + if subfile.lower() in _ignore_dir: continue + bNeedAddSubPage =3D True + subfullpath =3D os.path.join(fullpath, subfile) + self.ProcessSourceFileForInclude(subfullpath, pObj= , configFile) + subpage.AddDescription('
    • \link %s \endlink \n' % self._ConvertPathToDoxygen(subfullpath, pObj)) + subpage.AddDescription('
    \n') + if bNeedAddSubPage: + bNeedAddIncludePage =3D True + pageRoot.AddPage(subpage) + topPage.AddDescription('
\n') + if bNeedAddIncludePage: + pageRoot.AddPage(topPage) + + if pageRoot.GetSubpageCount() !=3D 0: + return [pageRoot] + else: + return [] + + def GenerateLibraryClassesSubPage(self, pObj, configFile): + """ + Generate sub page for library class for package. + One DEC file maybe contains many library class sections + for different architecture. + + @param fObj DEC file object. + """ + rootArray =3D [] + pageRoot =3D doxygen.Page("Library Class", "%s_libraryclass" % pOb= j.GetName()) + objs =3D pObj.GetFileObj().GetSectionObjectsByName('libraryclass',= self._arch) + if len(objs) =3D=3D 0: return [] + + if self._arch !=3D None: + for obj in objs: + classPage =3D doxygen.Page(obj.GetClassName(), + "lc_%s" % obj.GetClassName()) + comments =3D obj.GetComment() + if len(comments) !=3D 0: + classPage.AddDescription('
\n'.join(comments) + '\n') + pageRoot.AddPage(classPage) + path =3D os.path.join(pObj.GetFileObj().GetPackageRootPath= (), obj.GetHeaderFile()) + path =3D path[len(pObj.GetWorkspace()) + 1:] + if len(comments) =3D=3D 0: + classPage.AddDescription('\copydoc %s

' % obj.GetHea= derFile()) + section =3D doxygen.Section('ref', 'Refer to Header File') + section.AddDescription('\link %s\n' % obj.GetHeaderFile()) + section.AddDescription(' \endlink

\n') + classPage.AddSection(section) + fullPath =3D os.path.join(pObj.GetFileObj().GetPackageRoot= Path(), obj.GetHeaderFile()) + self.ProcessSourceFileForInclude(fullPath, pObj, configFil= e) + else: + archPageDict =3D {} + for obj in objs: + if obj.GetArch() not in archPageDict.keys(): + archPageDict[obj.GetArch()] =3D doxygen.Page(obj.GetAr= ch(), + 'lc_%s' % o= bj.GetArch()) + pageRoot.AddPage(archPageDict[obj.GetArch()]) + subArchRoot =3D archPageDict[obj.GetArch()] + classPage =3D doxygen.Page(obj.GetClassName(), + "lc_%s" % obj.GetClassName()) + comments =3D obj.GetComment() + if len(comments) !=3D 0: + classPage.AddDescription('
\n'.join(comments) + '\n') + subArchRoot.AddPage(classPage) + path =3D os.path.join(pObj.GetFileObj().GetPackageRootPath= (), obj.GetHeaderFile()) + path =3D path[len(pObj.GetWorkspace()) + 1:] + if len(comments) =3D=3D 0: + classPage.AddDescription('\copydoc %s

' % obj.GetHea= derFile()) + section =3D doxygen.Section('ref', 'Refer to Header File') + section.AddDescription('\link %s\n' % obj.GetHeaderFile()) + section.AddDescription(' \endlink

\n') + classPage.AddSection(section) + fullPath =3D os.path.join(pObj.GetFileObj().GetPackageRoot= Path(), obj.GetHeaderFile()) + + self.ProcessSourceFileForInclude(fullPath, pObj, configFil= e) + rootArray.append(pageRoot) + return rootArray + + def ProcessSourceFileForInclude(self, path, pObj, configFile, infObj= =3DNone): + """ + @param path the analysising file full path + @param pObj package object + @param configFile doxygen config file. + """ + if gInGui: + wx.Yield() + if not os.path.exists(path): + ErrorMsg('Source file path %s does not exist!' % path) + return + + if configFile.FileExists(path): + return + + try: + f =3D open(path, 'r') + lines =3D f.readlines() + f.close() + except IOError: + ErrorMsg('Fail to open file %s' % path) + return + + configFile.AddFile(path) + + no =3D 0 + for no in xrange(len(lines)): + if len(lines[no].strip()) =3D=3D 0: + continue + if lines[no].strip()[:2] in ['##', '//', '/*', '*/']: + continue + index =3D lines[no].lower().find('include') + #mo =3D IncludePattern.finditer(lines[no].lower()) + mo =3D re.match(r"^#\s*include\s+[<\"]([\\/\w.]+)[>\"]$", line= s[no].strip().lower()) + if not mo: + continue + mo =3D re.match(r"^[#\w\s]+[<\"]([\\/\w.]+)[>\"]$", lines[no].= strip()) + filePath =3D mo.groups()[0] + + if filePath =3D=3D None or len(filePath) =3D=3D 0: + continue + + # find header file in module's path firstly. + fullPath =3D None + + if os.path.exists(os.path.join(os.path.dirname(path), filePath= )): + # Find the file in current directory + fullPath =3D os.path.join(os.path.dirname(path), filePath)= .replace('\\', '/') + else: + # find in depedent package's include path + incObjs =3D pObj.GetFileObj().GetSectionObjectsByName('inc= ludes') + for incObj in incObjs: + incPath =3D os.path.join(pObj.GetFileObj().GetPackageR= ootPath(), incObj.GetPath()).strip() + incPath =3D os.path.realpath(os.path.join(incPath, fil= ePath)) + if os.path.exists(incPath): + fullPath =3D incPath + break + if infObj !=3D None: + pkgInfObjs =3D infObj.GetSectionObjectsByName('package= s') + for obj in pkgInfObjs: + decObj =3D dec.DECFile(os.path.join(pObj.GetWorksp= ace(), obj.GetPath())) + if not decObj: + ErrorMsg ('Fail to create pacakge object for %= s' % obj.GetPackageName()) + continue + if not decObj.Parse(): + ErrorMsg ('Fail to load package object for %s'= % obj.GetPackageName()) + continue + incObjs =3D decObj.GetSectionObjectsByName('includ= es') + for incObj in incObjs: + incPath =3D os.path.join(decObj.GetPackageRoot= Path(), incObj.GetPath()).replace('\\', '/') + if os.path.exists(os.path.join(incPath, filePa= th)): + fullPath =3D os.path.join(os.path.join(inc= Path, filePath)) + break + if fullPath !=3D None: + break + + if fullPath =3D=3D None and self.IsVerbose(): + self.Log('Can not resolve header file %s for file %s in pa= ckage %s\n' % (filePath, path, pObj.GetFileObj().GetFilename()), 'error') + return + else: + fullPath =3D fullPath.replace('\\', '/') + if self.IsVerbose(): + self.Log('Preprocessing: Add include file %s for file = %s\n' % (fullPath, path)) + #LogMsg ('Preprocessing: Add include file %s for file %s' = % (fullPath, path)) + self.ProcessSourceFileForInclude(fullPath, pObj, configFil= e, infObj) + + def AddAllIncludeFiles(self, pObj, configFile): + objs =3D pObj.GetFileObj().GetSectionObjectsByName('includes') + for obj in objs: + incPath =3D os.path.join(pObj.GetFileObj().GetPackageRootPath(= ), obj.GetPath()) + for root, dirs, files in os.walk(incPath): + for dir in dirs: + if dir.lower() in _ignore_dir: + dirs.remove(dir) + for file in files: + path =3D os.path.normpath(os.path.join(root, file)) + configFile.AddFile(path.replace('/', '\\')) + + def GeneratePcdSubPages(self, pObj, configFile): + """ + Generate sub pages for package's PCD definition. + @param pObj package object + @param configFile config file object + """ + rootArray =3D [] + objs =3D pObj.GetFileObj().GetSectionObjectsByName('pcd') + if len(objs) =3D=3D 0: + return [] + + pcdRootPage =3D doxygen.Page('PCD', 'pcd_root_page') + typeRootPageDict =3D {} + typeArchRootPageDict =3D {} + for obj in objs: + if obj.GetPcdType() not in typeRootPageDict.keys(): + typeRootPageDict[obj.GetPcdType()] =3D doxygen.Page(obj.Ge= tPcdType(), 'pcd_%s_root_page' % obj.GetPcdType()) + pcdRootPage.AddPage(typeRootPageDict[obj.GetPcdType()]) + typeRoot =3D typeRootPageDict[obj.GetPcdType()] + if self._arch !=3D None: + pcdPage =3D doxygen.Page('%s' % obj.GetPcdName(), + 'pcd_%s_%s_%s' % (obj.GetPcdType()= , obj.GetArch(), obj.GetPcdName().split('.')[1])) + pcdPage.AddDescription('
\n'.join(obj.GetComment()) + '=
\n') + section =3D doxygen.Section('PCDinformation', 'PCD Informa= tion') + desc =3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' % obj.GetPcdNam= e().split('.')[1] + desc +=3D '' % obj.GetPcdNam= e().split('.')[0] + desc +=3D '' % obj.GetPcdTok= en() + desc +=3D '' % obj.GetPcdDat= aType() + desc +=3D '' % obj.GetPcdVal= ue() + desc +=3D '' + desc +=3D '
Name
Token Space
Token number
Data Type
Default Value
%s
%s
%s
%s
%s
' + section.AddDescription(desc) + pcdPage.AddSection(section) + typeRoot.AddPage(pcdPage) + else: + keystr =3D obj.GetPcdType() + obj.GetArch() + if keystr not in typeArchRootPageDict.keys(): + typeArchRootPage =3D doxygen.Page(obj.GetArch(), 'pcd_= %s_%s_root_page' % (obj.GetPcdType(), obj.GetArch())) + typeArchRootPageDict[keystr] =3D typeArchRootPage + typeRoot.AddPage(typeArchRootPage) + typeArchRoot =3D typeArchRootPageDict[keystr] + pcdPage =3D doxygen.Page('%s' % obj.GetPcdName(), + 'pcd_%s_%s_%s' % (obj.GetPcdType()= , obj.GetArch(), obj.GetPcdName().split('.')[1])) + pcdPage.AddDescription('
\n'.join(obj.GetComment()) + '=
\n') + section =3D doxygen.Section('PCDinformation', 'PCD Informa= tion') + desc =3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' % obj.GetPcdNam= e().split('.')[1] + desc +=3D '' % obj.GetPcdNam= e().split('.')[0] + desc +=3D '' % obj.GetPcdTok= en() + desc +=3D '' % obj.GetPcdDat= aType() + desc +=3D '' % obj.GetPcdVal= ue() + desc +=3D '' + desc +=3D '
Name
Token Space
Token number
Data Type
Default Value
%s
%s
%s
%s
%s
' + section.AddDescription(desc) + pcdPage.AddSection(section) + typeArchRoot.AddPage(pcdPage) + return [pcdRootPage] + + def _GenerateGuidSubPage(self, pObj, obj, configFile): + guidPage =3D doxygen.Page('%s' % obj.GetName(), + 'guid_%s_%s' % (obj.GetArch(), obj.GetName= ())) + comments =3D obj.GetComment() + if len(comments) !=3D 0: + guidPage.AddDescription('
'.join(obj.GetComment()) + '
') + section =3D doxygen.Section('BasicGuidInfo', 'GUID Information') + desc =3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' % obj.GetName() + desc +=3D '' % obj.GetGuid() + desc +=3D '' + desc +=3D '
GUID\'s Guid Name
GUID\'s Guid
%s%s
' + section.AddDescription(desc) + guidPage.AddSection(section) + refFile =3D self.FindHeaderFileForGuid(pObj, obj.GetName(), config= File) + if refFile: + relPath =3D refFile[len(pObj.GetWorkspace()) + 1:] + if len(comments) =3D=3D 0: + guidPage.AddDescription(' \\copydoc %s
' % relPath) + + section =3D doxygen.Section('ref', 'Refer to Header File') + section.AddDescription('\link %s\n' % relPath) + section.AddDescription('\endlink\n') + self.ProcessSourceFileForInclude(refFile, pObj, configFile) + guidPage.AddSection(section) + return guidPage + + def GenerateGuidSubPages(self, pObj, configFile): + """ + Generate sub pages for package's GUID definition. + @param pObj package object + @param configFilf doxygen config file object + """ + pageRoot =3D doxygen.Page('GUID', 'guid_root_page') + objs =3D pObj.GetFileObj().GetSectionObjectsByName('guids', self._= arch) + if len(objs) =3D=3D 0: return [] + if self._arch !=3D None: + for obj in objs: + pageRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, conf= igFile)) + else: + guidArchRootPageDict =3D {} + for obj in objs: + if obj.GetArch() not in guidArchRootPageDict.keys(): + guidArchRoot =3D doxygen.Page(obj.GetArch(), 'guid_arc= h_root_%s' % obj.GetArch()) + pageRoot.AddPage(guidArchRoot) + guidArchRootPageDict[obj.GetArch()] =3D guidArchRoot + guidArchRoot =3D guidArchRootPageDict[obj.GetArch()] + guidArchRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, = configFile)) + return [pageRoot] + + def _GeneratePpiSubPage(self, pObj, obj, configFile): + guidPage =3D doxygen.Page(obj.GetName(), 'ppi_page_%s' % obj.GetNa= me()) + comments =3D obj.GetComment() + if len(comments) !=3D 0: + guidPage.AddDescription('
'.join(obj.GetComment()) + '
') + section =3D doxygen.Section('BasicPpiInfo', 'PPI Information') + desc =3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' % obj.GetName() + desc +=3D '' % obj.GetGuid() + desc +=3D '' + desc +=3D '
PPI\'s Guid Name
PPI\'s Guid
%s%s
' + section.AddDescription(desc) + guidPage.AddSection(section) + refFile =3D self.FindHeaderFileForGuid(pObj, obj.GetName(), config= File) + if refFile: + relPath =3D refFile[len(pObj.GetWorkspace()) + 1:] + if len(comments) =3D=3D 0: + guidPage.AddDescription(' \\copydoc %s
' % relPath) + section =3D doxygen.Section('ref', 'Refer to Header File') + section.AddDescription('\link %s\n' % relPath) + section.AddDescription('\endlink\n') + self.ProcessSourceFileForInclude(refFile, pObj, configFile) + guidPage.AddSection(section) + + return guidPage + + def GeneratePpiSubPages(self, pObj, configFile): + """ + Generate sub pages for package's GUID definition. + @param pObj package object + @param configFilf doxygen config file object + """ + pageRoot =3D doxygen.Page('PPI', 'ppi_root_page') + objs =3D pObj.GetFileObj().GetSectionObjectsByName('ppis', self._a= rch) + if len(objs) =3D=3D 0: return [] + if self._arch !=3D None: + for obj in objs: + pageRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, confi= gFile)) + else: + guidArchRootPageDict =3D {} + for obj in objs: + if obj.GetArch() not in guidArchRootPageDict.keys(): + guidArchRoot =3D doxygen.Page(obj.GetArch(), 'ppi_arch= _root_%s' % obj.GetArch()) + pageRoot.AddPage(guidArchRoot) + guidArchRootPageDict[obj.GetArch()] =3D guidArchRoot + guidArchRoot =3D guidArchRootPageDict[obj.GetArch()] + guidArchRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, c= onfigFile)) + return [pageRoot] + + def _GenerateProtocolSubPage(self, pObj, obj, configFile): + guidPage =3D doxygen.Page(obj.GetName(), 'protocol_page_%s' % obj.= GetName()) + comments =3D obj.GetComment() + if len(comments) !=3D 0: + guidPage.AddDescription('
'.join(obj.GetComment()) + '
') + section =3D doxygen.Section('BasicProtocolInfo', 'PROTOCOL Informa= tion') + desc =3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' % obj.GetName() + desc +=3D '' % obj.GetGuid() + desc +=3D '' + desc +=3D '
PROTOCOL\'s Guid Name
PROTOCOL\'s Guid
%s%s
' + section.AddDescription(desc) + guidPage.AddSection(section) + + refFile =3D self.FindHeaderFileForGuid(pObj, obj.GetName(), config= File) + if refFile: + relPath =3D refFile[len(pObj.GetWorkspace()) + 1:] + if len(comments) =3D=3D 0: + guidPage.AddDescription(' \\copydoc %s
' % relPath) + section =3D doxygen.Section('ref', 'Refer to Header File') + section.AddDescription('\link %s\n' % relPath) + section.AddDescription('\endlink\n') + self.ProcessSourceFileForInclude(refFile, pObj, configFile) + guidPage.AddSection(section) + + return guidPage + + def GenerateProtocolSubPages(self, pObj, configFile): + """ + Generate sub pages for package's GUID definition. + @param pObj package object + @param configFilf doxygen config file object + """ + pageRoot =3D doxygen.Page('PROTOCOL', 'protocol_root_page') + objs =3D pObj.GetFileObj().GetSectionObjectsByName('protocols', se= lf._arch) + if len(objs) =3D=3D 0: return [] + if self._arch !=3D None: + for obj in objs: + pageRoot.AddPage(self._GenerateProtocolSubPage(pObj, obj, = configFile)) + else: + guidArchRootPageDict =3D {} + for obj in objs: + if obj.GetArch() not in guidArchRootPageDict.keys(): + guidArchRoot =3D doxygen.Page(obj.GetArch(), 'protocol= _arch_root_%s' % obj.GetArch()) + pageRoot.AddPage(guidArchRoot) + guidArchRootPageDict[obj.GetArch()] =3D guidArchRoot + guidArchRoot =3D guidArchRootPageDict[obj.GetArch()] + guidArchRoot.AddPage(self._GenerateProtocolSubPage(pObj, o= bj, configFile)) + return [pageRoot] + + def FindHeaderFileForGuid(self, pObj, name, configFile): + """ + For declaration header file for GUID/PPI/Protocol. + + @param pObj package object + @param name guid/ppi/protocol's name + @param configFile config file object + + @return full path of header file and None if not found. + """ + startPath =3D pObj.GetFileObj().GetPackageRootPath() + incPath =3D os.path.join(startPath, 'Include').replace('\\', '/= ') + # if /include exist, then search header under it. + if os.path.exists(incPath): + startPath =3D incPath + + for root, dirs, files in os.walk(startPath): + for dir in dirs: + if dir.lower() in _ignore_dir: + dirs.remove(dir) + for file in files: + fPath =3D os.path.join(root, file) + if not IsCHeaderFile(fPath): + continue + try: + f =3D open(fPath, 'r') + lines =3D f.readlines() + f.close() + except IOError: + self.Log('Fail to open file %s\n' % fPath) + continue + for line in lines: + if line.find(name) !=3D -1 and \ + line.find('extern') !=3D -1: + return fPath.replace('\\', '/') + return None + + def GetPackageModuleList(self, pObj): + """ + Get all module's INF path under package's root path + @param pObj package object + @return arrary of INF full path + """ + mArray =3D [] + packPath =3D pObj.GetFileObj().GetPackageRootPath() + if not os.path.exists: + return None + for root, dirs, files in os.walk(packPath): + for dir in dirs: + if dir.lower() in _ignore_dir: + dirs.remove(dir) + for file in files: + if CheckPathPostfix(file, 'inf'): + fPath =3D os.path.join(root, file).replace('\\', '/') + mArray.append(fPath) + return mArray + + def GenerateModulePages(self, pObj, configFile): + """ + Generate sub pages for package's module which is under the package + root directory. + + @param pObj package object + @param configFilf doxygen config file object + """ + infList =3D self.GetPackageModuleList(pObj) + rootPages =3D [] + libObjs =3D [] + modObjs =3D [] + for infpath in infList: + infObj =3D inf.INFFile(infpath) + #infObj =3D INFFileObject.INFFile (pObj.GetWorkspacePath(), + # inf) + if not infObj: + self.Log('Fail create INF object for %s' % inf) + continue + if not infObj.Parse(): + self.Log('Fail to load INF file %s' % inf) + continue + if infObj.GetProduceLibraryClass() !=3D None: + libObjs.append(infObj) + else: + modObjs.append(infObj) + + if len(libObjs) !=3D 0: + libRootPage =3D doxygen.Page('Libraries', 'lib_root_page') + rootPages.append(libRootPage) + for libInf in libObjs: + libRootPage.AddPage(self.GenerateModulePage(pObj, libInf, = configFile, True)) + + if len(modObjs) !=3D 0: + modRootPage =3D doxygen.Page('Modules', 'module_root_page') + rootPages.append(modRootPage) + for modInf in modObjs: + modRootPage.AddPage(self.GenerateModulePage(pObj, modInf, = configFile, False)) + + return rootPages + + def GenerateModulePage(self, pObj, infObj, configFile, isLib): + """ + Generate page for a module/library. + @param infObj INF file object for module/library + @param configFile doxygen config file object + @param isLib Whether this module is libary + + @param module doxygen page object + """ + workspace =3D pObj.GetWorkspace() + refDecObjs =3D [] + for obj in infObj.GetSectionObjectsByName('packages'): + decObj =3D dec.DECFile(os.path.join(workspace, obj.GetPath())) + if not decObj: + ErrorMsg ('Fail to create pacakge object for %s' % obj.Get= PackageName()) + continue + if not decObj.Parse(): + ErrorMsg ('Fail to load package object for %s' % obj.GetPa= ckageName()) + continue + refDecObjs.append(decObj) + + modPage =3D doxygen.Page('%s' % infObj.GetBaseName(), + 'module_%s' % infObj.GetBaseName()) + modPage.AddDescription(infObj.GetFileHeader()) + + basicInfSection =3D doxygen.Section('BasicModuleInformation', 'Bas= ic Module Information') + desc =3D "" + for obj in infObj.GetSectionObjectsByName('defines'): + key =3D obj.GetKey() + value =3D obj.GetValue() + if key not in _inf_key_description_mapping_table.keys(): conti= nue + if key =3D=3D 'LIBRARY_CLASS' and value.find('|') !=3D -1: + clsname, types =3D value.split('|') + desc +=3D '' + desc +=3D '' % _inf_key_description_mapp= ing_table[key] + desc +=3D '' % clsname + desc +=3D '' + + desc +=3D '' + desc +=3D '' + desc +=3D '' % types + desc +=3D '' + else: + desc +=3D '' + desc +=3D '' % _inf_key_description_mapp= ing_table[key] + if key =3D=3D 'EFI_SPECIFICATION_VERSION' and value =3D=3D= '0x00020000': + value =3D '2.0' + desc +=3D '' % value + desc +=3D '' + desc +=3D '
%s%s
Supported Module Types%s
%s%s
' + basicInfSection.AddDescription(desc) + modPage.AddSection(basicInfSection) + + # Add protocol section + data =3D [] + for obj in infObj.GetSectionObjectsByName('pcd', self._arch): + data.append(obj.GetPcdName().strip()) + if len(data) !=3D 0: + s =3D doxygen.Section('Pcds', 'Pcds') + desc =3D "" + desc +=3D '' + for item in data: + desc +=3D '' + desc +=3D '' % item.split('.')[1] + desc +=3D '' % item.split('.')[0] + pkgbasename =3D self.SearchPcdPackage(item, workspace, ref= DecObjs) + desc +=3D '' % pkgbasename + desc +=3D '' + desc +=3D "
PCD NameTokenSpacePackage
%s%s%s
" + s.AddDescription(desc) + modPage.AddSection(s) + + # Add protocol section + #sects =3D infObj.GetSectionByString('protocol') + data =3D [] + #for sect in sects: + for obj in infObj.GetSectionObjectsByName('protocol', self._arch): + data.append(obj.GetName().strip()) + if len(data) !=3D 0: + s =3D doxygen.Section('Protocols', 'Protocols') + desc =3D "" + desc +=3D '' + for item in data: + desc +=3D '' + desc +=3D '' % item + pkgbasename =3D self.SearchProtocolPackage(item, workspace= , refDecObjs) + desc +=3D '' % pkgbasename + desc +=3D '' + desc +=3D "
NamePackage
%s%s
" + s.AddDescription(desc) + modPage.AddSection(s) + + # Add ppi section + #sects =3D infObj.GetSectionByString('ppi') + data =3D [] + #for sect in sects: + for obj in infObj.GetSectionObjectsByName('ppi', self._arch): + data.append(obj.GetName().strip()) + if len(data) !=3D 0: + s =3D doxygen.Section('Ppis', 'Ppis') + desc =3D "" + desc +=3D '' + for item in data: + desc +=3D '' + desc +=3D '' % item + pkgbasename =3D self.SearchPpiPackage(item, workspace, ref= DecObjs) + desc +=3D '' % pkgbasename + desc +=3D '' + desc +=3D "
NamePackage
%s%s
" + s.AddDescription(desc) + modPage.AddSection(s) + + # Add guid section + #sects =3D infObj.GetSectionByString('guid') + data =3D [] + #for sect in sects: + for obj in infObj.GetSectionObjectsByName('guid', self._arch): + data.append(obj.GetName().strip()) + if len(data) !=3D 0: + s =3D doxygen.Section('Guids', 'Guids') + desc =3D "" + desc +=3D '' + for item in data: + desc +=3D '' + desc +=3D '' % item + pkgbasename =3D self.SearchGuidPackage(item, workspace, re= fDecObjs) + desc +=3D '' % pkgbasename + desc +=3D '' + desc +=3D "
NamePackage
%s%s
" + s.AddDescription(desc) + modPage.AddSection(s) + + section =3D doxygen.Section('LibraryClasses', 'Library Classes') + desc =3D "" + desc +=3D '' + if isLib: + desc +=3D '' + desc +=3D '' % infObj.GetProduceLibraryClass() + desc +=3D '' + try: + pkgname, hPath =3D self.SearchLibraryClassHeaderFile(infOb= j.GetProduceLibraryClass(), + workspace, + refDecObjs) + except: + self.Log ('fail to get package header file for lib class %= s' % infObj.GetProduceLibraryClass()) + pkgname =3D 'NULL' + hPath =3D 'NULL' + desc +=3D '' % pkgname + if hPath !=3D "NULL": + desc +=3D '' % hPath + else: + desc +=3D '' % hPath + desc +=3D '' + for lcObj in infObj.GetSectionObjectsByName('libraryclasses', self= ._arch): + desc +=3D '' + desc +=3D '' % lcObj.GetClass() + retarr =3D self.SearchLibraryClassHeaderFile(lcObj.GetClass(), + workspace, + refDecObjs) + if retarr !=3D None: + pkgname, hPath =3D retarr + else: + self.Log('Fail find the library class %s definition from m= odule %s dependent package!' % (lcObj.GetClass(), infObj.GetFilename()), 'e= rror') + pkgname =3D 'NULL' + hPath =3D 'NULL' + desc +=3D '' + desc +=3D '' % pkgname + desc +=3D '' % hPath + desc +=3D '' + desc +=3D "
NameTypePack= ageHeader File
%sProduce%s\link %s \endlink%s
%sConsume%s\link %s \endlink
" + section.AddDescription(desc) + modPage.AddSection(section) + + section =3D doxygen.Section('SourceFiles', 'Source Files') + section.AddDescription('

    \n') + for obj in infObj.GetSourceObjects(self._arch, self._tooltag): + sPath =3D infObj.GetModuleRootPath() + sPath =3D os.path.join(sPath, obj.GetSourcePath()).replace('\\= ', '/').strip() + if sPath.lower().endswith('.uni') or sPath.lower().endswith('.= s') or sPath.lower().endswith('.asm') or sPath.lower().endswith('.nasm'): + newPath =3D self.TranslateUniFile(sPath) + configFile.AddFile(newPath) + newPath =3D newPath[len(pObj.GetWorkspace()) + 1:] + section.AddDescription('
  • \link %s \endlink
  • ' % n= ewPath) + else: + self.ProcessSourceFileForInclude(sPath, pObj, configFile, = infObj) + sPath =3D sPath[len(pObj.GetWorkspace()) + 1:] + section.AddDescription('
  • \link %s \endlink
  • ' % sPa= th) + section.AddDescription('
\n') + modPage.AddSection(section) + + #sects =3D infObj.GetSectionByString('depex') + data =3D [] + #for sect in sects: + for obj in infObj.GetSectionObjectsByName('depex'): + data.append(str(obj)) + if len(data) !=3D 0: + s =3D doxygen.Section('DependentSection', 'Module Dependencies= ') + s.AddDescription('
'.join(data)) + modPage.AddSection(s) + + return modPage + + def TranslateUniFile(self, path): + newpath =3D path + '.dox' + #import core.textfile as textfile + #file =3D textfile.TextFile(path) + + try: + file =3D open(path, 'rb') + except (IOError, OSError), msg: + return None + + t =3D file.read() + file.close() + + output =3D '/** @file \n' + #output =3D '' + arr =3D t.split('\r\n') + for line in arr: + if line.find('@file') !=3D -1: + continue + if line.find('*/') !=3D -1: + continue + line =3D line.strip() + if line.strip().startswith('/'): + arr =3D line.split(' ') + if len(arr) > 1: + line =3D ' '.join(arr[1:]) + else: + continue + output +=3D '%s
\n' % line + output +=3D '**/' + + if os.path.exists(newpath): + os.remove(newpath) + + file =3D open(newpath, "w") + file.write(output) + file.close() + return newpath + + def SearchPcdPackage(self, pcdname, workspace, decObjs): + for decObj in decObjs: + for pcd in decObj.GetSectionObjectsByName('pcd'): + if pcdname =3D=3D pcd.GetPcdName(): + return decObj.GetBaseName() + return None + + def SearchProtocolPackage(self, protname, workspace, decObjs): + for decObj in decObjs: + for proto in decObj.GetSectionObjectsByName('protocol'): + if protname =3D=3D proto.GetName(): + return decObj.GetBaseName() + return None + + def SearchPpiPackage(self, ppiname, workspace, decObjs): + for decObj in decObjs: + for ppi in decObj.GetSectionObjectsByName('ppi'): + if ppiname =3D=3D ppi.GetName(): + return decObj.GetBaseName() + return None + + def SearchGuidPackage(self, guidname, workspace, decObjs): + for decObj in decObjs: + for guid in decObj.GetSectionObjectsByName('guid'): + if guidname =3D=3D guid.GetName(): + return decObj.GetBaseName() + return None + + def SearchLibraryClassHeaderFile(self, className, workspace, decObjs): + for decObj in decObjs: + for cls in decObj.GetSectionObjectsByName('libraryclasses'): + if cls.GetClassName().strip() =3D=3D className: + path =3D cls.GetHeaderFile().strip() + path =3D os.path.join(decObj.GetPackageRootPath(), pat= h) + path =3D path[len(workspace) + 1:] + return decObj.GetBaseName(), path.replace('\\', '/') + + return None + + def _ConvertPathToDoxygen(self, path, pObj): + pRootPath =3D pObj.GetWorkspace() + path =3D path[len(pRootPath) + 1:] + return path.replace('\\', '/') + +def IsCHeaderFile(path): + return CheckPathPostfix(path, 'h') + +def CheckPathPostfix(path, str): + index =3D path.rfind('.') + if index =3D=3D -1: + return False + if path[index + 1:].lower() =3D=3D str.lower(): + return True + return False diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2= /model/doxygengen_spec.py b/BaseTools/Scripts/PackageDocumentTools/plugins/= EdkPlugins/edk2/model/doxygengen_spec.py new file mode 100644 index 0000000..876da13 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2/model/= doxygengen_spec.py @@ -0,0 +1,1092 @@ +## @file +# +# This file produce action class to generate doxygen document for edk2 cod= ebase. +# The action classes are shared by GUI and command line tools. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +import plugins.EdkPlugins.basemodel.doxygen as doxygen +import os +try: + import wx + gInGui =3D True +except: + gInGui =3D False +import re +import plugins.EdkPlugins.edk2.model.inf as inf +import plugins.EdkPlugins.edk2.model.dec as dec +from plugins.EdkPlugins.basemodel.message import * + +_ignore_dir =3D ['.svn', '_svn', 'cvs'] +_inf_key_description_mapping_table =3D { + 'INF_VERSION':'Version of INF file specification', + #'BASE_NAME':'Module Name', + 'FILE_GUID':'Module Guid', + 'MODULE_TYPE': 'Module Type', + 'VERSION_STRING': 'Module Version', + 'LIBRARY_CLASS': 'Produced Library Class', + 'EFI_SPECIFICATION_VERSION': 'UEFI Specification Version', + 'PI_SPECIFICATION_VERSION': 'PI Specification Version', + 'ENTRY_POINT': 'Module Entry Point Function', + 'CONSTRUCTOR': 'Library Constructor Function' +} + +_dec_key_description_mapping_table =3D { + 'DEC_SPECIFICATION': 'Version of DEC file specification', + 'PACKAGE_GUID': 'Package Guid' +} +class DoxygenAction: + """This is base class for all doxygen action. + """ + + def __init__(self, doxPath, chmPath, outputPath, projname, mode=3D'htm= l', log=3DNone, verbose=3DFalse): + """Constructor function. + @param doxPath the obosolution path of doxygen execute fi= le. + @param outputPath the obosolution output path. + @param log log function for output message + """ + self._doxPath =3D doxPath + self._chmPath =3D chmPath + self._outputPath =3D outputPath + self._projname =3D projname + self._configFile =3D None # doxygen config file is use= d by doxygen exe file + self._indexPageFile =3D None # doxygen page file for inde= x page. + self._log =3D log + self._mode =3D mode + self._verbose =3D verbose + self._doxygenCallback =3D None + self._chmCallback =3D None + + def Log(self, message, level=3D'info'): + if self._log !=3D None: + self._log(message, level) + + def IsVerbose(self): + return self._verbose + + def Generate(self): + """Generate interface called by outer directly""" + self.Log(">>>>>> Start generate doxygen document for %s... Zzz....= \n" % self._projname) + + # create doxygen config file at first + self._configFile =3D doxygen.DoxygenConfigFile() + self._configFile.SetOutputDir(self._outputPath) + + self._configFile.SetWarningFilePath(os.path.join(self._outputPath,= 'warning.txt')) + if self._mode.lower() =3D=3D 'html': + self._configFile.SetHtmlMode() + else: + self._configFile.SetChmMode() + + self.Log(" >>>>>> Initialize doxygen config file...Zzz...\n") + self.InitializeConfigFile() + + self.Log(" >>>>>> Generate doxygen index page file...Zzz...\n") + indexPagePath =3D self.GenerateIndexPage() + if indexPagePath =3D=3D None: + self.Log("Fail to generate index page!\n", 'error') + return False + else: + self.Log("Success to create doxygen index page file %s \n" % i= ndexPagePath) + + # Add index page doxygen file to file list. + self._configFile.AddFile(indexPagePath) + + # save config file to output path + configFilePath =3D os.path.join(self._outputPath, self._projname += '.doxygen_config') + self._configFile.Generate(configFilePath) + self.Log(" <<<<<< Success Save doxygen config file to %s...\n" = % configFilePath) + + # launch doxygen tool to generate document + if self._doxygenCallback !=3D None: + self.Log(" >>>>>> Start doxygen process...Zzz...\n") + if not self._doxygenCallback(self._doxPath, configFilePath): + return False + else: + self.Log("Fail to create doxygen process!", 'error') + return False + + return True + + def InitializeConfigFile(self): + """Initialize config setting for doxygen project. It will be invok= ed after config file + object is created. Inherited class should implement it. + """ + + def GenerateIndexPage(self): + """Generate doxygen index page. Inherited class should implement i= t.""" + return None + + def RegisterCallbackDoxygenProcess(self, callback): + self._doxygenCallback =3D callback + + def RegisterCallbackCHMProcess(self, callback): + self._chmCallback =3D callback + +class PlatformDocumentAction(DoxygenAction): + """Generate platform doxygen document, will be implement at future.""" + +class PackageDocumentAction(DoxygenAction): + """Generate package reference document""" + + def __init__(self, doxPath, chmPath, outputPath, pObj, mode=3D'html', = log=3DNone, arch=3DNone, tooltag=3DNone, + macros=3D[], onlyInclude=3DFalse, verbose=3DFalse): + DoxygenAction.__init__(self, doxPath, chmPath, outputPath, pObj.Ge= tName(), mode, log, verbose) + self._pObj =3D pObj + self._arch =3D arch + self._tooltag =3D tooltag + self._macros =3D macros + self._onlyIncludeDocument =3D onlyInclude + + def InitializeConfigFile(self): + if self._arch =3D=3D 'IA32': + self._configFile.AddPreDefined('MDE_CPU_IA32') + elif self._arch =3D=3D 'X64': + self._configFile.AddPreDefined('MDE_CPU_X64') + elif self._arch =3D=3D 'IPF': + self._configFile.AddPreDefined('MDE_CPU_IPF') + elif self._arch =3D=3D 'EBC': + self._configFile.AddPreDefined('MDE_CPU_EBC') + else: + self._arch =3D None + self._configFile.AddPreDefined('MDE_CPU_IA32') + self._configFile.AddPreDefined('MDE_CPU_X64') + self._configFile.AddPreDefined('MDE_CPU_IPF') + self._configFile.AddPreDefined('MDE_CPU_EBC') + self._configFile.AddPreDefined('MDE_CPU_ARM') + + for macro in self._macros: + self._configFile.AddPreDefined(macro) + + namestr =3D self._pObj.GetName() + if self._arch !=3D None: + namestr +=3D '[%s]' % self._arch + if self._tooltag !=3D None: + namestr +=3D '[%s]' % self._tooltag + self._configFile.SetProjectName(namestr) + self._configFile.SetStripPath(self._pObj.GetWorkspace()) + self._configFile.SetProjectVersion(self._pObj.GetFileObj().GetVers= ion()) + self._configFile.AddPattern('*.decdoxygen') + + if self._tooltag.lower() =3D=3D 'msft': + self._configFile.AddPreDefined('_MSC_EXTENSIONS') + elif self._tooltag.lower() =3D=3D 'gnu': + self._configFile.AddPreDefined('__GNUC__') + elif self._tooltag.lower() =3D=3D 'intel': + self._configFile.AddPreDefined('__INTEL_COMPILER') + else: + self._tooltag =3D None + self._configFile.AddPreDefined('_MSC_EXTENSIONS') + self._configFile.AddPreDefined('__GNUC__') + self._configFile.AddPreDefined('__INTEL_COMPILER') + + self._configFile.AddPreDefined('ASM_PFX=3D ') + self._configFile.AddPreDefined('OPTIONAL=3D ') + + def GenerateIndexPage(self): + """Generate doxygen index page. Inherited class should implement i= t.""" + fObj =3D self._pObj.GetFileObj() + pdObj =3D doxygen.DoxygenFile('%s Package Document' % self._pObj.= GetName(), + '%s.decdoxygen' % self._pObj.GetFilen= ame()) + self._configFile.AddFile(pdObj.GetFilename()) + pdObj.AddDescription(fObj.GetFileHeader()) + + defSection =3D fObj.GetSectionByName('defines')[0] + baseSection =3D doxygen.Section('PackageBasicInformation', 'Packag= e Basic Information') + descr =3D '' + for obj in defSection.GetObjects(): + if obj.GetKey() in _dec_key_description_mapping_table.keys(): + descr +=3D '' + descr +=3D '' % _dec_key_description_map= ping_table[obj.GetKey()] + descr +=3D '' % obj.GetValue() + descr +=3D '' + descr +=3D '
%s%s

' + baseSection.AddDescription(descr) + pdObj.AddSection(baseSection) + + knownIssueSection =3D doxygen.Section('Known_Issue_section', 'Know= n Issue') + knownIssueSection.AddDescription('
    ') + knownIssueSection.AddDescription('
  • OPTIONAL macro for function= parameter can not be dealed with doxygen, so it disapear in this document!=
  • ') + knownIssueSection.AddDescription('
') + pdObj.AddSection(knownIssueSection) + + self.AddAllIncludeFiles(self._pObj, self._configFile) + pages =3D self.GenerateIncludesSubPage(self._pObj, self._configFil= e) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + pages =3D self.GenerateLibraryClassesSubPage(self._pObj, self._con= figFile) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + pages =3D self.GeneratePcdSubPages(self._pObj, self._configFile) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + pages =3D self.GenerateGuidSubPages(self._pObj, self._configFile) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + pages =3D self.GeneratePpiSubPages(self._pObj, self._configFile) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + pages =3D self.GenerateProtocolSubPages(self._pObj, self._configFi= le) + if len(pages) !=3D 0: + pdObj.AddPages(pages) + if not self._onlyIncludeDocument: + pdObj.AddPages(self.GenerateModulePages(self._pObj, self._conf= igFile)) + + pdObj.Save() + return pdObj.GetFilename() + + def GenerateIncludesSubPage(self, pObj, configFile): + # by default add following path as include path to config file + pkpath =3D pObj.GetFileObj().GetPackageRootPath() + configFile.AddIncludePath(os.path.join(pkpath, 'Include')) + configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Library= ')) + configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Protoco= l')) + configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Ppi')) + configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Guid')) + configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Industr= yStandard')) + + rootArray =3D [] + pageRoot =3D doxygen.Page("Public Includes", "%s_public_includes" = % pObj.GetName()) + objs =3D pObj.GetFileObj().GetSectionObjectsByName('includes') + if len(objs) =3D=3D 0: return [] + + for obj in objs: + # Add path to include path + path =3D os.path.join(pObj.GetFileObj().GetPackageRootPath(), = obj.GetPath()) + configFile.AddIncludePath(path) + + # only list common folder's include file + if obj.GetArch().lower() !=3D 'common': + continue + + bNeedAddIncludePage =3D False + topPage =3D doxygen.Page(self._ConvertPathToDoxygen(path, pObj= ), 'public_include_top') + + topPage.AddDescription('
    \n') + for file in os.listdir(path): + if file.lower() in _ignore_dir: continue + fullpath =3D os.path.join(path, file) + if os.path.isfile(fullpath): + self.ProcessSourceFileForInclude(fullpath, pObj, confi= gFile) + topPage.AddDescription('
  • \link %s\endlink
  • \n'= % self._ConvertPathToDoxygen(fullpath, pObj)) + else: + if file.lower() in ['library', 'protocol', 'guid', 'pp= i', 'ia32', 'x64', 'ipf', 'ebc', 'arm', 'pi', 'uefi', 'aarch64']: + continue + bNeedAddSubPage =3D False + subpage =3D doxygen.Page(self._ConvertPathToDoxygen(fu= llpath, pObj), 'public_include_%s' % file) + subpage.AddDescription('
      \n') + for subfile in os.listdir(fullpath): + if subfile.lower() in _ignore_dir: continue + bNeedAddSubPage =3D True + subfullpath =3D os.path.join(fullpath, subfile) + self.ProcessSourceFileForInclude(subfullpath, pObj= , configFile) + subpage.AddDescription('
    • \link %s \endlink \n' % self._ConvertPathToDoxygen(subfullpath, pObj)) + subpage.AddDescription('
    \n') + if bNeedAddSubPage: + bNeedAddIncludePage =3D True + pageRoot.AddPage(subpage) + topPage.AddDescription('
\n') + if bNeedAddIncludePage: + pageRoot.AddPage(topPage) + + if pageRoot.GetSubpageCount() !=3D 0: + return [pageRoot] + else: + return [] + + def GenerateLibraryClassesSubPage(self, pObj, configFile): + """ + Generate sub page for library class for package. + One DEC file maybe contains many library class sections + for different architecture. + + @param fObj DEC file object. + """ + rootArray =3D [] + pageRoot =3D doxygen.Page("Library Class", "%s_libraryclass" % pOb= j.GetName()) + objs =3D pObj.GetFileObj().GetSectionObjectsByName('libraryclass',= self._arch) + if len(objs) =3D=3D 0: return [] + + if self._arch !=3D None: + for obj in objs: + classPage =3D doxygen.Page(obj.GetClassName(), + "lc_%s" % obj.GetClassName()) + comments =3D obj.GetComment() + if len(comments) !=3D 0: + classPage.AddDescription('
\n'.join(comments) + '\n') + pageRoot.AddPage(classPage) + path =3D os.path.join(pObj.GetFileObj().GetPackageRootPath= (), obj.GetHeaderFile()) + path =3D path[len(pObj.GetWorkspace()) + 1:] + if len(comments) =3D=3D 0: + classPage.AddDescription('\copydoc %s

' % obj.GetHea= derFile()) + section =3D doxygen.Section('ref', 'Refer to Header File') + section.AddDescription('\link %s\n' % obj.GetHeaderFile()) + section.AddDescription(' \endlink

\n') + classPage.AddSection(section) + fullPath =3D os.path.join(pObj.GetFileObj().GetPackageRoot= Path(), obj.GetHeaderFile()) + self.ProcessSourceFileForInclude(fullPath, pObj, configFil= e) + else: + archPageDict =3D {} + for obj in objs: + if obj.GetArch() not in archPageDict.keys(): + archPageDict[obj.GetArch()] =3D doxygen.Page(obj.GetAr= ch(), + 'lc_%s' % o= bj.GetArch()) + pageRoot.AddPage(archPageDict[obj.GetArch()]) + subArchRoot =3D archPageDict[obj.GetArch()] + classPage =3D doxygen.Page(obj.GetClassName(), + "lc_%s" % obj.GetClassName()) + comments =3D obj.GetComment() + if len(comments) !=3D 0: + classPage.AddDescription('
\n'.join(comments) + '\n') + subArchRoot.AddPage(classPage) + path =3D os.path.join(pObj.GetFileObj().GetPackageRootPath= (), obj.GetHeaderFile()) + path =3D path[len(pObj.GetWorkspace()) + 1:] + if len(comments) =3D=3D 0: + classPage.AddDescription('\copydoc %s

' % obj.GetHea= derFile()) + section =3D doxygen.Section('ref', 'Refer to Header File') + section.AddDescription('\link %s\n' % obj.GetHeaderFile()) + section.AddDescription(' \endlink

\n') + classPage.AddSection(section) + fullPath =3D os.path.join(pObj.GetFileObj().GetPackageRoot= Path(), obj.GetHeaderFile()) + + self.ProcessSourceFileForInclude(fullPath, pObj, configFil= e) + rootArray.append(pageRoot) + return rootArray + + def ProcessSourceFileForInclude(self, path, pObj, configFile, infObj= =3DNone): + """ + @param path the analysising file full path + @param pObj package object + @param configFile doxygen config file. + """ + + if gInGui: + wx.Yield() + if not os.path.exists(path): + ErrorMsg('Source file path %s does not exist!' % path) + return + + if configFile.FileExists(path): + return + + try: + f =3D open(path, 'r') + lines =3D f.readlines() + f.close() + except IOError: + ErrorMsg('Fail to open file %s' % path) + return + + configFile.AddFile(path) + return + no =3D 0 + for no in xrange(len(lines)): + if len(lines[no].strip()) =3D=3D 0: + continue + if lines[no].strip()[:2] in ['##', '//', '/*', '*/']: + continue + index =3D lines[no].lower().find('include') + #mo =3D IncludePattern.finditer(lines[no].lower()) + mo =3D re.match(r"^#\s*include\s+[<\"]([\\/\w.]+)[>\"]$", line= s[no].strip().lower()) + if not mo: + continue + mo =3D re.match(r"^[#\w\s]+[<\"]([\\/\w.]+)[>\"]$", lines[no].= strip()) + filePath =3D mo.groups()[0] + + if filePath =3D=3D None or len(filePath) =3D=3D 0: + continue + + # find header file in module's path firstly. + fullPath =3D None + + if os.path.exists(os.path.join(os.path.dirname(path), filePath= )): + # Find the file in current directory + fullPath =3D os.path.join(os.path.dirname(path), filePath)= .replace('\\', '/') + else: + # find in depedent package's include path + incObjs =3D pObj.GetFileObj().GetSectionObjectsByName('inc= ludes') + for incObj in incObjs: + incPath =3D os.path.join(pObj.GetFileObj().GetPackageR= ootPath(), incObj.GetPath()).strip() + incPath =3D os.path.realpath(os.path.join(incPath, fil= ePath)) + if os.path.exists(incPath): + fullPath =3D incPath + break + if infObj !=3D None: + pkgInfObjs =3D infObj.GetSectionObjectsByName('package= s') + for obj in pkgInfObjs: + decObj =3D dec.DECFile(os.path.join(pObj.GetWorksp= ace(), obj.GetPath())) + if not decObj: + ErrorMsg ('Fail to create pacakge object for %= s' % obj.GetPackageName()) + continue + if not decObj.Parse(): + ErrorMsg ('Fail to load package object for %s'= % obj.GetPackageName()) + continue + incObjs =3D decObj.GetSectionObjectsByName('includ= es') + for incObj in incObjs: + incPath =3D os.path.join(decObj.GetPackageRoot= Path(), incObj.GetPath()).replace('\\', '/') + if os.path.exists(os.path.join(incPath, filePa= th)): + fullPath =3D os.path.join(os.path.join(inc= Path, filePath)) + break + if fullPath !=3D None: + break + + if fullPath =3D=3D None and self.IsVerbose(): + self.Log('Can not resolve header file %s for file %s in pa= ckage %s\n' % (filePath, path, pObj.GetFileObj().GetFilename()), 'error') + return + else: + fullPath =3D fullPath.replace('\\', '/') + if self.IsVerbose(): + self.Log('Preprocessing: Add include file %s for file = %s\n' % (fullPath, path)) + #LogMsg ('Preprocessing: Add include file %s for file %s' = % (fullPath, path)) + self.ProcessSourceFileForInclude(fullPath, pObj, configFil= e, infObj) + + def AddAllIncludeFiles(self, pObj, configFile): + objs =3D pObj.GetFileObj().GetSectionObjectsByName('includes') + for obj in objs: + incPath =3D os.path.join(pObj.GetFileObj().GetPackageRootPath(= ), obj.GetPath()) + for root, dirs, files in os.walk(incPath): + for dir in dirs: + if dir.lower() in _ignore_dir: + dirs.remove(dir) + for file in files: + path =3D os.path.normpath(os.path.join(root, file)) + configFile.AddFile(path.replace('/', '\\')) + + def GeneratePcdSubPages(self, pObj, configFile): + """ + Generate sub pages for package's PCD definition. + @param pObj package object + @param configFile config file object + """ + rootArray =3D [] + objs =3D pObj.GetFileObj().GetSectionObjectsByName('pcd') + if len(objs) =3D=3D 0: + return [] + + pcdRootPage =3D doxygen.Page('PCD', 'pcd_root_page') + typeRootPageDict =3D {} + typeArchRootPageDict =3D {} + for obj in objs: + if obj.GetPcdType() not in typeRootPageDict.keys(): + typeRootPageDict[obj.GetPcdType()] =3D doxygen.Page(obj.Ge= tPcdType(), 'pcd_%s_root_page' % obj.GetPcdType()) + pcdRootPage.AddPage(typeRootPageDict[obj.GetPcdType()]) + typeRoot =3D typeRootPageDict[obj.GetPcdType()] + if self._arch !=3D None: + pcdPage =3D doxygen.Page('%s' % obj.GetPcdName(), + 'pcd_%s_%s_%s' % (obj.GetPcdType()= , obj.GetArch(), obj.GetPcdName().split('.')[1])) + pcdPage.AddDescription('
\n'.join(obj.GetComment()) + '=
\n') + section =3D doxygen.Section('PCDinformation', 'PCD Informa= tion') + desc =3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' % obj.GetPcdNam= e().split('.')[1] + desc +=3D '' % obj.GetPcdNam= e().split('.')[0] + desc +=3D '' % obj.GetPcdTok= en() + desc +=3D '' % obj.GetPcdDat= aType() + desc +=3D '' % obj.GetPcdVal= ue() + desc +=3D '' + desc +=3D '
Name
Token Space
Token number
Data Type
Default Value
%s
%s
%s
%s
%s
' + section.AddDescription(desc) + pcdPage.AddSection(section) + typeRoot.AddPage(pcdPage) + else: + keystr =3D obj.GetPcdType() + obj.GetArch() + if keystr not in typeArchRootPageDict.keys(): + typeArchRootPage =3D doxygen.Page(obj.GetArch(), 'pcd_= %s_%s_root_page' % (obj.GetPcdType(), obj.GetArch())) + typeArchRootPageDict[keystr] =3D typeArchRootPage + typeRoot.AddPage(typeArchRootPage) + typeArchRoot =3D typeArchRootPageDict[keystr] + pcdPage =3D doxygen.Page('%s' % obj.GetPcdName(), + 'pcd_%s_%s_%s' % (obj.GetPcdType()= , obj.GetArch(), obj.GetPcdName().split('.')[1])) + pcdPage.AddDescription('
\n'.join(obj.GetComment()) + '=
\n') + section =3D doxygen.Section('PCDinformation', 'PCD Informa= tion') + desc =3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' % obj.GetPcdNam= e().split('.')[1] + desc +=3D '' % obj.GetPcdNam= e().split('.')[0] + desc +=3D '' % obj.GetPcdTok= en() + desc +=3D '' % obj.GetPcdDat= aType() + desc +=3D '' % obj.GetPcdVal= ue() + desc +=3D '' + desc +=3D '
Name
Token Space
Token number
Data Type
Default Value
%s
%s
%s
%s
%s
' + section.AddDescription(desc) + pcdPage.AddSection(section) + typeArchRoot.AddPage(pcdPage) + return [pcdRootPage] + + def _GenerateGuidSubPage(self, pObj, obj, configFile): + guidPage =3D doxygen.Page('%s' % obj.GetName(), + 'guid_%s_%s' % (obj.GetArch(), obj.GetName= ())) + comments =3D obj.GetComment() + if len(comments) !=3D 0: + guidPage.AddDescription('
'.join(obj.GetComment()) + '
') + section =3D doxygen.Section('BasicGuidInfo', 'GUID Information') + desc =3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' % obj.GetName() + desc +=3D '' % obj.GetGuid() + desc +=3D '' + desc +=3D '
GUID\'s Guid Name
GUID\'s Guid
%s%s
' + section.AddDescription(desc) + guidPage.AddSection(section) + refFile =3D self.FindHeaderFileForGuid(pObj, obj.GetName(), config= File) + if refFile: + relPath =3D refFile[len(pObj.GetWorkspace()) + 1:] + if len(comments) =3D=3D 0: + guidPage.AddDescription(' \\copydoc %s
' % relPath) + + section =3D doxygen.Section('ref', 'Refer to Header File') + section.AddDescription('\link %s\n' % relPath) + section.AddDescription('\endlink\n') + self.ProcessSourceFileForInclude(refFile, pObj, configFile) + guidPage.AddSection(section) + return guidPage + + def GenerateGuidSubPages(self, pObj, configFile): + """ + Generate sub pages for package's GUID definition. + @param pObj package object + @param configFilf doxygen config file object + """ + pageRoot =3D doxygen.Page('GUID', 'guid_root_page') + objs =3D pObj.GetFileObj().GetSectionObjectsByName('guids', self._= arch) + if len(objs) =3D=3D 0: return [] + if self._arch !=3D None: + for obj in objs: + pageRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, conf= igFile)) + else: + guidArchRootPageDict =3D {} + for obj in objs: + if obj.GetArch() not in guidArchRootPageDict.keys(): + guidArchRoot =3D doxygen.Page(obj.GetArch(), 'guid_arc= h_root_%s' % obj.GetArch()) + pageRoot.AddPage(guidArchRoot) + guidArchRootPageDict[obj.GetArch()] =3D guidArchRoot + guidArchRoot =3D guidArchRootPageDict[obj.GetArch()] + guidArchRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, = configFile)) + return [pageRoot] + + def _GeneratePpiSubPage(self, pObj, obj, configFile): + guidPage =3D doxygen.Page(obj.GetName(), 'ppi_page_%s' % obj.GetNa= me()) + comments =3D obj.GetComment() + if len(comments) !=3D 0: + guidPage.AddDescription('
'.join(obj.GetComment()) + '
') + section =3D doxygen.Section('BasicPpiInfo', 'PPI Information') + desc =3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' % obj.GetName() + desc +=3D '' % obj.GetGuid() + desc +=3D '' + desc +=3D '
PPI\'s Guid Name
PPI\'s Guid
%s%s
' + section.AddDescription(desc) + guidPage.AddSection(section) + refFile =3D self.FindHeaderFileForGuid(pObj, obj.GetName(), config= File) + if refFile: + relPath =3D refFile[len(pObj.GetWorkspace()) + 1:] + if len(comments) =3D=3D 0: + guidPage.AddDescription(' \\copydoc %s
' % relPath) + section =3D doxygen.Section('ref', 'Refer to Header File') + section.AddDescription('\link %s\n' % relPath) + section.AddDescription('\endlink\n') + self.ProcessSourceFileForInclude(refFile, pObj, configFile) + guidPage.AddSection(section) + + return guidPage + + def GeneratePpiSubPages(self, pObj, configFile): + """ + Generate sub pages for package's GUID definition. + @param pObj package object + @param configFilf doxygen config file object + """ + pageRoot =3D doxygen.Page('PPI', 'ppi_root_page') + objs =3D pObj.GetFileObj().GetSectionObjectsByName('ppis', self._a= rch) + if len(objs) =3D=3D 0: return [] + if self._arch !=3D None: + for obj in objs: + pageRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, confi= gFile)) + else: + guidArchRootPageDict =3D {} + for obj in objs: + if obj.GetArch() not in guidArchRootPageDict.keys(): + guidArchRoot =3D doxygen.Page(obj.GetArch(), 'ppi_arch= _root_%s' % obj.GetArch()) + pageRoot.AddPage(guidArchRoot) + guidArchRootPageDict[obj.GetArch()] =3D guidArchRoot + guidArchRoot =3D guidArchRootPageDict[obj.GetArch()] + guidArchRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, c= onfigFile)) + return [pageRoot] + + def _GenerateProtocolSubPage(self, pObj, obj, configFile): + guidPage =3D doxygen.Page(obj.GetName(), 'protocol_page_%s' % obj.= GetName()) + comments =3D obj.GetComment() + if len(comments) !=3D 0: + guidPage.AddDescription('
'.join(obj.GetComment()) + '
') + section =3D doxygen.Section('BasicProtocolInfo', 'PROTOCOL Informa= tion') + desc =3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' + desc +=3D '' % obj.GetName() + desc +=3D '' % obj.GetGuid() + desc +=3D '' + desc +=3D '
PROTOCOL\'s Guid Name
PROTOCOL\'s Guid
%s%s
' + section.AddDescription(desc) + guidPage.AddSection(section) + + refFile =3D self.FindHeaderFileForGuid(pObj, obj.GetName(), config= File) + if refFile: + relPath =3D refFile[len(pObj.GetWorkspace()) + 1:] + if len(comments) =3D=3D 0: + guidPage.AddDescription(' \\copydoc %s
' % relPath) + section =3D doxygen.Section('ref', 'Refer to Header File') + section.AddDescription('\link %s\n' % relPath) + section.AddDescription('\endlink\n') + self.ProcessSourceFileForInclude(refFile, pObj, configFile) + guidPage.AddSection(section) + + return guidPage + + def GenerateProtocolSubPages(self, pObj, configFile): + """ + Generate sub pages for package's GUID definition. + @param pObj package object + @param configFilf doxygen config file object + """ + pageRoot =3D doxygen.Page('PROTOCOL', 'protocol_root_page') + objs =3D pObj.GetFileObj().GetSectionObjectsByName('protocols', se= lf._arch) + if len(objs) =3D=3D 0: return [] + if self._arch !=3D None: + for obj in objs: + pageRoot.AddPage(self._GenerateProtocolSubPage(pObj, obj, = configFile)) + else: + guidArchRootPageDict =3D {} + for obj in objs: + if obj.GetArch() not in guidArchRootPageDict.keys(): + guidArchRoot =3D doxygen.Page(obj.GetArch(), 'protocol= _arch_root_%s' % obj.GetArch()) + pageRoot.AddPage(guidArchRoot) + guidArchRootPageDict[obj.GetArch()] =3D guidArchRoot + guidArchRoot =3D guidArchRootPageDict[obj.GetArch()] + guidArchRoot.AddPage(self._GenerateProtocolSubPage(pObj, o= bj, configFile)) + return [pageRoot] + + def FindHeaderFileForGuid(self, pObj, name, configFile): + """ + For declaration header file for GUID/PPI/Protocol. + + @param pObj package object + @param name guid/ppi/protocol's name + @param configFile config file object + + @return full path of header file and None if not found. + """ + startPath =3D pObj.GetFileObj().GetPackageRootPath() + incPath =3D os.path.join(startPath, 'Include').replace('\\', '/= ') + # if /include exist, then search header under it. + if os.path.exists(incPath): + startPath =3D incPath + + for root, dirs, files in os.walk(startPath): + for dir in dirs: + if dir.lower() in _ignore_dir: + dirs.remove(dir) + for file in files: + fPath =3D os.path.join(root, file) + if not IsCHeaderFile(fPath): + continue + try: + f =3D open(fPath, 'r') + lines =3D f.readlines() + f.close() + except IOError: + self.Log('Fail to open file %s\n' % fPath) + continue + for line in lines: + if line.find(name) !=3D -1 and \ + line.find('extern') !=3D -1: + return fPath.replace('\\', '/') + return None + + def GetPackageModuleList(self, pObj): + """ + Get all module's INF path under package's root path + @param pObj package object + @return arrary of INF full path + """ + mArray =3D [] + packPath =3D pObj.GetFileObj().GetPackageRootPath() + if not os.path.exists: + return None + for root, dirs, files in os.walk(packPath): + for dir in dirs: + if dir.lower() in _ignore_dir: + dirs.remove(dir) + for file in files: + if CheckPathPostfix(file, 'inf'): + fPath =3D os.path.join(root, file).replace('\\', '/') + mArray.append(fPath) + return mArray + + def GenerateModulePages(self, pObj, configFile): + """ + Generate sub pages for package's module which is under the package + root directory. + + @param pObj package object + @param configFilf doxygen config file object + """ + infList =3D self.GetPackageModuleList(pObj) + rootPages =3D [] + libObjs =3D [] + modObjs =3D [] + for infpath in infList: + infObj =3D inf.INFFile(infpath) + #infObj =3D INFFileObject.INFFile (pObj.GetWorkspacePath(), + # inf) + if not infObj: + self.Log('Fail create INF object for %s' % inf) + continue + if not infObj.Parse(): + self.Log('Fail to load INF file %s' % inf) + continue + if infObj.GetProduceLibraryClass() !=3D None: + libObjs.append(infObj) + else: + modObjs.append(infObj) + + if len(libObjs) !=3D 0: + libRootPage =3D doxygen.Page('Libraries', 'lib_root_page') + rootPages.append(libRootPage) + for libInf in libObjs: + libRootPage.AddPage(self.GenerateModulePage(pObj, libInf, = configFile, True)) + + if len(modObjs) !=3D 0: + modRootPage =3D doxygen.Page('Modules', 'module_root_page') + rootPages.append(modRootPage) + for modInf in modObjs: + modRootPage.AddPage(self.GenerateModulePage(pObj, modInf, = configFile, False)) + + return rootPages + + def GenerateModulePage(self, pObj, infObj, configFile, isLib): + """ + Generate page for a module/library. + @param infObj INF file object for module/library + @param configFile doxygen config file object + @param isLib Whether this module is libary + + @param module doxygen page object + """ + workspace =3D pObj.GetWorkspace() + refDecObjs =3D [] + for obj in infObj.GetSectionObjectsByName('packages'): + decObj =3D dec.DECFile(os.path.join(workspace, obj.GetPath())) + if not decObj: + ErrorMsg ('Fail to create pacakge object for %s' % obj.Get= PackageName()) + continue + if not decObj.Parse(): + ErrorMsg ('Fail to load package object for %s' % obj.GetPa= ckageName()) + continue + refDecObjs.append(decObj) + + modPage =3D doxygen.Page('%s' % infObj.GetBaseName(), + 'module_%s' % infObj.GetBaseName()) + modPage.AddDescription(infObj.GetFileHeader()) + + basicInfSection =3D doxygen.Section('BasicModuleInformation', 'Bas= ic Module Information') + desc =3D "" + for obj in infObj.GetSectionObjectsByName('defines'): + key =3D obj.GetKey() + value =3D obj.GetValue() + if key not in _inf_key_description_mapping_table.keys(): conti= nue + if key =3D=3D 'LIBRARY_CLASS' and value.find('|') !=3D -1: + clsname, types =3D value.split('|') + desc +=3D '' + desc +=3D '' % _inf_key_description_mapp= ing_table[key] + desc +=3D '' % clsname + desc +=3D '' + + desc +=3D '' + desc +=3D '' + desc +=3D '' % types + desc +=3D '' + else: + desc +=3D '' + desc +=3D '' % _inf_key_description_mapp= ing_table[key] + if key =3D=3D 'EFI_SPECIFICATION_VERSION' and value =3D=3D= '0x00020000': + value =3D '2.0' + desc +=3D '' % value + desc +=3D '' + desc +=3D '
%s%s
Supported Module Types%s
%s%s
' + basicInfSection.AddDescription(desc) + modPage.AddSection(basicInfSection) + + # Add protocol section + data =3D [] + for obj in infObj.GetSectionObjectsByName('pcd', self._arch): + data.append(obj.GetPcdName().strip()) + if len(data) !=3D 0: + s =3D doxygen.Section('Pcds', 'Pcds') + desc =3D "" + desc +=3D '' + for item in data: + desc +=3D '' + desc +=3D '' % item.split('.')[1] + desc +=3D '' % item.split('.')[0] + pkgbasename =3D self.SearchPcdPackage(item, workspace, ref= DecObjs) + desc +=3D '' % pkgbasename + desc +=3D '' + desc +=3D "
PCD NameTokenSpacePackage
%s%s%s
" + s.AddDescription(desc) + modPage.AddSection(s) + + # Add protocol section + #sects =3D infObj.GetSectionByString('protocol') + data =3D [] + #for sect in sects: + for obj in infObj.GetSectionObjectsByName('protocol', self._arch): + data.append(obj.GetName().strip()) + if len(data) !=3D 0: + s =3D doxygen.Section('Protocols', 'Protocols') + desc =3D "" + desc +=3D '' + for item in data: + desc +=3D '' + desc +=3D '' % item + pkgbasename =3D self.SearchProtocolPackage(item, workspace= , refDecObjs) + desc +=3D '' % pkgbasename + desc +=3D '' + desc +=3D "
NamePackage
%s%s
" + s.AddDescription(desc) + modPage.AddSection(s) + + # Add ppi section + #sects =3D infObj.GetSectionByString('ppi') + data =3D [] + #for sect in sects: + for obj in infObj.GetSectionObjectsByName('ppi', self._arch): + data.append(obj.GetName().strip()) + if len(data) !=3D 0: + s =3D doxygen.Section('Ppis', 'Ppis') + desc =3D "" + desc +=3D '' + for item in data: + desc +=3D '' + desc +=3D '' % item + pkgbasename =3D self.SearchPpiPackage(item, workspace, ref= DecObjs) + desc +=3D '' % pkgbasename + desc +=3D '' + desc +=3D "
NamePackage
%s%s
" + s.AddDescription(desc) + modPage.AddSection(s) + + # Add guid section + #sects =3D infObj.GetSectionByString('guid') + data =3D [] + #for sect in sects: + for obj in infObj.GetSectionObjectsByName('guid', self._arch): + data.append(obj.GetName().strip()) + if len(data) !=3D 0: + s =3D doxygen.Section('Guids', 'Guids') + desc =3D "" + desc +=3D '' + for item in data: + desc +=3D '' + desc +=3D '' % item + pkgbasename =3D self.SearchGuidPackage(item, workspace, re= fDecObjs) + desc +=3D '' % pkgbasename + desc +=3D '' + desc +=3D "
NamePackage
%s%s
" + s.AddDescription(desc) + modPage.AddSection(s) + + section =3D doxygen.Section('LibraryClasses', 'Library Classes') + desc =3D "" + desc +=3D '' + if isLib: + desc +=3D '' + desc +=3D '' % infObj.GetProduceLibraryClass() + desc +=3D '' + try: + pkgname, hPath =3D self.SearchLibraryClassHeaderFile(infOb= j.GetProduceLibraryClass(), + workspace, + refDecObjs) + except: + self.Log ('fail to get package header file for lib class %= s' % infObj.GetProduceLibraryClass()) + pkgname =3D 'NULL' + hPath =3D 'NULL' + desc +=3D '' % pkgname + if hPath !=3D "NULL": + #desc +=3D '' % hPath + desc +=3D '' % hPath + else: + desc +=3D '' % hPath + desc +=3D '' + for lcObj in infObj.GetSectionObjectsByName('libraryclasses', self= ._arch): + desc +=3D '' + desc +=3D '' % lcObj.GetClass() + retarr =3D self.SearchLibraryClassHeaderFile(lcObj.GetClass(), + workspace, + refDecObjs) + if retarr !=3D None: + pkgname, hPath =3D retarr + else: + self.Log('Fail find the library class %s definition from m= odule %s dependent package!' % (lcObj.GetClass(), infObj.GetFilename()), 'e= rror') + pkgname =3D 'NULL' + hPath =3D 'NULL' + desc +=3D '' + desc +=3D '' % pkgname + desc +=3D '' % hPath + desc +=3D '' + desc +=3D "
NameTypePack= ageHeader File
%sProduce%s\link %s \endlink%s%s
%sConsume%s%s
" + section.AddDescription(desc) + modPage.AddSection(section) + + section =3D doxygen.Section('SourceFiles', 'Source Files') + section.AddDescription('

    \n') + for obj in infObj.GetSourceObjects(self._arch, self._tooltag): + sPath =3D infObj.GetModuleRootPath() + sPath =3D os.path.join(sPath, obj.GetSourcePath()).replace('\\= ', '/').strip() + if sPath.lower().endswith('.uni') or sPath.lower().endswith('.= s') or sPath.lower().endswith('.asm') or sPath.lower().endswith('.nasm'): + newPath =3D self.TranslateUniFile(sPath) + configFile.AddFile(newPath) + newPath =3D newPath[len(pObj.GetWorkspace()) + 1:] + section.AddDescription('
  • \link %s \endlink
  • ' % n= ewPath) + else: + self.ProcessSourceFileForInclude(sPath, pObj, configFile, = infObj) + sPath =3D sPath[len(pObj.GetWorkspace()) + 1:] + section.AddDescription('
  • \link %s \endlink
  • ' % sPa= th) + section.AddDescription('
\n') + modPage.AddSection(section) + + #sects =3D infObj.GetSectionByString('depex') + data =3D [] + #for sect in sects: + for obj in infObj.GetSectionObjectsByName('depex'): + data.append(str(obj)) + if len(data) !=3D 0: + s =3D doxygen.Section('DependentSection', 'Module Dependencies= ') + s.AddDescription('
'.join(data)) + modPage.AddSection(s) + + return modPage + + def TranslateUniFile(self, path): + newpath =3D path + '.dox' + #import core.textfile as textfile + #file =3D textfile.TextFile(path) + + try: + file =3D open(path, 'rb') + except (IOError, OSError), msg: + return None + + t =3D file.read() + file.close() + + output =3D '/** @file \n' + #output =3D '' + arr =3D t.split('\r\n') + for line in arr: + if line.find('@file') !=3D -1: + continue + if line.find('*/') !=3D -1: + continue + line =3D line.strip() + if line.strip().startswith('/'): + arr =3D line.split(' ') + if len(arr) > 1: + line =3D ' '.join(arr[1:]) + else: + continue + output +=3D '%s
\n' % line + output +=3D '**/' + + if os.path.exists(newpath): + os.remove(newpath) + + file =3D open(newpath, "w") + file.write(output) + file.close() + return newpath + + def SearchPcdPackage(self, pcdname, workspace, decObjs): + for decObj in decObjs: + for pcd in decObj.GetSectionObjectsByName('pcd'): + if pcdname =3D=3D pcd.GetPcdName(): + return decObj.GetBaseName() + return None + + def SearchProtocolPackage(self, protname, workspace, decObjs): + for decObj in decObjs: + for proto in decObj.GetSectionObjectsByName('protocol'): + if protname =3D=3D proto.GetName(): + return decObj.GetBaseName() + return None + + def SearchPpiPackage(self, ppiname, workspace, decObjs): + for decObj in decObjs: + for ppi in decObj.GetSectionObjectsByName('ppi'): + if ppiname =3D=3D ppi.GetName(): + return decObj.GetBaseName() + return None + + def SearchGuidPackage(self, guidname, workspace, decObjs): + for decObj in decObjs: + for guid in decObj.GetSectionObjectsByName('guid'): + if guidname =3D=3D guid.GetName(): + return decObj.GetBaseName() + return None + + def SearchLibraryClassHeaderFile(self, className, workspace, decObjs): + for decObj in decObjs: + for cls in decObj.GetSectionObjectsByName('libraryclasses'): + if cls.GetClassName().strip() =3D=3D className: + path =3D cls.GetHeaderFile().strip() + path =3D os.path.join(decObj.GetPackageRootPath(), pat= h) + path =3D path[len(workspace) + 1:] + return decObj.GetBaseName(), path.replace('\\', '/') + + return None + + def _ConvertPathToDoxygen(self, path, pObj): + pRootPath =3D pObj.GetWorkspace() + path =3D path[len(pRootPath) + 1:] + return path.replace('\\', '/') + +def IsCHeaderFile(path): + return CheckPathPostfix(path, 'h') + +def CheckPathPostfix(path, str): + index =3D path.rfind('.') + if index =3D=3D -1: + return False + if path[index + 1:].lower() =3D=3D str.lower(): + return True + return False diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2= /model/dsc.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/e= dk2/model/dsc.py new file mode 100644 index 0000000..f8ed531 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2/model/= dsc.py @@ -0,0 +1,201 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# + +import plugins.EdkPlugins.basemodel.ini as ini +import re, os +from plugins.EdkPlugins.basemodel.message import * + +class DSCFile(ini.BaseINIFile): + def GetSectionInstance(self, parent, name, isCombined=3DFalse): + return DSCSection(parent, name, isCombined) + + def GetComponents(self): + return self.GetSectionObjectsByName('Components') + +class DSCSection(ini.BaseINISection): + def GetSectionINIObject(self, parent): + type =3D self.GetType() + + if type.lower() =3D=3D 'components': + return DSCComponentObject(self) + if type.lower() =3D=3D 'libraryclasses': + return DSCLibraryClassObject(self) + if type.lower() =3D=3D 'defines': + return ini.BaseINISectionObject(self) + if type.lower() =3D=3D 'pcdsfeatureflag' or \ + type.lower() =3D=3D 'pcdsfixedatbuild' or \ + type.lower() =3D=3D 'pcdspatchableinmodule' or\ + type.lower() =3D=3D 'pcdsdynamicdefault' or \ + type.lower() =3D=3D 'pcdsdynamicex' or \ + type.lower() =3D=3D 'pcdsdynamichii' or \ + type.lower() =3D=3D 'pcdsdynamicvpd': + return DSCPcdObject(self) + + return DSCSectionObject(self) + + def GetType(self): + arr =3D self._name.split('.') + return arr[0].strip() + + def GetArch(self): + arr =3D self._name.split('.') + if len(arr) =3D=3D 1: + return 'common' + return arr[1] + + def GetModuleType(self): + arr =3D self._name.split('.') + if len(arr) < 3: + return 'common' + return arr[2] + +class DSCSectionObject(ini.BaseINISectionObject): + def GetArch(self): + return self.GetParent().GetArch() + +class DSCPcdObject(DSCSectionObject): + + def __init__(self, parent): + ini.BaseINISectionObject.__init__(self, parent) + self._name =3D None + + def Parse(self): + line =3D self.GetLineByOffset(self._start).strip().split('#')[0] + self._name =3D line.split('|')[0] + self._value =3D line.split('|')[1] + return True + + def GetPcdName(self): + return self._name + + def GetPcdType(self): + return self.GetParent().GetType() + + def GetPcdValue(self): + return self._value + +class DSCLibraryClassObject(DSCSectionObject): + def __init__(self, parent): + ini.BaseINISectionObject.__init__(self, parent) + + def GetClass(self): + line =3D self.GetLineByOffset(self._start) + return line.split('#')[0].split('|')[0].strip() + + def GetInstance(self): + line =3D self.GetLineByOffset(self._start) + return line.split('#')[0].split('|')[1].strip() + + def GetArch(self): + return self.GetParent().GetArch() + + def GetModuleType(self): + return self.GetParent().GetModuleType() + +class DSCComponentObject(DSCSectionObject): + + def __init__(self, parent): + ini.BaseINISectionObject.__init__(self, parent) + self._OveridePcds =3D {} + self._OverideLibraries =3D {} + self._Filename =3D '' + + def __del__(self): + self._OverideLibraries.clear() + self._OverideLibraries.clear() + ini.BaseINISectionObject.__del__(self) + + def AddOverideLib(self, libclass, libinstPath): + if libclass not in self._OverideLibraries.keys(): + self._OverideLibraries[libclass] =3D libinstPath + + def AddOveridePcd(self, name, type, value=3DNone): + if type not in self._OveridePcds.keys(): + self._OveridePcds[type] =3D [] + self._OveridePcds[type].append((name, value)) + + def GetOverideLibs(self): + return self._OverideLibraries + + def GetArch(self): + return self.GetParent().GetArch() + + def GetOveridePcds(self): + return self._OveridePcds + + def GetFilename(self): + return self.GetLineByOffset(self._start).split('#')[0].split('{')[= 0].strip() + + def SetFilename(self, fName): + self._Filename =3D fName + + def Parse(self): + if (self._start < self._end): + # + # The first line is inf path and could be ignored + # The end line is '}' and could be ignored + # + curr =3D self._start + 1 + end =3D self._end - 1 + OverideName =3D '' + while (curr <=3D end): + line =3D self.GetLineByOffset(curr).strip() + if len(line) > 0 and line[0] !=3D '#': + line =3D line.split('#')[0].strip() + if line[0] =3D=3D '<': + OverideName =3D line[1:len(line)-1] + elif OverideName.lower() =3D=3D 'libraryclasses': + arr =3D line.split('|') + self._OverideLibraries[arr[0].strip()] =3D arr[1].= strip() + elif OverideName.lower() =3D=3D 'pcds': + ErrorMsg('EDES does not support PCD overide', + self.GetFileName(), + self.GetParent().GetLinenumberByOffset(cu= rr)) + curr =3D curr + 1 + return True + + def GenerateLines(self): + lines =3D [] + hasLib =3D False + hasPcd =3D False + if len(self._OverideLibraries) !=3D 0: + hasLib =3D True + if len(self._OveridePcds) !=3D 0: + hasPcd =3D True + + if hasLib or hasPcd: + lines.append((' %s {\n' % self._Filename)) + else: + lines.append((' %s \n' % self._Filename)) + return lines + + if hasLib: + lines.append(' \n') + for libKey in self._OverideLibraries.keys(): + lines.append(' %s|%s\n' % (libKey, self._OverideLibra= ries[libKey])) + + if hasPcd: + for key in self._OveridePcds.keys(): + lines.append(' <%s>\n' % key) + + for name, value in self._OveridePcds[key]: + if value !=3D None: + lines.append(' %s|%s\n' % (name, value)) + else: + lines.append(' %s\n' % name) + + if hasLib or hasPcd: + lines.append(' }\n') + + return lines + diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2= /model/inf.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/e= dk2/model/inf.py new file mode 100644 index 0000000..9d70fbc --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2/model/= inf.py @@ -0,0 +1,341 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# + +import plugins.EdkPlugins.basemodel.ini as ini +import re, os +from plugins.EdkPlugins.basemodel.message import * + +class INFFile(ini.BaseINIFile): + _libobjs =3D {} + + def GetSectionInstance(self, parent, name, isCombined=3DFalse): + return INFSection(parent, name, isCombined) + + def GetProduceLibraryClass(self): + obj =3D self.GetDefine("LIBRARY_CLASS") + if obj =3D=3D None: return None + + return obj.split('|')[0].strip() + + def GetSectionObjectsByName(self, name, arch=3DNone): + arr =3D [] + sects =3D self.GetSectionByName(name) + for sect in sects: + # skip unmatched archtecture content + if not sect.IsArchMatch(arch): + continue + + for obj in sect.GetObjects(): + arr.append(obj) + + return arr + + def GetSourceObjects(self, arch=3DNone, tool=3DNone): + arr =3D [] + sects =3D self.GetSectionByName('sources') + for sect in sects: + # skip unmatched archtecture content + if not sect.IsArchMatch(arch): + continue + + for obj in sect.GetObjects(): + if not obj.IsMatchFamily(tool): + continue + arr.append(obj) + + return arr + + def Parse(self): + if not ini.BaseINIFile.Parse(self): + return False + classname =3D self.GetProduceLibraryClass() + if classname !=3D None: + libobjdict =3D INFFile._libobjs + if libobjdict.has_key(classname): + if self not in libobjdict[classname]: + libobjdict[classname].append(self) + else: + libobjdict[classname] =3D [self] + + return True + + def GetBaseName(self): + return self.GetDefine("BASE_NAME").strip() + + def GetModuleRootPath(self): + return os.path.dirname(self.GetFilename()) + + def Clear(self): + classname =3D self.GetProduceLibraryClass() + if classname !=3D None: + libobjdict =3D INFFile._libobjs + libobjdict[classname].remove(self) + if len(libobjdict[classname]) =3D=3D 0: + del libobjdict[classname] + ini.BaseINIFile.Clear(self) + + +class INFSection(ini.BaseINISection): + def GetSectionINIObject(self, parent): + type =3D self.GetType() + + if type.lower() =3D=3D 'libraryclasses': + return INFLibraryClassObject(self) + if type.lower() =3D=3D 'sources': + return INFSourceObject(self) + if type.lower().find('pcd') !=3D -1: + return INFPcdObject(self) + if type.lower() =3D=3D 'packages': + return INFDependentPackageObject(self) + if type.lower() in ['guids', 'protocols', 'ppis']: + return INFGuidObject(self) + if type.lower() =3D=3D 'defines': + return INFDefineSectionObject(self) + return INFSectionObject(self) + + def GetType(self): + arr =3D self._name.split('.') + return arr[0].strip() + + def GetArch(self): + arr =3D self._name.split('.') + if len(arr) =3D=3D 1: + return 'common' + return arr[1] + + def IsArchMatch(self, arch): + if arch =3D=3D None or self.GetArch() =3D=3D 'common': + return True + + if self.GetArch().lower() !=3D arch.lower(): + return False + + return True + +class INFSectionObject(ini.BaseINISectionObject): + def GetArch(self): + return self.GetParent().GetArch() + +class INFDefineSectionObject(INFSectionObject): + def __init__(self, parent): + INFSectionObject.__init__(self, parent) + self._key =3D None + self._value =3D None + + def Parse(self): + assert (self._start =3D=3D self._end), 'The object in define secti= on must be in single line' + + line =3D self.GetLineByOffset(self._start).strip() + + line =3D line.split('#')[0] + arr =3D line.split('=3D') + if len(arr) !=3D 2: + ErrorMsg('Invalid define section object', + self.GetFilename(), + self._start + ) + return False + + self._key =3D arr[0].strip() + self._value =3D arr[1].strip() + + return True + + def GetKey(self): + return self._key + + def GetValue(self): + return self._value + +class INFLibraryClassObject(INFSectionObject): + _objs =3D {} + def __init__(self, parent): + INFSectionObject.__init__(self, parent) + self._classname =3D None + + def GetClass(self): + return self._classname + + def Parse(self): + self._classname =3D self.GetLineByOffset(self._start).split('#')[0= ].strip() + objdict =3D INFLibraryClassObject._objs + if objdict.has_key(self._classname): + objdict[self._classname].append(self) + else: + objdict[self._classname] =3D [self] + return True + + def Destroy(self): + objdict =3D INFLibraryClassObject._objs + objdict[self._classname].remove(self) + if len(objdict[self._classname]) =3D=3D 0: + del objdict[self._classname] + + def GetName(self): + return self._classname + + @staticmethod + def GetObjectDict(): + return INFLibraryClassObject._objs + +class INFDependentPackageObject(INFSectionObject): + def GetPath(self): + return self.GetLineByOffset(self._start).split('#')[0].strip() + +class INFSourceObject(INFSectionObject): + _objs =3D {} + def __init__(self, parent): + INFSectionObject.__init__(self, parent) + + self.mSourcename =3D None + self.mToolCode =3D None + self.mFamily =3D None + self.mTagName =3D None + self.mFeaturePcd =3D None + self.mFilename =3D None + + def GetSourcePath(self): + return self.mSourcename + + def GetSourceFullPath(self): + path =3D os.path.dirname(self.GetFilename()) + path =3D os.path.join(path, self.GetSourcePath()) + return os.path.normpath(path) + + def GetToolCode(self): + return self.mToolCode + + def GetFamily(self): + return self.mFamily + + def GetTagName(self): + return self.mTagName + + def GetFeaturePcd(self): + return self.mFeaturePcd + + def Parse(self): + line =3D self.GetLineByOffset(self._start).strip().split('#')[0] + + arr =3D line.split('|') + + self.mSourcename =3D arr[0].strip() + if len(arr) >=3D 2: + self.mFamily =3D arr[1].strip() + if len(arr) >=3D 3: + self.mTagName =3D arr[2].strip() + if len(arr) >=3D 4: + self.mToolCode =3D arr[3].strip() + if len(arr) >=3D 5: + self.mFeaturePcd =3D arr[4].strip() + + self.mFilename =3D os.path.basename(self.GetSourceFullPath()) + objdict =3D INFSourceObject._objs + if not objdict.has_key(self.mFilename): + objdict[self.mFilename] =3D [self] + else: + objdict[self.mFilename].append(self) + + return True + + def GetName(self): + return self.mFilename + + def Destroy(self): + objdict =3D INFSourceObject._objs + objdict[self.mFilename].remove(self) + if len(objdict[self.mFilename]) =3D=3D 0: + del objdict[self.mFilename] + + def IsMatchFamily(self, family): + if family =3D=3D None: + return True + if self.mFamily !=3D None: + if family.strip().lower() =3D=3D self.mFamily.lower(): + return True + else: + return False + else: + fname =3D self.GetSourcePath() + if fname.endswith('.S') and family.lower() !=3D 'gcc': + return False + if fname.endswith('.s') and (self.GetArch().lower() !=3D 'ipf'= and self.GetArch().lower() !=3D 'common'): + return False + if fname.lower().endswith('.asm') and (family.lower() !=3D 'ms= ft' and family.lower() !=3D 'intel'): + return False + return True + + @staticmethod + def GetObjectDict(): + return INFSourceObject._objs + +class INFPcdObject(INFSectionObject): + _objs =3D {} + + def __init__(self, parent): + INFSectionObject.__init__(self, parent) + + self.mPcdType =3D None + self.mDefaultValue =3D None + self.mPcdName =3D None + + @staticmethod + def GetObjectDict(): + return INFPcdObject._objs + + def Parse(self): + line =3D self.GetLineByOffset(self._start).strip().split('#')[0] + + arr =3D line.split('|') + self.mPcdName =3D arr[0].strip() + + if len(arr) >=3D 2: + self.mDefaultValue =3D arr[1].strip() + + objdict =3D INFPcdObject._objs + if objdict.has_key(self.GetName()): + if self not in objdict[self.GetName()]: + objdict[self.GetName()].append(self) + else: + objdict[self.GetName()] =3D [self] + return True + + def GetPcdName(self): + return self.mPcdName + + def GetPcdType(self): + return self.GetParent().GetType() + + def GetName(self): + return self.mPcdName.split('.')[1] + + def Destroy(self): + objdict =3D INFPcdObject._objs + objdict[self.GetName()].remove(self) + if len(objdict[self.GetName()]) =3D=3D 0: + del objdict[self.GetName()] + +class INFGuidObject(INFSectionObject): + def __init__(self, parent): + INFSectionObject.__init__(self, parent) + self._name =3D None + + def Parse(self): + line =3D self.GetLineByOffset(self._start).strip().split('#')[0].s= plit("|")[0] + self._name =3D line.strip() + return True + + def GetName(self): + return self._name + + diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/__init__.py b/B= aseTools/Scripts/PackageDocumentTools/plugins/__init__.py new file mode 100644 index 0000000..3e4ee53 --- /dev/null +++ b/BaseTools/Scripts/PackageDocumentTools/plugins/__init__.py @@ -0,0 +1,12 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made availa= ble +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# --=20 2.6.1.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel