--- /dev/null
+Prerequisite Tools:\r
+1. Install Python 2.7.3 from https://www.python.org/download/releases/2.7.3/\r
+2. Install wxPython 2.8.12.1 from https://sourceforge.net/projects/wxpython/files/wxPython/2.8.12.1/\r
+ generally the libraries will be installed at python's subfolder, for example in windows: c:\python27\Lib\site-packages\\r
+3. Install DoxyGen 1.8.6 from https://sourceforge.net/projects/doxygen/files/rel-1.8.6/\r
+4. (Windows only) Install Htmlhelp tool from https://msdn.microsoft.com/en-us/library/windows/desktop/ms669985(v=vs.85).aspx\r
+\r
+Limitation:\r
+1. Current tool doesn't work on latest wxPython and DoxyGen tool. Please use the sepecific version in above.\r
+\r
+Run the Tool:\r
+a) Run with GUI:\r
+ 1. Enter src folder, double click "packagedocapp.pyw" or run command "python packagedocapp.pyw" to open the GUI.\r
+ 2. Make sure all the information in blank are correct.\r
+ 3. Click "Generate Package Document!"\r
+b) Run with command line:\r
+ 1. Open command line window\r
+ 2. Enter src folder, for example: "cd C:\PackageDocumentTools\src"\r
+ 3. Run "python packagedoc_cli.py --help" for detail command.\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
--- /dev/null
+## @file\r
+# This module provide command line entry for generating package document!\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+import os, sys, logging, traceback, subprocess\r
+from optparse import OptionParser\r
+\r
+import plugins.EdkPlugins.edk2.model.baseobject as baseobject\r
+import plugins.EdkPlugins.edk2.model.doxygengen as doxygengen\r
+\r
+gArchMarcoDict = {'ALL' : 'MDE_CPU_IA32 MDE_CPU_X64 MDE_CPU_EBC MDE_CPU_IPF _MSC_EXTENSIONS __GNUC__ __INTEL_COMPILER',\r
+ 'IA32_MSFT': 'MDE_CPU_IA32 _MSC_EXTENSIONS',\r
+ 'IA32_GNU' : 'MDE_CPU_IA32 __GNUC__',\r
+ 'X64_MSFT' : 'MDE_CPU_X64 _MSC_EXTENSIONS ASM_PFX= OPTIONAL= ',\r
+ 'X64_GNU' : 'MDE_CPU_X64 __GNUC__ ASM_PFX= OPTIONAL= ',\r
+ 'IPF_MSFT' : 'MDE_CPU_IPF _MSC_EXTENSIONS ASM_PFX= OPTIONAL= ',\r
+ 'IPF_GNU' : 'MDE_CPU_IPF __GNUC__ ASM_PFX= OPTIONAL= ',\r
+ 'EBC_INTEL': 'MDE_CPU_EBC __INTEL_COMPILER ASM_PFX= OPTIONAL= '}\r
+\r
+def parseCmdArgs():\r
+ parser = OptionParser(version="Package Document Generation Tools - Version 0.1")\r
+ parser.add_option('-w', '--workspace', action='store', type='string', dest='WorkspacePath',\r
+ help='Specify workspace absolute path. For example: c:\\tianocore')\r
+ parser.add_option('-p', '--decfile', action='store', dest='PackagePath',\r
+ help='Specify the absolute path for package DEC file. For example: c:\\tianocore\\MdePkg\\MdePkg.dec')\r
+ parser.add_option('-x', '--doxygen', action='store', dest='DoxygenPath',\r
+ help='Specify the absolute path of doxygen tools installation. For example: C:\\Program Files\\doxygen\bin\doxygen.exe')\r
+ parser.add_option('-o', '--output', action='store', dest='OutputPath',\r
+ help='Specify the document output path. For example: c:\\docoutput')\r
+ parser.add_option('-a', '--arch', action='store', dest='Arch', choices=gArchMarcoDict.keys(),\r
+ help='Specify the architecture used in preprocess package\'s source. For example: -a IA32_MSFT')\r
+ parser.add_option('-m', '--mode', action='store', dest='DocumentMode', choices=['CHM', 'HTML'],\r
+ help='Specify the document mode from : CHM or HTML')\r
+ parser.add_option('-i', '--includeonly', action='store_true', dest='IncludeOnly',\r
+ help='Only generate document for package\'s public interfaces produced by include folder. ')\r
+ parser.add_option('-c', '--htmlworkshop', dest='HtmlWorkshopPath',\r
+ help='Specify the absolute path for Microsoft HTML Workshop\'s hhc.exe file. For example: C:\\Program Files\\HTML Help Workshop\\hhc.exe')\r
+ (options, args) = parser.parse_args()\r
+\r
+ # validate the options\r
+ errors = []\r
+ if options.WorkspacePath == None:\r
+ errors.append('- Please specify workspace path via option -w!')\r
+ elif not os.path.exists(options.WorkspacePath):\r
+ errors.append("- Invalid workspace path %s! The workspace path should be exist in absolute path!" % options.WorkspacePath)\r
+\r
+ if options.PackagePath == None:\r
+ errors.append('- Please specify package DEC file path via option -p!')\r
+ elif not os.path.exists(options.PackagePath):\r
+ errors.append("- Invalid package's DEC file path %s! The DEC path should be exist in absolute path!" % options.PackagePath)\r
+\r
+ default = "C:\\Program Files\\doxygen\\bin\\doxygen.exe"\r
+ if options.DoxygenPath == None:\r
+ if os.path.exists(default):\r
+ print "Warning: Assume doxygen tool is installed at %s. If not, please specify via -x" % default\r
+ options.DoxygenPath = default\r
+ else:\r
+ errors.append('- Please specify the path of doxygen tool installation via option -x! or install it in default path %s' % default)\r
+ elif not os.path.exists(options.DoxygenPath):\r
+ errors.append("- Invalid doxygen tool path %s! The doxygen tool path should be exist in absolute path!" % options.DoxygenPath)\r
+\r
+ if options.OutputPath != None:\r
+ if not os.path.exists(options.OutputPath):\r
+ # create output\r
+ try:\r
+ os.makedirs(options.OutputPath)\r
+ except:\r
+ errors.append('- Fail to create the output directory %s' % options.OutputPath)\r
+ else:\r
+ if options.PackagePath != None and os.path.exists(options.PackagePath):\r
+ dirpath = os.path.dirname(options.PackagePath)\r
+ default = os.path.join (dirpath, "Document")\r
+ print 'Warning: Assume document output at %s. If not, please specify via option -o' % default\r
+ options.OutputPath = default\r
+ if not os.path.exists(default):\r
+ try:\r
+ os.makedirs(default)\r
+ except:\r
+ errors.append('- Fail to create default output directory %s! Please specify document output diretory via option -o' % default)\r
+ else:\r
+ errors.append('- Please specify document output path via option -o!')\r
+\r
+ if options.Arch == None:\r
+ options.Arch = 'ALL'\r
+ print "Warning: Assume arch is \"ALL\". If not, specify via -a"\r
+\r
+ if options.DocumentMode == None:\r
+ options.DocumentMode = "HTML"\r
+ print "Warning: Assume document mode is \"HTML\". If not, specify via -m"\r
+\r
+ if options.IncludeOnly == None:\r
+ options.IncludeOnly = False\r
+ print "Warning: Assume generate package document for all package\'s source including publich interfaces and implementation libraries and modules."\r
+\r
+ if options.DocumentMode.lower() == 'chm':\r
+ default = "C:\\Program Files\\HTML Help Workshop\\hhc.exe"\r
+ if options.HtmlWorkshopPath == None:\r
+ if os.path.exists(default):\r
+ print 'Warning: Assume the installation path of Microsoft HTML Workshop is %s. If not, specify via option -c.' % default\r
+ options.HtmlWorkshopPath = default\r
+ else:\r
+ errors.append('- Please specify the installation path of Microsoft HTML Workshop via option -c!')\r
+ elif not os.path.exists(options.HtmlWorkshopPath):\r
+ errors.append('- The installation path of Microsoft HTML Workshop %s does not exists. ' % options.HtmlWorkshopPath)\r
+\r
+ if len(errors) != 0:\r
+ print '\n'\r
+ parser.error('Fail to start due to following reasons: \n%s' %'\n'.join(errors))\r
+ return (options.WorkspacePath, options.PackagePath, options.DoxygenPath, options.OutputPath,\r
+ options.Arch, options.DocumentMode, options.IncludeOnly, options.HtmlWorkshopPath)\r
+\r
+def createPackageObject(wsPath, pkgPath):\r
+ try:\r
+ pkgObj = baseobject.Package(None, wsPath)\r
+ pkgObj.Load(pkgPath)\r
+ except:\r
+ logging.getLogger().error ('Fail to create package object!')\r
+ return None\r
+\r
+ return pkgObj\r
+\r
+def callbackLogMessage(msg, level):\r
+ print msg.strip()\r
+\r
+def callbackCreateDoxygenProcess(doxPath, configPath):\r
+ if sys.platform == 'win32':\r
+ cmd = '"%s" %s' % (doxPath, configPath)\r
+ else:\r
+ cmd = '%s %s' % (doxPath, configPath)\r
+ print cmd\r
+ subprocess.call(cmd, shell=True)\r
+\r
+\r
+def DocumentFixup(outPath, arch):\r
+ # find BASE_LIBRARY_JUMP_BUFFER structure reference page\r
+\r
+ print '\n >>> Start fixup document \n'\r
+\r
+ for root, dirs, files in os.walk(outPath):\r
+ for dir in dirs:\r
+ if dir.lower() in ['.svn', '_svn', 'cvs']:\r
+ dirs.remove(dir)\r
+ for file in files:\r
+ if not file.lower().endswith('.html'): continue\r
+ fullpath = os.path.join(outPath, root, file)\r
+ try:\r
+ f = open(fullpath, 'r')\r
+ text = f.read()\r
+ f.close()\r
+ except:\r
+ logging.getLogger().error('\nFail to open file %s\n' % fullpath)\r
+ continue\r
+ if arch.lower() == 'all':\r
+ if text.find('BASE_LIBRARY_JUMP_BUFFER Struct Reference') != -1:\r
+ FixPageBASE_LIBRARY_JUMP_BUFFER(fullpath, text)\r
+ if text.find('MdePkg/Include/Library/BaseLib.h File Reference') != -1:\r
+ FixPageBaseLib(fullpath, text)\r
+ if text.find('IA32_IDT_GATE_DESCRIPTOR Union Reference') != -1:\r
+ FixPageIA32_IDT_GATE_DESCRIPTOR(fullpath, text)\r
+ if text.find('MdePkg/Include/Library/UefiDriverEntryPoint.h File Reference') != -1:\r
+ FixPageUefiDriverEntryPoint(fullpath, text)\r
+ if text.find('MdePkg/Include/Library/UefiApplicationEntryPoint.h File Reference') != -1:\r
+ FixPageUefiApplicationEntryPoint(fullpath, text)\r
+\r
+ print ' >>> Finish all document fixing up! \n'\r
+\r
+def FixPageBaseLib(path, text):\r
+ print ' >>> Fixup BaseLib file page at file %s \n' % path\r
+ lines = text.split('\n')\r
+ lastBaseJumpIndex = -1\r
+ lastIdtGateDescriptor = -1\r
+ for index in range(len(lines) - 1, -1, -1):\r
+ line = lines[index]\r
+ if line.strip() == '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 4 </td>':\r
+ lines[index] = '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 4 [IA32] </td>'\r
+ if line.strip() == '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 0x10 </td>':\r
+ lines[index] = '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 0x10 [IPF] </td>'\r
+ if line.strip() == '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8 </td>':\r
+ lines[index] = '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 9 [EBC, x64] </td>'\r
+ if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 4') != -1:\r
+ lines[index] = lines[index].replace('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 4',\r
+ 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 4 [IA32]')\r
+ if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 0x10') != -1:\r
+ lines[index] = lines[index].replace('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 0x10',\r
+ 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 0x10 [IPF]')\r
+ if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 8') != -1:\r
+ lines[index] = lines[index].replace('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 8',\r
+ 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 8 [x64, EBC]')\r
+ if line.find('>BASE_LIBRARY_JUMP_BUFFER</a>') != -1:\r
+ if lastBaseJumpIndex != -1:\r
+ del lines[lastBaseJumpIndex]\r
+ lastBaseJumpIndex = index\r
+ if line.find('>IA32_IDT_GATE_DESCRIPTOR</a></td>') != -1:\r
+ if lastIdtGateDescriptor != -1:\r
+ del lines[lastIdtGateDescriptor]\r
+ lastIdtGateDescriptor = index\r
+ try:\r
+ f = open(path, 'w')\r
+ f.write('\n'.join(lines))\r
+ f.close()\r
+ except:\r
+ logging.getLogger().error(" <<< Fail to fixup file %s\n" % path)\r
+ return\r
+ print " <<< Finish to fixup file %s\n" % path\r
+\r
+def FixPageIA32_IDT_GATE_DESCRIPTOR(path, text):\r
+ print ' >>> Fixup structure reference IA32_IDT_GATE_DESCRIPTOR at file %s \n' % path\r
+ lines = text.split('\n')\r
+ for index in range(len(lines) - 1, -1, -1):\r
+ line = lines[index].strip()\r
+ if line.find('struct {</td>') != -1 and lines[index - 2].find('>Uint64</a></td>') != -1:\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For X64</h2></td></tr>')\r
+ if line.find('struct {</td>') != -1 and lines[index - 1].find('Data Fields') != -1:\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For IA32</h2></td></tr>')\r
+ try:\r
+ f = open(path, 'w')\r
+ f.write('\n'.join(lines))\r
+ f.close()\r
+ except:\r
+ logging.getLogger().error(" <<< Fail to fixup file %s\n" % path)\r
+ return\r
+ print " <<< Finish to fixup file %s\n" % path\r
+\r
+def FixPageBASE_LIBRARY_JUMP_BUFFER(path, text):\r
+ print ' >>> Fixup structure reference BASE_LIBRARY_JUMP_BUFFER at file %s \n' % path\r
+ lines = text.split('\n')\r
+ bInDetail = True\r
+ bNeedRemove = False\r
+ for index in range(len(lines) - 1, -1, -1):\r
+ line = lines[index]\r
+ if line.find('Detailed Description') != -1:\r
+ bInDetail = False\r
+ if line.startswith('EBC context buffer used by') and lines[index - 1].startswith('x64 context buffer'):\r
+ lines[index] = "IA32/IPF/X64/" + line\r
+ bNeedRemove = True\r
+ if line.startswith("x64 context buffer") or line.startswith('IPF context buffer used by') or \\r
+ line.startswith('IA32 context buffer used by'):\r
+ if bNeedRemove:\r
+ lines.remove(line)\r
+ if line.find('>R0</a>') != -1 and not bInDetail:\r
+ if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For EBC</h2></td></tr>':\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For EBC</h2></td></tr>')\r
+ if line.find('>Rbx</a>') != -1 and not bInDetail:\r
+ if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For X64</h2></td></tr>':\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For X64</h2></td></tr>')\r
+ if line.find('>F2</a>') != -1 and not bInDetail:\r
+ if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For IPF</h2></td></tr>':\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For IPF</h2></td></tr>')\r
+ if line.find('>Ebx</a>') != -1 and not bInDetail:\r
+ if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For IA32</h2></td></tr>':\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For IA32</h2></td></tr>')\r
+ try:\r
+ f = open(path, 'w')\r
+ f.write('\n'.join(lines))\r
+ f.close()\r
+ except:\r
+ logging.getLogger().error(" <<< Fail to fixup file %s" % path)\r
+ return\r
+ print " <<< Finish to fixup file %s\n" % path\r
+\r
+def FixPageUefiDriverEntryPoint(path, text):\r
+ print ' >>> Fixup file reference MdePkg/Include/Library/UefiDriverEntryPoint.h at file %s \n' % path\r
+ lines = text.split('\n')\r
+ bInModuleEntry = False\r
+ bInEfiMain = False\r
+ ModuleEntryDlCount = 0\r
+ ModuleEntryDelStart = 0\r
+ ModuleEntryDelEnd = 0\r
+ EfiMainDlCount = 0\r
+ EfiMainDelStart = 0\r
+ EfiMainDelEnd = 0\r
+\r
+ for index in range(len(lines)):\r
+ line = lines[index].strip()\r
+ if line.find('EFI_STATUS</a> EFIAPI _ModuleEntryPoint </td>') != -1:\r
+ bInModuleEntry = True\r
+ if line.find('EFI_STATUS</a> EFIAPI EfiMain </td>') != -1:\r
+ bInEfiMain = True\r
+ if line.startswith('<p>References <a'):\r
+ if bInModuleEntry:\r
+ ModuleEntryDelEnd = index - 1\r
+ bInModuleEntry = False\r
+ elif bInEfiMain:\r
+ EfiMainDelEnd = index - 1\r
+ bInEfiMain = False\r
+ if bInModuleEntry:\r
+ if line.startswith('</dl>'):\r
+ ModuleEntryDlCount = ModuleEntryDlCount + 1\r
+ if ModuleEntryDlCount == 1:\r
+ ModuleEntryDelStart = index + 1\r
+ if bInEfiMain:\r
+ if line.startswith('</dl>'):\r
+ EfiMainDlCount = EfiMainDlCount + 1\r
+ if EfiMainDlCount == 1:\r
+ EfiMainDelStart = index + 1\r
+\r
+ if EfiMainDelEnd > EfiMainDelStart:\r
+ for index in range(EfiMainDelEnd, EfiMainDelStart, -1):\r
+ del lines[index]\r
+ if ModuleEntryDelEnd > ModuleEntryDelStart:\r
+ for index in range(ModuleEntryDelEnd, ModuleEntryDelStart, -1):\r
+ del lines[index]\r
+\r
+ try:\r
+ f = open(path, 'w')\r
+ f.write('\n'.join(lines))\r
+ f.close()\r
+ except:\r
+ logging.getLogger().error(" <<< Fail to fixup file %s" % path)\r
+ return\r
+ print " <<< Finish to fixup file %s\n" % path\r
+\r
+\r
+def FixPageUefiApplicationEntryPoint(path, text):\r
+ print ' >>> Fixup file reference MdePkg/Include/Library/UefiApplicationEntryPoint.h at file %s \n' % path\r
+ lines = text.split('\n')\r
+ bInModuleEntry = False\r
+ bInEfiMain = False\r
+ ModuleEntryDlCount = 0\r
+ ModuleEntryDelStart = 0\r
+ ModuleEntryDelEnd = 0\r
+ EfiMainDlCount = 0\r
+ EfiMainDelStart = 0\r
+ EfiMainDelEnd = 0\r
+\r
+ for index in range(len(lines)):\r
+ line = lines[index].strip()\r
+ if line.find('EFI_STATUS</a> EFIAPI _ModuleEntryPoint </td>') != -1:\r
+ bInModuleEntry = True\r
+ if line.find('EFI_STATUS</a> EFIAPI EfiMain </td>') != -1:\r
+ bInEfiMain = True\r
+ if line.startswith('<p>References <a'):\r
+ if bInModuleEntry:\r
+ ModuleEntryDelEnd = index - 1\r
+ bInModuleEntry = False\r
+ elif bInEfiMain:\r
+ EfiMainDelEnd = index - 1\r
+ bInEfiMain = False\r
+ if bInModuleEntry:\r
+ if line.startswith('</dl>'):\r
+ ModuleEntryDlCount = ModuleEntryDlCount + 1\r
+ if ModuleEntryDlCount == 1:\r
+ ModuleEntryDelStart = index + 1\r
+ if bInEfiMain:\r
+ if line.startswith('</dl>'):\r
+ EfiMainDlCount = EfiMainDlCount + 1\r
+ if EfiMainDlCount == 1:\r
+ EfiMainDelStart = index + 1\r
+\r
+ if EfiMainDelEnd > EfiMainDelStart:\r
+ for index in range(EfiMainDelEnd, EfiMainDelStart, -1):\r
+ del lines[index]\r
+ if ModuleEntryDelEnd > ModuleEntryDelStart:\r
+ for index in range(ModuleEntryDelEnd, ModuleEntryDelStart, -1):\r
+ del lines[index]\r
+\r
+ try:\r
+ f = open(path, 'w')\r
+ f.write('\n'.join(lines))\r
+ f.close()\r
+ except:\r
+ logging.getLogger().error(" <<< Fail to fixup file %s" % path)\r
+ return\r
+ print " <<< Finish to fixup file %s\n" % path\r
+\r
+if __name__ == '__main__':\r
+ wspath, pkgpath, doxpath, outpath, archtag, docmode, isinc, hwpath = parseCmdArgs()\r
+\r
+ # configure logging system\r
+ logfilepath = os.path.join(outpath, 'log.txt')\r
+ logging.basicConfig(format='%(levelname)-8s %(message)s', level=logging.DEBUG)\r
+\r
+ # create package model object firstly\r
+ pkgObj = createPackageObject(wspath, pkgpath)\r
+ if pkgObj == None:\r
+ sys.exit(-1)\r
+\r
+ # create doxygen action model\r
+ arch = None\r
+ tooltag = None\r
+ if archtag.lower() != 'all':\r
+ arch = archtag.split('_')[0]\r
+ tooltag = archtag.split('_')[1]\r
+ else:\r
+ arch = 'all'\r
+ tooltag = 'all'\r
+\r
+ # preprocess package and call doxygen\r
+ try:\r
+ action = doxygengen.PackageDocumentAction(doxpath,\r
+ hwpath,\r
+ outpath,\r
+ pkgObj,\r
+ docmode,\r
+ callbackLogMessage,\r
+ arch,\r
+ tooltag,\r
+ isinc,\r
+ True)\r
+ action.RegisterCallbackDoxygenProcess(callbackCreateDoxygenProcess)\r
+ action.Generate()\r
+ except:\r
+ message = traceback.format_exception(*sys.exc_info())\r
+ logging.getLogger().error('Fail to create doxygen action! \n%s' % ''.join(message))\r
+ sys.exit(-1)\r
+\r
+ DocumentFixup(outpath, arch)\r
+\r
+ # generate CHM is necessary\r
+ if docmode.lower() == 'chm':\r
+ indexpath = os.path.join(outpath, 'html', 'index.hhp')\r
+ if sys.platform == 'win32':\r
+ cmd = '"%s" %s' % (hwpath, indexpath)\r
+ else:\r
+ cmd = '%s %s' % (hwpath, indexpath)\r
+ subprocess.call(cmd)\r
+ print '\nFinish to generate package document! Please open %s for review' % os.path.join(outpath, 'html', 'index.chm')\r
+ else:\r
+ print '\nFinish to generate package document! Please open %s for review' % os.path.join(outpath, 'html', 'index.html')\r
--- /dev/null
+## @file\r
+# This file is used to define common string related functions used in parsing\r
+# process\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+import os, sys, wx, logging\r
+\r
+import wx.stc\r
+import wx.lib.newevent\r
+import wx.lib.agw.genericmessagedialog as GMD\r
+import plugins.EdkPlugins.edk2.model.baseobject as baseobject\r
+import plugins.EdkPlugins.edk2.model.doxygengen as doxygengen\r
+\r
+if hasattr(sys, "frozen"):\r
+ appPath = os.path.abspath(os.path.dirname(sys.executable))\r
+else:\r
+ appPath = os.path.abspath(os.path.dirname(__file__))\r
+\r
+AppCallBackEvent, EVT_APP_CALLBACK = wx.lib.newevent.NewEvent()\r
+LogEvent, EVT_LOG = wx.lib.newevent.NewEvent()\r
+\r
+class PackageDocApp(wx.App):\r
+\r
+ def OnInit(self):\r
+ logfile = os.path.join(appPath, 'log.txt')\r
+ logging.basicConfig(format='%(name)-8s %(levelname)-8s %(message)s',\r
+ filename=logfile, level=logging.ERROR)\r
+\r
+ self.SetAppName('Package Doxygen Generate Application')\r
+ frame = PackageDocMainFrame(None, "Package Document Generation Application!")\r
+ self.SetTopWindow(frame)\r
+\r
+ frame.Show(True)\r
+\r
+ EVT_APP_CALLBACK( self, self.OnAppCallBack)\r
+ return True\r
+\r
+ def GetLogger(self):\r
+ return logging.getLogger('')\r
+\r
+ def ForegroundProcess(self, function, args):\r
+ wx.PostEvent(self, AppCallBackEvent(callback=function, args=args))\r
+\r
+ def OnAppCallBack(self, event):\r
+ try:\r
+ event.callback(*event.args)\r
+ except:\r
+ self._logger.exception( 'OnAppCallBack<%s.%s>\n' %\r
+ (event.callback.__module__, event.callback.__name__ ))\r
+\r
+class PackageDocMainFrame(wx.Frame):\r
+ def __init__(self, parent, title):\r
+ wx.Frame.__init__(self, parent, -1, title, size=(550, 290), style=wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.CAPTION|wx.CLOSE_BOX )\r
+\r
+ panel = wx.Panel(self)\r
+ sizer = wx.BoxSizer(wx.VERTICAL)\r
+\r
+ subsizer = wx.GridBagSizer(5, 10)\r
+ subsizer.AddGrowableCol(1)\r
+ subsizer.Add(wx.StaticText(panel, -1, "Workspace Location : "), (0, 0), flag=wx.ALIGN_CENTER_VERTICAL)\r
+ self._workspacePathCtrl = wx.ComboBox(panel, -1)\r
+ list = self.GetConfigure("WorkspacePath")\r
+ if len(list) != 0:\r
+ for item in list:\r
+ self._workspacePathCtrl.Append(item)\r
+ self._workspacePathCtrl.SetValue(list[len(list) - 1])\r
+\r
+ subsizer.Add(self._workspacePathCtrl, (0, 1), flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)\r
+ self._workspacePathBt = wx.BitmapButton(panel, -1, bitmap=wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN))\r
+ subsizer.Add(self._workspacePathBt, (0, 2), flag=wx.ALIGN_CENTER_VERTICAL)\r
+ wx.EVT_BUTTON(self._workspacePathBt, self._workspacePathBt.GetId(), self.OnBrowsePath)\r
+\r
+ subsizer.Add(wx.StaticText(panel, -1, "Package DEC Location : "), (1, 0), flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)\r
+ self._packagePathCtrl = wx.ComboBox(panel, -1)\r
+ list = self.GetConfigure("PackagePath")\r
+ if len(list) != 0:\r
+ for item in list:\r
+ self._packagePathCtrl.Append(item)\r
+ self._packagePathCtrl.SetValue(list[len(list) - 1])\r
+ subsizer.Add(self._packagePathCtrl, (1, 1), flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)\r
+ self._packagePathBt = wx.BitmapButton(panel, -1, bitmap=wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN))\r
+ subsizer.Add(self._packagePathBt, (1, 2), flag=wx.ALIGN_CENTER_VERTICAL)\r
+ wx.EVT_BUTTON(self._packagePathBt, self._packagePathBt.GetId(), self.OnBrowsePath)\r
+\r
+ subsizer.Add(wx.StaticText(panel, -1, "Doxygen Tool Location : "), (2, 0), flag=wx.ALIGN_CENTER_VERTICAL)\r
+ self._doxygenPathCtrl = wx.TextCtrl(panel, -1)\r
+ list = self.GetConfigure('DoxygenPath')\r
+ if len(list) != 0:\r
+ self._doxygenPathCtrl.SetValue(list[0])\r
+ else:\r
+ if wx.Platform == '__WXMSW__':\r
+ self._doxygenPathCtrl.SetValue('C:\\Program Files\\Doxygen\\bin\\doxygen.exe')\r
+ else:\r
+ self._doxygenPathCtrl.SetValue('/usr/bin/doxygen')\r
+\r
+ self._doxygenPathBt = wx.BitmapButton(panel, -1, bitmap=wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN))\r
+ subsizer.Add(self._doxygenPathCtrl, (2, 1), flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)\r
+ subsizer.Add(self._doxygenPathBt, (2, 2), flag=wx.ALIGN_CENTER_VERTICAL)\r
+ wx.EVT_BUTTON(self._doxygenPathBt, self._doxygenPathBt.GetId(), self.OnBrowsePath)\r
+\r
+ subsizer.Add(wx.StaticText(panel, -1, "CHM Tool Location : "), (3, 0), flag=wx.ALIGN_CENTER_VERTICAL)\r
+ self._chmPathCtrl = wx.TextCtrl(panel, -1)\r
+ list = self.GetConfigure('CHMPath')\r
+ if len(list) != 0:\r
+ self._chmPathCtrl.SetValue(list[0])\r
+ else:\r
+ self._chmPathCtrl.SetValue('C:\\Program Files\\HTML Help Workshop\\hhc.exe')\r
+\r
+ self._chmPathBt = wx.BitmapButton(panel, -1, bitmap=wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN))\r
+ subsizer.Add(self._chmPathCtrl, (3, 1), flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)\r
+ subsizer.Add(self._chmPathBt, (3, 2), flag=wx.ALIGN_CENTER_VERTICAL)\r
+ wx.EVT_BUTTON(self._chmPathBt, self._chmPathBt.GetId(), self.OnBrowsePath)\r
+\r
+ subsizer.Add(wx.StaticText(panel, -1, "Output Location : "), (4, 0), flag=wx.ALIGN_CENTER_VERTICAL)\r
+ self._outputPathCtrl = wx.ComboBox(panel, -1)\r
+ list = self.GetConfigure("OutputPath")\r
+ if len(list) != 0:\r
+ for item in list:\r
+ self._outputPathCtrl.Append(item)\r
+ self._outputPathCtrl.SetValue(list[len(list) - 1])\r
+\r
+ subsizer.Add(self._outputPathCtrl, (4, 1), flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)\r
+ self._outputPathBt = wx.BitmapButton(panel, -1, bitmap=wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN))\r
+ subsizer.Add(self._outputPathBt, (4, 2), flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)\r
+ wx.EVT_BUTTON(self._outputPathBt, self._outputPathBt.GetId(), self.OnBrowsePath)\r
+\r
+ subsizer.Add(wx.StaticText(panel, -1, "Architecture Specified : "), (5, 0), flag=wx.ALIGN_CENTER_VERTICAL)\r
+ self._archCtrl = wx.ComboBox(panel, -1, value='ALL', choices=['ALL', 'IA32/MSFT', 'IA32/GNU', 'X64/INTEL', 'X64/GNU', 'IPF/MSFT', 'IPF/GNU', 'EBC/INTEL'],\r
+ style=wx.CB_READONLY)\r
+ self._archCtrl.Bind(wx.EVT_COMBOBOX, self.OnArchtectureSelectChanged)\r
+ subsizer.Add(self._archCtrl, (5, 1), (1, 2), flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)\r
+ sizer.Add(subsizer, 0, wx.EXPAND|wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT, 5)\r
+\r
+ sizer6 = wx.BoxSizer(wx.HORIZONTAL)\r
+ self._modesel = wx.RadioBox(panel, -1, 'Generated Document Mode', majorDimension=2, choices=['CHM', 'HTML'], style=wx.RA_SPECIFY_COLS)\r
+ self._modesel.SetStringSelection('HTML')\r
+\r
+ self._includeonlysel = wx.CheckBox(panel, -1, 'Only document public include')\r
+\r
+ sizer6.Add(self._modesel, 0 , wx.EXPAND)\r
+ sizer6.Add(self._includeonlysel, 0, wx.EXPAND|wx.LEFT, 5)\r
+\r
+ sizer.Add(sizer6, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)\r
+\r
+ self._generateBt = wx.Button(panel, -1, "Generate Package Document!")\r
+ self._generateBt.Bind(wx.EVT_BUTTON, self.OnGenerate)\r
+ sizer.Add(self._generateBt, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)\r
+\r
+ panel.SetSizer(sizer)\r
+ panel.Layout()\r
+ panel.SetAutoLayout(True)\r
+ self.CenterOnScreen()\r
+\r
+ def SaveConfigure(self, name, value):\r
+ if value ==None or len(value) == 0:\r
+ return\r
+ config = wx.ConfigBase_Get()\r
+ oldvalues = config.Read(name, '').split(';')\r
+ if len(oldvalues) >= 10:\r
+ oldvalues.remove(oldvalues[0])\r
+ if value not in oldvalues:\r
+ oldvalues.append(value)\r
+ else:\r
+ oldvalues.remove(value)\r
+ oldvalues.append(value)\r
+\r
+ config.Write(name, ';'.join(oldvalues))\r
+\r
+ def GetConfigure(self, name):\r
+ config = wx.ConfigBase_Get()\r
+ values = config.Read(name, '').split(';')\r
+ list = []\r
+ for item in values:\r
+ if len(item) != 0:\r
+ list.append(item)\r
+ return list\r
+\r
+ def OnBrowsePath(self, event):\r
+ id = event.GetId()\r
+ editctrl = None\r
+ startdir = ''\r
+ isFile = False\r
+ if id == self._packagePathBt.GetId():\r
+ dlgTitle = "Choose package path:"\r
+ editctrl = self._packagePathCtrl\r
+ isFile = True\r
+ if os.path.exists(self.GetWorkspace()):\r
+ startdir = self.GetWorkspace()\r
+ elif id == self._workspacePathBt.GetId():\r
+ dlgTitle = "Choose workspace path:"\r
+ editctrl = self._workspacePathCtrl\r
+ startdir = editctrl.GetValue()\r
+ elif id == self._doxygenPathBt.GetId():\r
+ isFile = True\r
+ dlgTitle = "Choose doxygen installation path:"\r
+ editctrl = self._doxygenPathCtrl\r
+ startdir = editctrl.GetValue()\r
+ elif id == self._outputPathBt.GetId():\r
+ dlgTitle = "Choose document output path:"\r
+ editctrl = self._outputPathCtrl\r
+ if os.path.exists(self.GetWorkspace()):\r
+ startdir = self.GetWorkspace()\r
+ startdir = editctrl.GetValue()\r
+ elif id == self._chmPathBt.GetId():\r
+ isFile = True\r
+ dlgTitle = "Choose installation path for Microsoft HTML workshop software"\r
+ editctrl = self._chmPathCtrl\r
+ startdir = editctrl.GetValue()\r
+ else:\r
+ return\r
+\r
+ if not isFile:\r
+ dlg = wx.DirDialog(self, dlgTitle, defaultPath=startdir)\r
+ else:\r
+ dlg = wx.FileDialog(self, dlgTitle, defaultDir=startdir)\r
+\r
+ if dlg.ShowModal() == wx.ID_OK:\r
+ editctrl.SetValue(dlg.GetPath())\r
+ dlg.Destroy()\r
+\r
+ def OnArchtectureSelectChanged(self, event):\r
+ str = ''\r
+ selarch = self._archCtrl.GetValue()\r
+ if selarch == 'ALL':\r
+ str += 'MDE_CPU_IA32 MDE_CPU_X64 MDE_CPU_EBC MDE_CPU_IPF _MSC_EXTENSIONS __GNUC__ __INTEL_COMPILER'\r
+ elif selarch == 'IA32/MSFT':\r
+ str += 'MDE_CPU_IA32 _MSC_EXTENSIONS'\r
+ elif selarch == 'IA32/GNU':\r
+ str += 'MDE_CPU_IA32 __GNUC__'\r
+ elif selarch == 'X64/MSFT':\r
+ str += 'MDE_CPU_X64 _MSC_EXTENSIONS'\r
+ elif selarch == 'X64/GNU':\r
+ str += 'MDE_CPU_X64 __GNUC__'\r
+ elif selarch == 'IPF/MSFT':\r
+ str += 'MDE_CPU_IPF _MSC_EXTENSIONS'\r
+ elif selarch == 'IPF/GNU':\r
+ str += 'MDE_CPU_IPF __GNUC__'\r
+ elif selarch == 'EBC/INTEL':\r
+ str += 'MDE_CPU_EBC __INTEL_COMPILER'\r
+\r
+ str += ' ASM_PFX= OPTIONAL= '\r
+\r
+ def OnMacroText(self, event):\r
+ str = ''\r
+ selarch = self._archCtrl.GetValue()\r
+ if selarch == 'ALL':\r
+ str += 'MDE_CPU_IA32 MDE_CPU_X64 MDE_CPU_EBC MDE_CPU_IPF _MSC_EXTENSIONS __GNUC__ __INTEL_COMPILER'\r
+ elif selarch == 'IA32/MSFT':\r
+ str += 'MDE_CPU_IA32 _MSC_EXTENSIONS'\r
+ elif selarch == 'IA32/GNU':\r
+ str += 'MDE_CPU_IA32 __GNUC__'\r
+ elif selarch == 'X64/MSFT':\r
+ str += 'MDE_CPU_X64 _MSC_EXTENSIONS'\r
+ elif selarch == 'X64/GNU':\r
+ str += 'MDE_CPU_X64 __GNUC__'\r
+ elif selarch == 'IPF/MSFT':\r
+ str += 'MDE_CPU_IPF _MSC_EXTENSIONS'\r
+ elif selarch == 'IPF/GNU':\r
+ str += 'MDE_CPU_IPF __GNUC__'\r
+ elif selarch == 'EBC/INTEL':\r
+ str += 'MDE_CPU_EBC __INTEL_COMPILER'\r
+\r
+ str += ' ASM_PFX= OPTIONAL= '\r
+\r
+ def OnGenerate(self, event):\r
+ if not self.CheckInput(): return\r
+\r
+ dlg = ProgressDialog(self)\r
+ dlg.ShowModal()\r
+ dlg.Destroy()\r
+\r
+ def CheckInput(self):\r
+ pPath = self.GetPackagePath()\r
+ wPath = self.GetWorkspace()\r
+ dPath = self.GetDoxygenToolPath()\r
+ cPath = self.GetChmToolPath()\r
+ oPath = self.GetOutputPath()\r
+\r
+ if len(wPath) == 0 or not os.path.exists(wPath):\r
+ self._Error("Please input existing workspace path!")\r
+ return False\r
+ else:\r
+ self.SaveConfigure('WorkspacePath', wPath)\r
+\r
+ if len(pPath) == 0 or not os.path.exists(pPath) or not pPath.lower().endswith('.dec'):\r
+ self._Error("Please input existing package file location!")\r
+ return False\r
+ elif pPath.lower().find(wPath.lower()) == -1:\r
+ self._Error("Package patch should starts with workspace path, such as if workspace path is c:\\edk2, package patch could be c:\\edk2\MdePkg")\r
+ return False\r
+ else:\r
+ self.SaveConfigure('PackagePath', pPath)\r
+\r
+ if len(dPath) == 0 or not os.path.exists(dPath):\r
+ self._Error("Can not find doxygen tool from path %s! Please download it from www.stack.nl/~dimitri/doxygen/download.html" % dPath)\r
+ return False\r
+ else:\r
+ self.SaveConfigure('DoxygenPath', dPath)\r
+\r
+ if self._modesel.GetStringSelection() == 'CHM':\r
+ if (len(cPath) == 0 or not os.path.exists(cPath)):\r
+ self._Error("You select CHM mode to generate document, but can not find software of Microsoft HTML Help Workshop.\nPlease\\r
+ download it from http://www.microsoft.com/downloads/details.aspx?FamilyID=00535334-c8a6-452f-9aa0-d597d16580cc&displaylang=en\n\\r
+and install!")\r
+ return False\r
+ else:\r
+ self.SaveConfigure('CHMPath', cPath)\r
+\r
+ if len(oPath) == 0:\r
+ self._Error("You must specific document output path")\r
+ return False\r
+ else:\r
+ self.SaveConfigure('OutputPath', oPath)\r
+\r
+ if os.path.exists(oPath):\r
+ # add checking whether there is old doxygen config file here\r
+ files = os.listdir(oPath)\r
+ for file in files:\r
+ if os.path.isfile(os.path.join(oPath,file)):\r
+ basename, ext = os.path.splitext(file)\r
+ if ext.lower() == '.doxygen_config':\r
+ dlg = GMD.GenericMessageDialog(self, "Existing doxygen document in output directory will be overwritten\n, Are you sure?",\r
+ "Info", wx.ICON_WARNING|wx.YES_NO)\r
+ if dlg.ShowModal() == wx.ID_YES:\r
+ break\r
+ else:\r
+ return False\r
+ else:\r
+ try:\r
+ os.makedirs(oPath)\r
+ except:\r
+ self._Error("Fail to create output directory, please select another output directory!")\r
+ return False\r
+\r
+ return True\r
+\r
+ def _Error(self, message):\r
+ dlg = GMD.GenericMessageDialog(self, message,\r
+ "Error", wx.ICON_ERROR|wx.OK)\r
+ dlg.ShowModal()\r
+ dlg.Destroy()\r
+\r
+ def GetWorkspace(self):\r
+ return os.path.normpath(self._workspacePathCtrl.GetValue())\r
+\r
+ def GetPackagePath(self):\r
+ return os.path.normpath(self._packagePathCtrl.GetValue())\r
+\r
+ def GetOutputPath(self):\r
+ return os.path.normpath(self._outputPathCtrl.GetValue())\r
+\r
+ def GetDoxygenToolPath(self):\r
+ return os.path.normpath(self._doxygenPathCtrl.GetValue())\r
+\r
+ def GetChmToolPath(self):\r
+ return os.path.normpath(self._chmPathCtrl.GetValue())\r
+\r
+ def GetDocumentMode(self):\r
+ return self._modesel.GetStringSelection()\r
+\r
+ def GetArchitecture(self):\r
+ value = self._archCtrl.GetValue()\r
+ return value.split('/')[0]\r
+\r
+ def GetToolTag(self):\r
+ value = self._archCtrl.GetValue()\r
+ if value == 'ALL':\r
+ return 'ALL'\r
+ return value.split('/')[1]\r
+\r
+ def GetIsOnlyDocumentInclude(self):\r
+ return self._includeonlysel.IsChecked()\r
+\r
+class ProgressDialog(wx.Dialog):\r
+ def __init__(self, parent, id=wx.ID_ANY):\r
+ title = "Generate Document for " + parent.GetPackagePath()\r
+ wx.Dialog.__init__(self, parent, id, title=title, style=wx.CAPTION, size=(600, 300))\r
+ self.Freeze()\r
+ sizer = wx.BoxSizer(wx.VERTICAL)\r
+ self._textCtrl = wx.StaticText(self, -1, "Start launching!")\r
+ self._gaugeCtrl = wx.Gauge(self, -1, 100, size=(-1, 10))\r
+ self._resultCtrl = wx.stc.StyledTextCtrl(self, -1)\r
+ self._closeBt = wx.Button(self, -1, "Close")\r
+ self._gotoOuputBt = wx.Button(self, -1, "Goto Output")\r
+\r
+ # clear all margin\r
+ self._resultCtrl.SetMarginWidth(0, 0)\r
+ self._resultCtrl.SetMarginWidth(1, 0)\r
+ self._resultCtrl.SetMarginWidth(2, 0)\r
+\r
+ sizer.Add(self._textCtrl, 0, wx.EXPAND|wx.LEFT|wx.TOP|wx.RIGHT, 5)\r
+ sizer.Add(self._gaugeCtrl, 0, wx.EXPAND|wx.LEFT|wx.TOP|wx.RIGHT, 5)\r
+ sizer.Add(self._resultCtrl, 1, wx.EXPAND|wx.LEFT|wx.TOP|wx.RIGHT, 5)\r
+ btsizer = wx.BoxSizer(wx.HORIZONTAL)\r
+ btsizer.Add(self._gotoOuputBt, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.LEFT|wx.TOP|wx.LEFT|wx.BOTTOM, 5)\r
+ btsizer.Add(self._closeBt, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.LEFT|wx.TOP|wx.LEFT|wx.BOTTOM, 5)\r
+ sizer.Add(btsizer, 0, wx.ALIGN_CENTER_HORIZONTAL)\r
+\r
+ self.SetSizer(sizer)\r
+ self.CenterOnScreen()\r
+ self.Thaw()\r
+\r
+ self._logger = logging.getLogger('')\r
+ self._loghandle = ResultHandler(self)\r
+ logging.getLogger('edk').addHandler(self._loghandle)\r
+ logging.getLogger('').addHandler(self._loghandle)\r
+ logging.getLogger('app').addHandler(self._loghandle)\r
+\r
+ wx.EVT_BUTTON(self._closeBt, self._closeBt.GetId(), self.OnButtonClose)\r
+ wx.EVT_UPDATE_UI(self, self._closeBt.GetId(), self.OnUpdateCloseButton)\r
+ wx.EVT_BUTTON(self._gotoOuputBt, self._gotoOuputBt.GetId(), self.OnGotoOutput)\r
+ EVT_LOG(self, self.OnPostLog)\r
+\r
+ self._process = None\r
+ self._pid = None\r
+ self._input = None\r
+ self._output = None\r
+ self._error = None\r
+ self._inputThread = None\r
+ self._errorThread = None\r
+ self._isBusy = True\r
+ self._pObj = None\r
+\r
+ wx.CallAfter(self.GenerateAction)\r
+\r
+ def OnUpdateCloseButton(self, event):\r
+ self._closeBt.Enable(not self._isBusy)\r
+ return True\r
+\r
+ def OnButtonClose(self, event):\r
+ if self._isBusy:\r
+ self._InfoDialog("Please don't close in progressing...")\r
+ return\r
+\r
+ if self._process != None:\r
+ self._process.CloseOutput()\r
+\r
+ if self._inputThread:\r
+ self._inputThread.Terminate()\r
+ if self._errorThread:\r
+ self._errorThread.Terminate()\r
+\r
+ if self._pid != None:\r
+ wx.Process.Kill(self._pid, wx.SIGKILL, wx.KILL_CHILDREN)\r
+\r
+ logging.getLogger('edk').removeHandler(self._loghandle)\r
+ logging.getLogger('').removeHandler(self._loghandle)\r
+ logging.getLogger('app').removeHandler(self._loghandle)\r
+\r
+ if self._pObj != None:\r
+ self._pObj.Destroy()\r
+\r
+ self.EndModal(0)\r
+\r
+ def OnGotoOutput(self, event):\r
+ output = self.GetParent().GetOutputPath()\r
+ if os.path.exists(output):\r
+ if wx.Platform == '__WXMSW__':\r
+ os.startfile(self.GetParent().GetOutputPath())\r
+ else:\r
+ import webbrowser\r
+ webbrowser.open(self.GetParent().GetOutputPath())\r
+ else:\r
+ self._ErrorDialog("Output directory does not exist!")\r
+\r
+ def _ErrorDialog(self, message):\r
+ dlg = GMD.GenericMessageDialog(self, message,\r
+ "Error", wx.ICON_ERROR|wx.OK)\r
+ dlg.ShowModal()\r
+ dlg.Destroy()\r
+\r
+ def _InfoDialog(self, message):\r
+ dlg = GMD.GenericMessageDialog(self, message,\r
+ "Info", wx.ICON_INFORMATION|wx.OK)\r
+ dlg.ShowModal()\r
+ dlg.Destroy()\r
+\r
+ def _LogStep(self, index, message):\r
+ stepstr = "Step %d: %s" % (index, message)\r
+ self._textCtrl.SetLabel(stepstr)\r
+ self.LogMessage(os.linesep + stepstr + os.linesep)\r
+ self._gaugeCtrl.SetValue(index * 100 / 6 )\r
+\r
+ def OnPostLog(self, event):\r
+ self.LogMessage(event.message)\r
+\r
+ def GenerateAction(self):\r
+ self._LogStep(1, "Create Package Object Model")\r
+ wsPath = self.GetParent().GetWorkspace()\r
+ pkPath = self.GetParent().GetPackagePath()[len(wsPath) + 1:]\r
+\r
+ try:\r
+ pObj = baseobject.Package(None, self.GetParent().GetWorkspace())\r
+ pObj.Load(pkPath)\r
+ except:\r
+ self._ErrorDialog("Fail to create package object model! Please check log.txt under this application folder!")\r
+ self._isBusy = False\r
+ return\r
+ self._pObj = pObj\r
+\r
+ self.LogMessage(str(pObj.GetPcds()))\r
+\r
+ self._LogStep(2, "Preprocess and Generate Doxygen Config File")\r
+ try:\r
+ action = doxygengen.PackageDocumentAction(self.GetParent().GetDoxygenToolPath(),\r
+ self.GetParent().GetChmToolPath(),\r
+ self.GetParent().GetOutputPath(),\r
+ pObj,\r
+ self.GetParent().GetDocumentMode(),\r
+ self.LogMessage,\r
+ self.GetParent().GetArchitecture(),\r
+ self.GetParent().GetToolTag(),\r
+ self.GetParent().GetIsOnlyDocumentInclude(),\r
+ True)\r
+ except:\r
+ self._ErrorDialog("Fail to preprocess! Please check log.txt under this application folder!")\r
+ self._isBusy = False\r
+ return\r
+\r
+ action.RegisterCallbackDoxygenProcess(self.CreateDoxygeProcess)\r
+\r
+ try:\r
+ if not action.Generate():\r
+ self._isBusy = False\r
+ self.LogMessage("Fail to generate package document! Please check log.txt under this application folder!", 'error')\r
+ except:\r
+ import traceback\r
+ message = traceback.format_exception(*sys.exc_info())\r
+ logging.getLogger('').error(''.join(message))\r
+ self._isBusy = False\r
+ self._ErrorDialog("Fail to generate package document! Please check log.txt under this application folder!")\r
+\r
+ def LogMessage(self, message, level='info'):\r
+ self._resultCtrl.DocumentEnd()\r
+ self._resultCtrl.SetReadOnly(False)\r
+ self._resultCtrl.AppendText(message)\r
+ self._resultCtrl.Home()\r
+ self._resultCtrl.Home()\r
+ self._resultCtrl.SetReadOnly(True)\r
+ if level == 'error':\r
+ wx.GetApp().GetLogger().error(message)\r
+\r
+ def CreateDoxygeProcess(self, doxPath, configFile):\r
+ self._LogStep(3, "Launch Doxygen Tool and Generate Package Document")\r
+\r
+ cmd = '"%s" %s' % (doxPath, configFile)\r
+ try:\r
+ self._process = DoxygenProcess()\r
+ self._process.SetParent(self)\r
+ self._process.Redirect()\r
+ self._pid = wx.Execute(cmd, wx.EXEC_ASYNC, self._process)\r
+ self._input = self._process.GetInputStream()\r
+ self._output = self._process.GetOutputStream()\r
+ self._error = self._process.GetErrorStream()\r
+ except:\r
+ self._ErrorDialog('Fail to launch doxygen cmd %s! Please check log.txt under this application folder!' % cmd)\r
+ self._isBusy = False\r
+ return False\r
+\r
+ self._inputThread = MonitorThread(self._input, self.LogMessage)\r
+ self._errorThread = MonitorThread(self._error, self.LogMessage)\r
+ self._inputThread.start()\r
+ self._errorThread.start()\r
+ return True\r
+\r
+ def OnTerminateDoxygenProcess(self):\r
+ if self._inputThread:\r
+ self._inputThread.Terminate()\r
+ self._inputThread = None\r
+ if self._errorThread:\r
+ self._errorThread.Terminate()\r
+ self._errorThread = None\r
+\r
+ if self._error:\r
+ while self._error.CanRead():\r
+ text = self._error.read()\r
+ self.LogMessage(text)\r
+\r
+ if self._input:\r
+ while self._input.CanRead():\r
+ text = self._input.read()\r
+ self.LogMessage(text)\r
+ self._process.Detach()\r
+\r
+ self._process.CloseOutput()\r
+ self._process = None\r
+ self._pid = None\r
+\r
+ self.DocumentFixup()\r
+\r
+ if self.GetParent().GetDocumentMode().lower() == 'chm':\r
+ hhcfile = os.path.join(self.GetParent().GetOutputPath(), 'html', 'index.hhc')\r
+ hhpfile = os.path.join(self.GetParent().GetOutputPath(), 'html', 'index.hhp')\r
+ self.FixDecDoxygenFileLink(hhcfile, None)\r
+ if not self.CreateCHMProcess(self.GetParent().GetChmToolPath(), hhpfile):\r
+ self._ErrorDialog("Fail to Create %s process for %s" % (self.GetParent().GetChmToolPath(), hhpfile))\r
+ self._isBusy = False\r
+ else:\r
+ self._LogStep(6, "Finished Document Generation!")\r
+ self._isBusy = False\r
+ indexpath = os.path.realpath(os.path.join(self.GetParent().GetOutputPath(), 'html', 'index.html'))\r
+ if wx.Platform == '__WXMSW__':\r
+ os.startfile(indexpath)\r
+ else:\r
+ import webbrowser\r
+ webbrowser.open(indexpath)\r
+\r
+ self._InfoDialog('Success create HTML doxgen document %s' % indexpath)\r
+\r
+ def CreateCHMProcess(self, chmPath, hhpfile):\r
+ self.LogMessage(" >>>>>> Start Microsoft HTML workshop process...Zzz...\n")\r
+ cmd = '"%s" %s' % (chmPath, hhpfile)\r
+ try:\r
+ self._process = CHMProcess()\r
+ self._process.SetParent(self)\r
+ self._process.Redirect()\r
+ self._pid = wx.Execute(cmd, wx.EXEC_ASYNC, self._process)\r
+ self._input = self._process.GetInputStream()\r
+ self._output = self._process.GetOutputStream()\r
+ self._error = self._process.GetErrorStream()\r
+ except:\r
+ self.LogMessage('\nFail to launch hhp cmd %s!\n' % cmd)\r
+ self._isBusy = False\r
+ return False\r
+ self._inputThread = MonitorThread(self._input, self.LogMessage)\r
+ self._errorThread = MonitorThread(self._error, self.LogMessage)\r
+ self._inputThread.start()\r
+ self._errorThread.start()\r
+ return True\r
+\r
+ def OnTerminateCHMProcess(self):\r
+ if self._inputThread:\r
+ self._inputThread.Terminate()\r
+ self._inputThread = None\r
+ if self._errorThread:\r
+ self._errorThread.Terminate()\r
+ self._errorThread = None\r
+\r
+ if self._error:\r
+ while self._error.CanRead():\r
+ text = self._error.read()\r
+ self.LogMessage(text)\r
+ if self._input:\r
+ while self._input.CanRead():\r
+ text = self._input.read()\r
+ self.LogMessage(text)\r
+ self._process.Detach()\r
+\r
+ self._process.CloseOutput()\r
+ self._process = None\r
+ self._pid = None\r
+ self._isBusy = False\r
+ indexpath = os.path.realpath(os.path.join(self.GetParent().GetOutputPath(), 'html', 'index.chm'))\r
+ if os.path.exists(indexpath):\r
+ if wx.Platform == '__WXMSW__':\r
+ os.startfile(indexpath)\r
+ else:\r
+ import webbrowser\r
+ webbrowser.open(indexpath)\r
+\r
+ self._LogStep(6, "Finished Document Generation!")\r
+ self.LogMessage('\nSuccess create CHM doxgen document %s\n' % indexpath)\r
+ self._InfoDialog('Success create CHM doxgen document %s' % indexpath)\r
+\r
+ def DocumentFixup(self):\r
+ # find BASE_LIBRARY_JUMP_BUFFER structure reference page\r
+ self._LogStep(4, "Fixup Package Document!")\r
+ self.LogMessage('\n >>> Start fixup document \n')\r
+\r
+ for root, dirs, files in os.walk(os.path.join(self.GetParent().GetOutputPath(), 'html')):\r
+ for dir in dirs:\r
+ if dir.lower() in ['.svn', '_svn', 'cvs']:\r
+ dirs.remove(dir)\r
+ for file in files:\r
+ wx.YieldIfNeeded()\r
+ if not file.lower().endswith('.html'): continue\r
+ fullpath = os.path.join(self.GetParent().GetOutputPath(), root, file)\r
+ try:\r
+ f = open(fullpath, 'r')\r
+ text = f.read()\r
+ f.close()\r
+ except:\r
+ self.LogMessage('\nFail to open file %s\n' % fullpath)\r
+ continue\r
+ if text.find('BASE_LIBRARY_JUMP_BUFFER Struct Reference') != -1 and self.GetParent().GetArchitecture() == 'ALL':\r
+ self.FixPageBASE_LIBRARY_JUMP_BUFFER(fullpath, text)\r
+ if text.find('MdePkg/Include/Library/BaseLib.h File Reference') != -1 and self.GetParent().GetArchitecture() == 'ALL':\r
+ self.FixPageBaseLib(fullpath, text)\r
+ if text.find('IA32_IDT_GATE_DESCRIPTOR Union Reference') != -1 and self.GetParent().GetArchitecture() == 'ALL':\r
+ self.FixPageIA32_IDT_GATE_DESCRIPTOR(fullpath, text)\r
+ if text.find('MdePkg/Include/Library/UefiDriverEntryPoint.h File Reference') != -1:\r
+ self.FixPageUefiDriverEntryPoint(fullpath, text)\r
+ if text.find('MdePkg/Include/Library/UefiApplicationEntryPoint.h File Reference') != -1:\r
+ self.FixPageUefiApplicationEntryPoint(fullpath, text)\r
+ if text.lower().find('.s.dox') != -1 or \\r
+ text.lower().find('.asm.dox') != -1 or \\r
+ text.lower().find('.uni.dox') != -1:\r
+ self.FixDoxFileLink(fullpath, text)\r
+\r
+ self.RemoveFileList()\r
+ self.LogMessage(' >>> Finish all document fixing up! \n')\r
+\r
+ def RemoveFileList(self):\r
+ path_html = os.path.join(self.GetParent().GetOutputPath(), "html", "tree.html")\r
+ path_chm = os.path.join(self.GetParent().GetOutputPath(), "html", "index.hhc")\r
+ if os.path.exists(path_html):\r
+ self.LogMessage(' >>>Remove FileList item from generated HTML document.\n');\r
+ lines = []\r
+ f = open (path_html, "r")\r
+ lines = f.readlines()\r
+ f.close()\r
+ bfound = False\r
+ for index in xrange(len(lines)):\r
+ if lines[index].find('<a class="el" href="files.html" target="basefrm">File List</a>') != -1:\r
+ lines[index] = "<!-- %s" % lines[index]\r
+ bfound = True\r
+ continue\r
+ if bfound:\r
+ if lines[index].find('</div>') != -1:\r
+ lines[index] = "%s -->" % lines[index]\r
+ break\r
+ if bfound:\r
+ f = open(path_html, "w")\r
+ f.write("".join(lines))\r
+ f.close()\r
+ else:\r
+ self.LogMessage (' !!!Can not found FileList item in HTML document!\n')\r
+\r
+ if os.path.exists(path_chm):\r
+ self.LogMessage(" >>>Warning: Can not remove FileList for CHM files!\n");\r
+ """\r
+ self.LogMessage(' >>>Remove FileList item from generated CHM document!\n');\r
+ lines = []\r
+ f = open (path_chm, "r")\r
+ lines = f.readlines()\r
+ f.close()\r
+ bfound = False\r
+ for index in xrange(len(lines)):\r
+ if not bfound:\r
+ if lines[index].find('<param name="Local" value="files.html">') != -1:\r
+ lines[index] = '<!-- %s' % lines[index]\r
+ bfound = True\r
+ continue\r
+ if bfound:\r
+ if lines[index].find('</UL>') != -1:\r
+ lines[index] = '%s -->\n' % lines[index].rstrip()\r
+ break\r
+ if bfound:\r
+ f = open(path_chm, "w")\r
+ f.write("".join(lines))\r
+ f.close()\r
+ import time\r
+ time.sleep(2)\r
+ else:\r
+ self.LogMessage(' !!!Can not found the FileList item in CHM document!')\r
+ """\r
+ def FixPageBaseLib(self, path, text):\r
+ self.LogMessage(' >>> Fixup BaseLib file page at file %s \n' % path)\r
+ lines = text.split('\n')\r
+ lastBaseJumpIndex = -1\r
+ lastIdtGateDescriptor = -1\r
+ for index in range(len(lines) - 1, -1, -1):\r
+ line = lines[index]\r
+ if line.strip() == '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 4 </td>':\r
+ lines[index] = '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 4 [IA32] </td>'\r
+ if line.strip() == '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 0x10 </td>':\r
+ lines[index] = '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 0x10 [IPF] </td>'\r
+ if line.strip() == '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8 </td>':\r
+ lines[index] = '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 9 [EBC, x64] </td>'\r
+ if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 4') != -1:\r
+ lines[index] = lines[index].replace('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 4',\r
+ 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 4 [IA32]')\r
+ if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 0x10') != -1:\r
+ lines[index] = lines[index].replace('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 0x10',\r
+ 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 0x10 [IPF]')\r
+ if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 8') != -1:\r
+ lines[index] = lines[index].replace('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 8',\r
+ 'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a> 8 [x64, EBC]')\r
+ if line.find('>BASE_LIBRARY_JUMP_BUFFER</a>') != -1:\r
+ if lastBaseJumpIndex != -1:\r
+ del lines[lastBaseJumpIndex]\r
+ lastBaseJumpIndex = index\r
+ if line.find('>IA32_IDT_GATE_DESCRIPTOR</a></td>') != -1:\r
+ if lastIdtGateDescriptor != -1:\r
+ del lines[lastIdtGateDescriptor]\r
+ lastIdtGateDescriptor = index\r
+ try:\r
+ f = open(path, 'w')\r
+ f.write('\n'.join(lines))\r
+ f.close()\r
+ except:\r
+ self._isBusy = False\r
+ self.LogMessage(" <<< Fail to fixup file %s\n" % path)\r
+ self.LogMessage(" <<< Finish to fixup file %s\n" % path)\r
+\r
+ def FixPageIA32_IDT_GATE_DESCRIPTOR(self, path, text):\r
+ self.LogMessage(' >>> Fixup structure reference IA32_IDT_GATE_DESCRIPTOR at file %s \n' % path)\r
+ lines = text.split('\n')\r
+ for index in range(len(lines) - 1, -1, -1):\r
+ line = lines[index].strip()\r
+ if line.find('struct {</td>') != -1 and lines[index - 2].find('>Uint64</a></td>') != -1:\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For X64</h2></td></tr>')\r
+ if line.find('struct {</td>') != -1 and lines[index - 1].find('Data Fields') != -1:\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For IA32</h2></td></tr>')\r
+ try:\r
+ f = open(path, 'w')\r
+ f.write('\n'.join(lines))\r
+ f.close()\r
+ except:\r
+ self._isBusy = False\r
+ self.LogMessage(" <<< Fail to fixup file %s\n" % path)\r
+ self.LogMessage(" <<< Finish to fixup file %s\n" % path)\r
+\r
+ def FixPageBASE_LIBRARY_JUMP_BUFFER(self, path, text):\r
+ self.LogMessage(' >>> Fixup structure reference BASE_LIBRARY_JUMP_BUFFER at file %s \n' % path)\r
+ lines = text.split('\n')\r
+ bInDetail = True\r
+ bNeedRemove = False\r
+ for index in range(len(lines) - 1, -1, -1):\r
+ line = lines[index]\r
+ if line.find('Detailed Description') != -1:\r
+ bInDetail = False\r
+ if line.startswith('EBC context buffer used by') and lines[index - 1].startswith('x64 context buffer'):\r
+ lines[index] = "IA32/IPF/X64/" + line\r
+ bNeedRemove = True\r
+ if line.startswith("x64 context buffer") or line.startswith('IPF context buffer used by') or \\r
+ line.startswith('IA32 context buffer used by'):\r
+ if bNeedRemove:\r
+ lines.remove(line)\r
+ if line.find('>R0</a>') != -1 and not bInDetail:\r
+ if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For EBC</h2></td></tr>':\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For EBC</h2></td></tr>')\r
+ if line.find('>Rbx</a>') != -1 and not bInDetail:\r
+ if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For X64</h2></td></tr>':\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For X64</h2></td></tr>')\r
+ if line.find('>F2</a>') != -1 and not bInDetail:\r
+ if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For IPF</h2></td></tr>':\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For IPF</h2></td></tr>')\r
+ if line.find('>Ebx</a>') != -1 and not bInDetail:\r
+ if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For IA32</h2></td></tr>':\r
+ lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For IA32</h2></td></tr>')\r
+ try:\r
+ f = open(path, 'w')\r
+ f.write('\n'.join(lines))\r
+ f.close()\r
+ except:\r
+ self._isBusy = False\r
+ self.LogMessage(" <<< Fail to fixup file %s" % path)\r
+ self.LogMessage(" <<< Finish to fixup file %s\n" % path)\r
+\r
+ def FixPageUefiDriverEntryPoint(self, path, text):\r
+ self.LogMessage(' >>> Fixup file reference MdePkg/Include/Library/UefiDriverEntryPoint.h at file %s \n' % path)\r
+ lines = text.split('\n')\r
+ bInModuleEntry = False\r
+ bInEfiMain = False\r
+ ModuleEntryDlCount = 0\r
+ ModuleEntryDelStart = 0\r
+ ModuleEntryDelEnd = 0\r
+ EfiMainDlCount = 0\r
+ EfiMainDelStart = 0\r
+ EfiMainDelEnd = 0\r
+\r
+ for index in range(len(lines)):\r
+ line = lines[index].strip()\r
+ if line.find('EFI_STATUS</a> EFIAPI _ModuleEntryPoint </td>') != -1:\r
+ bInModuleEntry = True\r
+ if line.find('EFI_STATUS</a> EFIAPI EfiMain </td>') != -1:\r
+ bInEfiMain = True\r
+ if line.startswith('<p>References <a'):\r
+ if bInModuleEntry:\r
+ ModuleEntryDelEnd = index - 1\r
+ bInModuleEntry = False\r
+ elif bInEfiMain:\r
+ EfiMainDelEnd = index - 1\r
+ bInEfiMain = False\r
+ if bInModuleEntry:\r
+ if line.startswith('</dl>'):\r
+ ModuleEntryDlCount = ModuleEntryDlCount + 1\r
+ if ModuleEntryDlCount == 1:\r
+ ModuleEntryDelStart = index + 1\r
+ if bInEfiMain:\r
+ if line.startswith('</dl>'):\r
+ EfiMainDlCount = EfiMainDlCount + 1\r
+ if EfiMainDlCount == 1:\r
+ EfiMainDelStart = index + 1\r
+\r
+ if EfiMainDelEnd > EfiMainDelStart:\r
+ for index in range(EfiMainDelEnd, EfiMainDelStart, -1):\r
+ del lines[index]\r
+ if ModuleEntryDelEnd > ModuleEntryDelStart:\r
+ for index in range(ModuleEntryDelEnd, ModuleEntryDelStart, -1):\r
+ del lines[index]\r
+\r
+ try:\r
+ f = open(path, 'w')\r
+ f.write('\n'.join(lines))\r
+ f.close()\r
+ except:\r
+ self._isBusy = False\r
+ self.LogMessage(" <<< Fail to fixup file %s" % path)\r
+ self.LogMessage(" <<< Finish to fixup file %s\n" % path)\r
+\r
+ def FixPageUefiApplicationEntryPoint(self, path, text):\r
+ self.LogMessage(' >>> Fixup file reference MdePkg/Include/Library/UefiApplicationEntryPoint.h at file %s \n' % path)\r
+ lines = text.split('\n')\r
+ bInModuleEntry = False\r
+ bInEfiMain = False\r
+ ModuleEntryDlCount = 0\r
+ ModuleEntryDelStart = 0\r
+ ModuleEntryDelEnd = 0\r
+ EfiMainDlCount = 0\r
+ EfiMainDelStart = 0\r
+ EfiMainDelEnd = 0\r
+\r
+ for index in range(len(lines)):\r
+ line = lines[index].strip()\r
+ if line.find('EFI_STATUS</a> EFIAPI _ModuleEntryPoint </td>') != -1:\r
+ bInModuleEntry = True\r
+ if line.find('EFI_STATUS</a> EFIAPI EfiMain </td>') != -1:\r
+ bInEfiMain = True\r
+ if line.startswith('<p>References <a'):\r
+ if bInModuleEntry:\r
+ ModuleEntryDelEnd = index - 1\r
+ bInModuleEntry = False\r
+ elif bInEfiMain:\r
+ EfiMainDelEnd = index - 1\r
+ bInEfiMain = False\r
+ if bInModuleEntry:\r
+ if line.startswith('</dl>'):\r
+ ModuleEntryDlCount = ModuleEntryDlCount + 1\r
+ if ModuleEntryDlCount == 1:\r
+ ModuleEntryDelStart = index + 1\r
+ if bInEfiMain:\r
+ if line.startswith('</dl>'):\r
+ EfiMainDlCount = EfiMainDlCount + 1\r
+ if EfiMainDlCount == 1:\r
+ EfiMainDelStart = index + 1\r
+\r
+ if EfiMainDelEnd > EfiMainDelStart:\r
+ for index in range(EfiMainDelEnd, EfiMainDelStart, -1):\r
+ del lines[index]\r
+ if ModuleEntryDelEnd > ModuleEntryDelStart:\r
+ for index in range(ModuleEntryDelEnd, ModuleEntryDelStart, -1):\r
+ del lines[index]\r
+\r
+ try:\r
+ f = open(path, 'w')\r
+ f.write('\n'.join(lines))\r
+ f.close()\r
+ except:\r
+ self._isBusy = False\r
+ self.LogMessage(" <<< Fail to fixup file %s" % path)\r
+ self.LogMessage(" <<< Finish to fixup file %s\n" % path)\r
+\r
+\r
+ def FixDoxFileLink(self, path, text):\r
+ self.LogMessage(' >>> Fixup .dox postfix for file %s \n' % path)\r
+ try:\r
+ fd = open(path, 'r')\r
+ text = fd.read()\r
+ fd.close()\r
+ except Exception, e:\r
+ self.LogMessage (" <<<Fail to open file %s" % path)\r
+ return\r
+ text = text.replace ('.s.dox', '.s')\r
+ text = text.replace ('.S.dox', '.S')\r
+ text = text.replace ('.asm.dox', '.asm')\r
+ text = text.replace ('.Asm.dox', '.Asm')\r
+ text = text.replace ('.uni.dox', '.uni')\r
+ text = text.replace ('.Uni.dox', '.Uni')\r
+ try:\r
+ fd = open(path, 'w')\r
+ fd.write(text)\r
+ fd.close()\r
+ except Exception, e:\r
+ self.LogMessage (" <<<Fail to fixup file %s" % path)\r
+ return\r
+ self.LogMessage(' >>> Finish to fixup .dox postfix for file %s \n' % path)\r
+\r
+ def FixDecDoxygenFileLink(self, path, text):\r
+ self.LogMessage(' >>> Fixup .decdoxygen postfix for file %s \n' % path)\r
+ try:\r
+ fd = open(path, 'r')\r
+ lines = fd.readlines()\r
+ fd.close()\r
+ except Exception, e:\r
+ self.LogMessage (" <<<Fail to open file %s" % path)\r
+ return\r
+ for line in lines:\r
+ if line.find('.decdoxygen') != -1:\r
+ lines.remove(line)\r
+ break\r
+ try:\r
+ fd = open(path, 'w')\r
+ fd.write("".join(lines))\r
+ fd.close()\r
+ except Exception, e:\r
+ self.LogMessage (" <<<Fail to fixup file %s" % path)\r
+ return\r
+ self.LogMessage(' >>> Finish to fixup .decdoxygen postfix for file %s \n' % path)\r
+\r
+import threading\r
+class MonitorThread(threading.Thread):\r
+ def __init__(self, pipe, callback):\r
+ threading.Thread.__init__(self)\r
+ self._pipe = pipe\r
+ self._callback = callback\r
+ self._isCancel = False\r
+\r
+ def run(self):\r
+ while (not self._isCancel):\r
+ self._pipe.Peek()\r
+ if self._pipe.LastRead() == 0:\r
+ break\r
+ text = self._pipe.read()\r
+ if len(text.strip()) != 0:\r
+ wx.GetApp().ForegroundProcess(self._callback, (text,))\r
+\r
+ def Terminate(self):\r
+ self._pipe.flush()\r
+ self._isCancel = True\r
+\r
+class DoxygenProcess(wx.Process):\r
+ def OnTerminate(self, id, status):\r
+ self._parent.OnTerminateDoxygenProcess()\r
+\r
+ def SetParent(self, parent):\r
+ self._parent = parent\r
+\r
+class CHMProcess(wx.Process):\r
+ def OnTerminate(self, id, status):\r
+ self._parent.OnTerminateCHMProcess()\r
+\r
+ def SetParent(self, parent):\r
+ self._parent = parent\r
+\r
+class ResultHandler:\r
+ def __init__(self, parent):\r
+ self._parent = parent\r
+ self.level = 0\r
+\r
+ def emit(self, record):\r
+ self._parent.LogMessage(record)\r
+\r
+ def handle(self, record):\r
+ wx.PostEvent(self._parent, LogEvent(message=record.getMessage()))\r
+\r
+ def acquire(self):\r
+ pass\r
+\r
+ def release(self):\r
+ pass\r
+\r
+if __name__ == '__main__':\r
+ app = PackageDocApp(redirect=False)\r
+ app.MainLoop()\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+import os\r
+\r
+from message import *\r
+\r
+class BaseDoxygeItem:\r
+ def __init__(self, name, tag=''):\r
+ self.mName = name\r
+ self.mTag = tag\r
+ self.mDescription = ''\r
+ self.mText = []\r
+\r
+ def AddDescription(self, desc):\r
+ self.mDescription = '%s%s' % (self.mDescription, desc)\r
+\r
+ def __str__(self):\r
+ return '\n'.join(self.mText)\r
+\r
+ def Generate(self):\r
+ """This interface need to be override"""\r
+\r
+class Section(BaseDoxygeItem):\r
+ def Generate(self):\r
+ """This interface need to be override"""\r
+ if len(self.mTag) != 0:\r
+ self.mText.append(' \section %s %s' % (self.mName, self.mTag))\r
+ else:\r
+ self.mText.append(' \section %s' % self.mName)\r
+\r
+ self.mText.append(self.mDescription)\r
+ return self.mText\r
+\r
+class Page(BaseDoxygeItem):\r
+ def __init__(self, name, tag=None, isSort=True):\r
+ BaseDoxygeItem.__init__(self, name, tag)\r
+ self.mSubPages = []\r
+ self.mIsMainPage = False\r
+ self.mSections = []\r
+ self.mIsSort = isSort\r
+\r
+ def GetSubpageCount(self):\r
+ return len(self.mSubPages)\r
+\r
+ def AddPage(self, subpage):\r
+ self.mSubPages.append(subpage)\r
+ return subpage\r
+\r
+ def AddPages(self, pageArray):\r
+ if pageArray == None:\r
+ return\r
+ for page in pageArray:\r
+ self.AddPage(page)\r
+\r
+ def AddSection(self, section):\r
+ self.mSections.append(section)\r
+ self.mSections.sort(cmp=lambda x,y: cmp(x.mName.lower(), y.mName.lower()))\r
+\r
+ def Generate(self):\r
+ if self.mIsMainPage:\r
+ self.mText.append('/** \mainpage %s' % self.mName)\r
+ self.mIsSort = False\r
+ else:\r
+ self.mText.append('/** \page %s %s' % (self.mTag, self.mName))\r
+\r
+ if len(self.mDescription) != 0:\r
+ self.mText.append(self.mDescription)\r
+ endIndex = len(self.mText)\r
+\r
+ self.mSections.sort()\r
+ for sect in self.mSections:\r
+ self.mText += sect.Generate()\r
+\r
+ endIndex = len(self.mText)\r
+\r
+ if len(self.mSubPages) != 0:\r
+ self.mText.insert(endIndex, "<p> \section content_index INDEX")\r
+ endIndex = len(self.mText)\r
+ self.mText.insert(endIndex, '<ul>')\r
+ endIndex += 1\r
+ if self.mIsSort:\r
+ self.mSubPages.sort(cmp=lambda x,y: cmp(x.mName.lower(), y.mName.lower()))\r
+ for page in self.mSubPages:\r
+ self.mText.insert(endIndex, '<li>\subpage %s \"%s\" </li>' % (page.mTag, page.mName))\r
+ endIndex += 1\r
+ self.mText += page.Generate()\r
+ self.mText.insert(endIndex, '</ul>')\r
+ endIndex += 1\r
+ self.mText.insert(endIndex, ' **/')\r
+ return self.mText\r
+\r
+class DoxygenFile(Page):\r
+ def __init__(self, name, file):\r
+ Page.__init__(self, name)\r
+ self.mFilename = file\r
+ self.mIsMainPage = True\r
+\r
+ def GetFilename(self):\r
+ return self.mFilename.replace('/', '\\')\r
+\r
+ def Save(self):\r
+ str = self.Generate()\r
+ try:\r
+ f = open(self.mFilename, 'w')\r
+ f.write('\n'.join(str))\r
+ f.close()\r
+ except IOError, e:\r
+ ErrorMsg ('Fail to write file %s' % self.mFilename)\r
+ return False\r
+\r
+ return True\r
+\r
+doxygenConfigTemplate = """\r
+DOXYFILE_ENCODING = UTF-8\r
+PROJECT_NAME = %(ProjectName)s\r
+PROJECT_NUMBER = %(ProjectVersion)s\r
+OUTPUT_DIRECTORY = %(OutputDir)s\r
+CREATE_SUBDIRS = YES\r
+OUTPUT_LANGUAGE = English\r
+BRIEF_MEMBER_DESC = YES\r
+REPEAT_BRIEF = YES\r
+ABBREVIATE_BRIEF = "The $name class " \\\r
+ "The $name widget " \\\r
+ "The $name file " \\\r
+ is \\\r
+ provides \\\r
+ specifies \\\r
+ contains \\\r
+ represents \\\r
+ a \\\r
+ an \\\r
+ the\r
+ALWAYS_DETAILED_SEC = NO\r
+INLINE_INHERITED_MEMB = NO\r
+FULL_PATH_NAMES = YES\r
+STRIP_FROM_PATH = %(StripPath)s\r
+STRIP_FROM_INC_PATH =\r
+SHORT_NAMES = YES\r
+JAVADOC_AUTOBRIEF = NO\r
+QT_AUTOBRIEF = NO\r
+MULTILINE_CPP_IS_BRIEF = NO\r
+DETAILS_AT_TOP = YES\r
+INHERIT_DOCS = YES\r
+SEPARATE_MEMBER_PAGES = NO\r
+TAB_SIZE = 1\r
+ALIASES =\r
+OPTIMIZE_OUTPUT_FOR_C = YES\r
+OPTIMIZE_OUTPUT_JAVA = NO\r
+BUILTIN_STL_SUPPORT = NO\r
+CPP_CLI_SUPPORT = NO\r
+SIP_SUPPORT = NO\r
+DISTRIBUTE_GROUP_DOC = YES\r
+SUBGROUPING = YES\r
+TYPEDEF_HIDES_STRUCT = NO\r
+\r
+EXTRACT_ALL = YES\r
+EXTRACT_PRIVATE = NO\r
+EXTRACT_STATIC = NO\r
+EXTRACT_LOCAL_CLASSES = NO\r
+EXTRACT_LOCAL_METHODS = NO\r
+EXTRACT_ANON_NSPACES = NO\r
+HIDE_UNDOC_MEMBERS = NO\r
+HIDE_UNDOC_CLASSES = NO\r
+HIDE_FRIEND_COMPOUNDS = NO\r
+HIDE_IN_BODY_DOCS = NO\r
+INTERNAL_DOCS = NO\r
+CASE_SENSE_NAMES = NO\r
+HIDE_SCOPE_NAMES = NO\r
+SHOW_INCLUDE_FILES = NO\r
+INLINE_INFO = YES\r
+SORT_MEMBER_DOCS = YES\r
+SORT_BRIEF_DOCS = NO\r
+SORT_BY_SCOPE_NAME = YES\r
+GENERATE_TODOLIST = YES\r
+GENERATE_TESTLIST = YES\r
+GENERATE_BUGLIST = YES\r
+GENERATE_DEPRECATEDLIST= YES\r
+ENABLED_SECTIONS =\r
+MAX_INITIALIZER_LINES = 30\r
+SHOW_USED_FILES = NO\r
+SHOW_DIRECTORIES = NO\r
+FILE_VERSION_FILTER =\r
+\r
+QUIET = NO\r
+WARNINGS = YES\r
+WARN_IF_UNDOCUMENTED = YES\r
+WARN_IF_DOC_ERROR = YES\r
+WARN_NO_PARAMDOC = YES\r
+WARN_FORMAT = "$file:$line: $text "\r
+WARN_LOGFILE = %(WarningFile)s\r
+\r
+INPUT = %(FileList)s\r
+INPUT_ENCODING = UTF-8\r
+FILE_PATTERNS = %(Pattern)s\r
+RECURSIVE = NO\r
+EXCLUDE = *.svn\r
+EXCLUDE_SYMLINKS = NO\r
+EXCLUDE_PATTERNS = .svn\r
+EXCLUDE_SYMBOLS =\r
+EXAMPLE_PATH = %(ExamplePath)s\r
+EXAMPLE_PATTERNS = *\r
+EXAMPLE_RECURSIVE = NO\r
+IMAGE_PATH =\r
+INPUT_FILTER =\r
+FILTER_PATTERNS =\r
+FILTER_SOURCE_FILES = NO\r
+\r
+SOURCE_BROWSER = NO\r
+INLINE_SOURCES = NO\r
+STRIP_CODE_COMMENTS = YES\r
+REFERENCED_BY_RELATION = YES\r
+REFERENCES_RELATION = YES\r
+REFERENCES_LINK_SOURCE = NO\r
+USE_HTAGS = NO\r
+VERBATIM_HEADERS = NO\r
+\r
+ALPHABETICAL_INDEX = NO\r
+COLS_IN_ALPHA_INDEX = 5\r
+IGNORE_PREFIX =\r
+\r
+GENERATE_HTML = YES\r
+HTML_OUTPUT = html\r
+HTML_FILE_EXTENSION = .html\r
+HTML_HEADER =\r
+HTML_FOOTER =\r
+HTML_STYLESHEET =\r
+HTML_ALIGN_MEMBERS = YES\r
+GENERATE_HTMLHELP = %(WhetherGenerateHtmlHelp)s\r
+HTML_DYNAMIC_SECTIONS = NO\r
+CHM_FILE = index.chm\r
+HHC_LOCATION =\r
+GENERATE_CHI = NO\r
+BINARY_TOC = NO\r
+TOC_EXPAND = NO\r
+DISABLE_INDEX = NO\r
+ENUM_VALUES_PER_LINE = 4\r
+GENERATE_TREEVIEW = %(WhetherGenerateTreeView)s\r
+TREEVIEW_WIDTH = 250\r
+\r
+GENERATE_LATEX = NO\r
+LATEX_OUTPUT = latex\r
+LATEX_CMD_NAME = latex\r
+MAKEINDEX_CMD_NAME = makeindex\r
+COMPACT_LATEX = NO\r
+PAPER_TYPE = a4wide\r
+EXTRA_PACKAGES =\r
+LATEX_HEADER =\r
+PDF_HYPERLINKS = YES\r
+USE_PDFLATEX = YES\r
+LATEX_BATCHMODE = NO\r
+LATEX_HIDE_INDICES = NO\r
+\r
+GENERATE_RTF = NO\r
+RTF_OUTPUT = rtf\r
+COMPACT_RTF = NO\r
+RTF_HYPERLINKS = NO\r
+RTF_STYLESHEET_FILE =\r
+RTF_EXTENSIONS_FILE =\r
+\r
+GENERATE_MAN = NO\r
+MAN_OUTPUT = man\r
+MAN_EXTENSION = .3\r
+MAN_LINKS = NO\r
+\r
+GENERATE_XML = NO\r
+XML_OUTPUT = xml\r
+XML_SCHEMA =\r
+XML_DTD =\r
+XML_PROGRAMLISTING = YES\r
+\r
+GENERATE_AUTOGEN_DEF = NO\r
+\r
+GENERATE_PERLMOD = NO\r
+PERLMOD_LATEX = NO\r
+PERLMOD_PRETTY = YES\r
+PERLMOD_MAKEVAR_PREFIX =\r
+\r
+ENABLE_PREPROCESSING = YES\r
+MACRO_EXPANSION = YES\r
+EXPAND_ONLY_PREDEF = YES\r
+SEARCH_INCLUDES = YES\r
+INCLUDE_PATH = %(IncludePath)s\r
+INCLUDE_FILE_PATTERNS = *.h\r
+PREDEFINED = %(PreDefined)s\r
+EXPAND_AS_DEFINED =\r
+SKIP_FUNCTION_MACROS = NO\r
+\r
+TAGFILES =\r
+GENERATE_TAGFILE =\r
+ALLEXTERNALS = NO\r
+EXTERNAL_GROUPS = YES\r
+PERL_PATH = /usr/bin/perl\r
+\r
+CLASS_DIAGRAMS = NO\r
+MSCGEN_PATH =\r
+HIDE_UNDOC_RELATIONS = YES\r
+HAVE_DOT = NO\r
+CLASS_GRAPH = YES\r
+COLLABORATION_GRAPH = YES\r
+GROUP_GRAPHS = YES\r
+UML_LOOK = NO\r
+TEMPLATE_RELATIONS = NO\r
+INCLUDE_GRAPH = YES\r
+INCLUDED_BY_GRAPH = YES\r
+CALL_GRAPH = NO\r
+CALLER_GRAPH = NO\r
+GRAPHICAL_HIERARCHY = YES\r
+DIRECTORY_GRAPH = YES\r
+DOT_IMAGE_FORMAT = png\r
+DOT_PATH =\r
+DOTFILE_DIRS =\r
+DOT_GRAPH_MAX_NODES = 50\r
+MAX_DOT_GRAPH_DEPTH = 1000\r
+DOT_TRANSPARENT = YES\r
+DOT_MULTI_TARGETS = NO\r
+GENERATE_LEGEND = YES\r
+DOT_CLEANUP = YES\r
+\r
+SEARCHENGINE = NO\r
+\r
+"""\r
+class DoxygenConfigFile:\r
+ def __init__(self):\r
+ self.mProjectName = ''\r
+ self.mOutputDir = ''\r
+ self.mFileList = []\r
+ self.mIncludeList = []\r
+ self.mStripPath = ''\r
+ self.mExamplePath = ''\r
+ self.mPattern = ['*.c', '*.h',\r
+ '*.asm', '*.s', '.nasm', '*.html', '*.dox']\r
+ self.mMode = 'HTML'\r
+ self.mWarningFile = ''\r
+ self.mPreDefined = []\r
+ self.mProjectVersion = 0.1\r
+\r
+ def SetChmMode(self):\r
+ self.mMode = 'CHM'\r
+\r
+ def SetHtmlMode(self):\r
+ self.mMode = 'HTML'\r
+\r
+ def SetProjectName(self, str):\r
+ self.mProjectName = str\r
+\r
+ def SetProjectVersion(self, str):\r
+ self.mProjectVersion = str\r
+\r
+ def SetOutputDir(self, str):\r
+ self.mOutputDir = str\r
+\r
+ def SetStripPath(self, str):\r
+ self.mStripPath = str\r
+\r
+ def SetExamplePath(self, str):\r
+ self.mExamplePath = str\r
+\r
+ def SetWarningFilePath(self, str):\r
+ self.mWarningFile = str.replace('\\', '/')\r
+\r
+ def FileExists(self, path):\r
+ if path == None:\r
+ return False\r
+ if len(path) == 0:\r
+ return False\r
+\r
+ for p in self.mFileList:\r
+ if path.lower() == p.lower():\r
+ return True\r
+\r
+ return False\r
+\r
+ def AddFile(self, path):\r
+ if path == None:\r
+ return\r
+\r
+ if len(path) == 0:\r
+ return\r
+ path = path.replace('\\', '/')\r
+ if not self.FileExists(path):\r
+ self.mFileList.append(path)\r
+\r
+ def AddIncludePath(self, path):\r
+ path = path.replace('\\', '/')\r
+ if path not in self.mIncludeList:\r
+ self.mIncludeList.append(path)\r
+\r
+ def AddPattern(self, pattern):\r
+ self.mPattern.append(pattern)\r
+\r
+ def AddPreDefined(self, macro):\r
+ self.mPreDefined.append(macro)\r
+\r
+ def Generate(self, path):\r
+ files = ' \\\n'.join(self.mFileList)\r
+ includes = ' \\\n'.join(self.mIncludeList)\r
+ patterns = ' \\\n'.join(self.mPattern)\r
+ if self.mMode.lower() == 'html':\r
+ sHtmlHelp = 'NO'\r
+ sTreeView = 'YES'\r
+ else:\r
+ sHtmlHelp = 'YES'\r
+ sTreeView = 'NO'\r
+\r
+ text = doxygenConfigTemplate % {'ProjectName':self.mProjectName,\r
+ 'OutputDir':self.mOutputDir,\r
+ 'StripPath':self.mStripPath,\r
+ 'ExamplePath':self.mExamplePath,\r
+ 'FileList':files,\r
+ 'Pattern':patterns,\r
+ 'WhetherGenerateHtmlHelp':sHtmlHelp,\r
+ 'WhetherGenerateTreeView':sTreeView,\r
+ 'IncludePath':includes,\r
+ 'WarningFile':self.mWarningFile,\r
+ 'PreDefined':' '.join(self.mPreDefined),\r
+ 'ProjectVersion':self.mProjectVersion}\r
+ try:\r
+ f = open(path, 'w')\r
+ f.write(text)\r
+ f.close()\r
+ except IOError, e:\r
+ ErrorMsg ('Fail to generate doxygen config file %s' % path)\r
+ return False\r
+\r
+ return True\r
+\r
+########################################################################\r
+# TEST CODE\r
+########################################################################\r
+if __name__== '__main__':\r
+ df = DoxygenFile('Platform Document', 'm:\tree')\r
+ df.AddPage(Page('Module', 'module'))\r
+ p = df.AddPage(Page('Library', 'library'))\r
+ p.AddDescription(desc)\r
+ p.AddPage(Page('PCD', 'pcds'))\r
+\r
+ df.Generate()\r
+ print df\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+import array\r
+import uuid\r
+import re\r
+import os\r
+import logging\r
+import core.pe as pe\r
+\r
+def GetLogger():\r
+ return logging.getLogger('EFI Binary File')\r
+\r
+class EFIBinaryError(Exception):\r
+ def __init__(self, message):\r
+ Exception.__init__(self)\r
+ self._message = message\r
+\r
+ def GetMessage(self):\r
+ return self._message\r
+\r
+class EfiFd(object):\r
+ EFI_FV_HEADER_SIZE = 0x48\r
+\r
+ def __init__(self):\r
+ self._fvs = []\r
+\r
+ def Load(self, fd, size):\r
+ index = fd.tell()\r
+ while (index + self.EFI_FV_HEADER_SIZE < size):\r
+ fv = EfiFv(self)\r
+ fv.Load(fd)\r
+ self._fvs.append(fv)\r
+ index += fv.GetHeader().GetFvLength()\r
+ index = align(index, 8)\r
+ fd.seek(index)\r
+\r
+ def GetFvs(self):\r
+ return self._fvs\r
+\r
+class EfiFv(object):\r
+ FILE_SYSTEM_GUID = uuid.UUID('{8c8ce578-8a3d-4f1c-9935-896185c32dd3}')\r
+\r
+ def __init__(self, parent=None):\r
+ self._size = 0\r
+ self._filename = None\r
+ self._fvheader = None\r
+ self._blockentries = []\r
+ self._ffs = []\r
+\r
+ # following field is for FV in FD\r
+ self._parent = parent\r
+ self._offset = 0\r
+ self._raw = array.array('B')\r
+\r
+ def Load(self, fd):\r
+ self._offset = fd.tell()\r
+ self._filename = fd.name\r
+\r
+ # get file header\r
+ self._fvheader = EfiFirmwareVolumeHeader.Read(fd)\r
+ #self._fvheader.Dump()\r
+\r
+ self._size = self._fvheader.GetFvLength()\r
+\r
+ if self._fvheader.GetFileSystemGuid() != self.FILE_SYSTEM_GUID:\r
+ fd.seek(self._offset)\r
+ self._raw.fromfile(fd, self.GetHeader().GetFvLength())\r
+ return\r
+\r
+ # read block map\r
+ blockentry = BlockMapEntry.Read(fd)\r
+ self._blockentries.append(blockentry)\r
+ while (blockentry.GetNumberBlocks() != 0 and blockentry.GetLength() != 0):\r
+ self._blockentries.append(blockentry)\r
+ blockentry = BlockMapEntry.Read(fd)\r
+\r
+\r
+ if self._fvheader.GetSize() + (len(self._blockentries)) * 8 != \\r
+ self._fvheader.GetHeaderLength():\r
+ raise EFIBinaryError("Volume Header length not consistent with block map!")\r
+\r
+ index = align(fd.tell(), 8)\r
+ count = 0\r
+ while ((index + EfiFfs.FFS_HEADER_SIZE) < self._size):\r
+ ffs = EfiFfs.Read(fd, self)\r
+ if not isValidGuid(ffs.GetNameGuid()):\r
+ break\r
+ self._ffs.append(ffs)\r
+ count += 1\r
+ index = align(fd.tell(), 8)\r
+\r
+ fd.seek(self._offset)\r
+ self._raw.fromfile(fd, self.GetHeader().GetFvLength())\r
+\r
+ def GetFfs(self):\r
+ return self._ffs\r
+\r
+ def GetHeader(self):\r
+ return self._fvheader\r
+\r
+ def GetBlockEntries(self):\r
+ return self._blockentries\r
+\r
+ def GetHeaderRawData(self):\r
+ ret = []\r
+ ret += self._fvheader.GetRawData()\r
+ for block in self._blockentries:\r
+ ret += block.GetRawData()\r
+ return ret\r
+\r
+ def GetOffset(self):\r
+ return 0\r
+\r
+ def GetRawData(self):\r
+ return self._raw.tolist()\r
+\r
+class BinaryItem(object):\r
+ def __init__(self, parent=None):\r
+ self._size = 0\r
+ self._arr = array.array('B')\r
+ self._parent = parent\r
+\r
+ @classmethod\r
+ def Read(cls, fd, parent=None):\r
+ item = cls(parent)\r
+ item.fromfile(fd)\r
+ return item\r
+\r
+ def Load(self, fd):\r
+ self.fromfile(fd)\r
+\r
+ def GetSize(self):\r
+ """should be implemented by inherited class"""\r
+\r
+ def fromfile(self, fd):\r
+ self._arr.fromfile(fd, self.GetSize())\r
+\r
+ def GetParent(self):\r
+ return self._parent\r
+\r
+class EfiFirmwareVolumeHeader(BinaryItem):\r
+ def GetSize(self):\r
+ return 56\r
+\r
+ def GetSigunature(self):\r
+ list = self._arr.tolist()\r
+ sig = ''\r
+ for x in list[40:44]:\r
+ sig += chr(x)\r
+ return sig\r
+\r
+ def GetAttribute(self):\r
+ return list2int(self._arr.tolist()[44:48])\r
+\r
+ def GetErasePolarity(self):\r
+ list = self.GetAttrStrings()\r
+ if 'EFI_FVB2_ERASE_POLARITY' in list:\r
+ return True\r
+ return False\r
+\r
+ def GetAttrStrings(self):\r
+ list = []\r
+ value = self.GetAttribute()\r
+ if (value & 0x01) != 0:\r
+ list.append('EFI_FVB2_READ_DISABLED_CAP')\r
+ if (value & 0x02) != 0:\r
+ list.append('EFI_FVB2_READ_ENABLED_CAP')\r
+ if (value & 0x04) != 0:\r
+ list.append('EFI_FVB2_READ_STATUS')\r
+ if (value & 0x08) != 0:\r
+ list.append('EFI_FVB2_WRITE_DISABLED_CAP')\r
+ if (value & 0x10) != 0:\r
+ list.append('EFI_FVB2_WRITE_ENABLED_CAP')\r
+ if (value & 0x20) != 0:\r
+ list.append('EFI_FVB2_WRITE_STATUS')\r
+ if (value & 0x40) != 0:\r
+ list.append('EFI_FVB2_LOCK_CAP')\r
+ if (value & 0x80) != 0:\r
+ list.append('EFI_FVB2_LOCK_STATUS')\r
+ if (value & 0x200) != 0:\r
+ list.append('EFI_FVB2_STICKY_WRITE')\r
+ if (value & 0x400) != 0:\r
+ list.append('EFI_FVB2_MEMORY_MAPPED')\r
+ if (value & 0x800) != 0:\r
+ list.append('EFI_FVB2_ERASE_POLARITY')\r
+ if (value & 0x1000) != 0:\r
+ list.append('EFI_FVB2_READ_LOCK_CAP')\r
+ if (value & 0x00002000) != 0:\r
+ list.append('EFI_FVB2_READ_LOCK_STATUS')\r
+ if (value & 0x00004000) != 0:\r
+ list.append('EFI_FVB2_WRITE_LOCK_CAP')\r
+ if (value & 0x00008000) != 0:\r
+ list.append('EFI_FVB2_WRITE_LOCK_STATUS')\r
+\r
+ if (value == 0):\r
+ list.append('EFI_FVB2_ALIGNMENT_1')\r
+ if (value & 0x001F0000) == 0x00010000:\r
+ list.append('EFI_FVB2_ALIGNMENT_2')\r
+ if (value & 0x001F0000) == 0x00020000:\r
+ list.append('EFI_FVB2_ALIGNMENT_4')\r
+ if (value & 0x001F0000) == 0x00030000:\r
+ list.append('EFI_FVB2_ALIGNMENT_8')\r
+ if (value & 0x001F0000) == 0x00040000:\r
+ list.append('EFI_FVB2_ALIGNMENT_16')\r
+ if (value & 0x001F0000) == 0x00050000:\r
+ list.append('EFI_FVB2_ALIGNMENT_32')\r
+ if (value & 0x001F0000) == 0x00060000:\r
+ list.append('EFI_FVB2_ALIGNMENT_64')\r
+ if (value & 0x001F0000) == 0x00070000:\r
+ list.append('EFI_FVB2_ALIGNMENT_128')\r
+ if (value & 0x001F0000) == 0x00080000:\r
+ list.append('EFI_FVB2_ALIGNMENT_256')\r
+ if (value & 0x001F0000) == 0x00090000:\r
+ list.append('EFI_FVB2_ALIGNMENT_512')\r
+ if (value & 0x001F0000) == 0x000A0000:\r
+ list.append('EFI_FVB2_ALIGNMENT_1K')\r
+ if (value & 0x001F0000) == 0x000B0000:\r
+ list.append('EFI_FVB2_ALIGNMENT_2K')\r
+ if (value & 0x001F0000) == 0x000C0000:\r
+ list.append('EFI_FVB2_ALIGNMENT_4K')\r
+ if (value & 0x001F0000) == 0x000D0000:\r
+ list.append('EFI_FVB2_ALIGNMENT_8K')\r
+ if (value & 0x001F0000) == 0x000E0000:\r
+ list.append('EFI_FVB2_ALIGNMENT_16K')\r
+ if (value & 0x001F0000) == 0x000F0000:\r
+ list.append('EFI_FVB2_ALIGNMENT_32K')\r
+ if (value & 0x001F0000) == 0x00100000:\r
+ list.append('EFI_FVB2_ALIGNMENT_64K')\r
+ if (value & 0x001F0000) == 0x00110000:\r
+ list.append('EFI_FVB2_ALIGNMENT_128K')\r
+ if (value & 0x001F0000) == 0x00120000:\r
+ list.append('EFI_FVB2_ALIGNMENT_256K')\r
+ if (value & 0x001F0000) == 0x00130000:\r
+ list.append('EFI_FVB2_ALIGNMENT_512K')\r
+\r
+ return list\r
+\r
+ def GetHeaderLength(self):\r
+ return list2int(self._arr.tolist()[48:50])\r
+\r
+ def Dump(self):\r
+ print 'Signature: %s' % self.GetSigunature()\r
+ print 'Attribute: 0x%X' % self.GetAttribute()\r
+ print 'Header Length: 0x%X' % self.GetHeaderLength()\r
+ print 'File system Guid: ', self.GetFileSystemGuid()\r
+ print 'Revision: 0x%X' % self.GetRevision()\r
+ print 'FvLength: 0x%X' % self.GetFvLength()\r
+\r
+ def GetFileSystemGuid(self):\r
+ list = self._arr.tolist()\r
+ return list2guid(list[16:32])\r
+\r
+ def GetRevision(self):\r
+ list = self._arr.tolist()\r
+ return int(list[55])\r
+\r
+ def GetFvLength(self):\r
+ list = self._arr.tolist()\r
+ return list2int(list[32:40])\r
+\r
+ def GetRawData(self):\r
+ return self._arr.tolist()\r
+\r
+class BlockMapEntry(BinaryItem):\r
+ def GetSize(self):\r
+ return 8\r
+\r
+ def GetNumberBlocks(self):\r
+ list = self._arr.tolist()\r
+ return list2int(list[0:4])\r
+\r
+ def GetLength(self):\r
+ list = self._arr.tolist()\r
+ return list2int(list[4:8])\r
+\r
+ def GetRawData(self):\r
+ return self._arr.tolist()\r
+\r
+ def __str__(self):\r
+ return '[BlockEntry] Number = 0x%X, length=0x%X' % (self.GetNumberBlocks(), self.GetLength())\r
+\r
+class EfiFfs(object):\r
+ FFS_HEADER_SIZE = 24\r
+\r
+ def __init__(self, parent=None):\r
+ self._header = None\r
+\r
+ # following field is for FFS in FV file.\r
+ self._parent = parent\r
+ self._offset = 0\r
+ self._sections = []\r
+\r
+ def Load(self, fd):\r
+ self._offset = align(fd.tell(), 8)\r
+\r
+ self._header = EfiFfsHeader.Read(fd, self)\r
+\r
+ if not isValidGuid(self.GetNameGuid()):\r
+ return\r
+\r
+ index = self._offset\r
+ fileend = self._offset + self.GetSize()\r
+ while (index + EfiSection.EFI_SECTION_HEADER_SIZE < fileend):\r
+ section = EfiSection(self)\r
+ section.Load(fd)\r
+ if section.GetSize() == 0 and section.GetHeader().GetType() == 0:\r
+ break\r
+ self._sections.append(section)\r
+ index = fd.tell()\r
+\r
+ # rebase file pointer to next ffs file\r
+ index = self._offset + self._header.GetFfsSize()\r
+ index = align(index, 8)\r
+ fd.seek(index)\r
+\r
+ def GetOffset(self):\r
+ return self._offset\r
+\r
+ def GetSize(self):\r
+ return self._header.GetFfsSize()\r
+\r
+ @classmethod\r
+ def Read(cls, fd, parent=None):\r
+ item = cls(parent)\r
+ item.Load(fd)\r
+ return item\r
+\r
+ def GetNameGuid(self):\r
+ return self._header.GetNameGuid()\r
+\r
+ def DumpContent(self):\r
+ list = self._content.tolist()\r
+ line = []\r
+ count = 0\r
+ for item in list:\r
+ if count < 32:\r
+ line.append('0x%X' % int(item))\r
+ count += 1\r
+ else:\r
+ print ' '.join(line)\r
+ count = 0\r
+ line = []\r
+ line.append('0x%X' % int(item))\r
+ count += 1\r
+\r
+ def GetHeader(self):\r
+ return self._header\r
+\r
+ def GetParent(self):\r
+ return self._parent\r
+\r
+ def GetSections(self):\r
+ return self._sections\r
+\r
+class EfiFfsHeader(BinaryItem):\r
+ ffs_state_map = {0x01:'EFI_FILE_HEADER_CONSTRUCTION',\r
+ 0x02:'EFI_FILE_HEADER_VALID',\r
+ 0x04:'EFI_FILE_DATA_VALID',\r
+ 0x08:'EFI_FILE_MARKED_FOR_UPDATE',\r
+ 0x10:'EFI_FILE_DELETED',\r
+ 0x20:'EFI_FILE_HEADER_INVALID'}\r
+\r
+ def GetSize(self):\r
+ return 24\r
+\r
+ def GetNameGuid(self):\r
+ list = self._arr.tolist()\r
+ return list2guid(list[0:16])\r
+\r
+ def GetType(self):\r
+ list = self._arr.tolist()\r
+ return int(list[18])\r
+\r
+\r
+ def GetTypeString(self):\r
+ value = self.GetType()\r
+ if value == 0x01:\r
+ return 'EFI_FV_FILETYPE_RAW'\r
+ if value == 0x02:\r
+ return 'EFI_FV_FILETYPE_FREEFORM'\r
+ if value == 0x03:\r
+ return 'EFI_FV_FILETYPE_SECURITY_CORE'\r
+ if value == 0x04:\r
+ return 'EFI_FV_FILETYPE_PEI_CORE'\r
+ if value == 0x05:\r
+ return 'EFI_FV_FILETYPE_DXE_CORE'\r
+ if value == 0x06:\r
+ return 'EFI_FV_FILETYPE_PEIM'\r
+ if value == 0x07:\r
+ return 'EFI_FV_FILETYPE_DRIVER'\r
+ if value == 0x08:\r
+ return 'EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER'\r
+ if value == 0x09:\r
+ return 'EFI_FV_FILETYPE_APPLICATION'\r
+ if value == 0x0B:\r
+ return 'EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE'\r
+ if value == 0xc0:\r
+ return 'EFI_FV_FILETYPE_OEM_MIN'\r
+ if value == 0xdf:\r
+ return 'EFI_FV_FILETYPE_OEM_MAX'\r
+ if value == 0xe0:\r
+ return 'EFI_FV_FILETYPE_DEBUG_MIN'\r
+ if value == 0xef:\r
+ return 'EFI_FV_FILETYPE_DEBUG_MAX'\r
+ if value == 0xf0:\r
+ return 'EFI_FV_FILETYPE_FFS_PAD'\r
+ if value == 0xff:\r
+ return 'EFI_FV_FILETYPE_FFS_MAX'\r
+ return 'Unknown FFS Type'\r
+\r
+ def GetAttributes(self):\r
+ list = self._arr.tolist()\r
+ return int(list[19])\r
+\r
+ def GetFfsSize(self):\r
+ list = self._arr.tolist()\r
+ return list2int(list[20:23])\r
+\r
+ def GetState(self):\r
+ list = self._arr.tolist()\r
+ state = int(list[23])\r
+ polarity = self.GetParent().GetParent().GetHeader().GetErasePolarity()\r
+ if polarity:\r
+ state = (~state) & 0xFF\r
+ HighestBit = 0x80\r
+ while (HighestBit != 0) and (HighestBit & state) == 0:\r
+ HighestBit = HighestBit >> 1\r
+ return HighestBit\r
+\r
+ def GetStateString(self):\r
+ state = self.GetState()\r
+ if state in self.ffs_state_map.keys():\r
+ return self.ffs_state_map[state]\r
+ return 'Unknown Ffs State'\r
+\r
+ def Dump(self):\r
+ print "FFS name: ", self.GetNameGuid()\r
+ print "FFS type: ", self.GetType()\r
+ print "FFS attr: 0x%X" % self.GetAttributes()\r
+ print "FFS size: 0x%X" % self.GetFfsSize()\r
+ print "FFS state: 0x%X" % self.GetState()\r
+\r
+ def GetRawData(self):\r
+ return self._arr.tolist()\r
+\r
+\r
+class EfiSection(object):\r
+ EFI_SECTION_HEADER_SIZE = 4\r
+\r
+ def __init__(self, parent=None):\r
+ self._size = 0\r
+ self._parent = parent\r
+ self._offset = 0\r
+ self._contents = array.array('B')\r
+\r
+ def Load(self, fd):\r
+ self._offset = align(fd.tell(), 4)\r
+\r
+ self._header = EfiSectionHeader.Read(fd, self)\r
+\r
+ if self._header.GetTypeString() == "EFI_SECTION_PE32":\r
+ pefile = pe.PEFile(self)\r
+ pefile.Load(fd, self.GetContentSize())\r
+\r
+ fd.seek(self._offset)\r
+ self._contents.fromfile(fd, self.GetContentSize())\r
+\r
+ # rebase file pointer to next section\r
+ index = self._offset + self.GetSize()\r
+ index = align(index, 4)\r
+ fd.seek(index)\r
+\r
+ def GetContentSize(self):\r
+ return self.GetSize() - self.EFI_SECTION_HEADER_SIZE\r
+\r
+ def GetContent(self):\r
+ return self._contents.tolist()\r
+\r
+ def GetSize(self):\r
+ return self._header.GetSectionSize()\r
+\r
+ def GetHeader(self):\r
+ return self._header\r
+\r
+ def GetSectionOffset(self):\r
+ return self._offset + self.EFI_SECTION_HEADER_SIZE\r
+\r
+class EfiSectionHeader(BinaryItem):\r
+ section_type_map = {0x01: 'EFI_SECTION_COMPRESSION',\r
+ 0x02: 'EFI_SECTION_GUID_DEFINED',\r
+ 0x10: 'EFI_SECTION_PE32',\r
+ 0x11: 'EFI_SECTION_PIC',\r
+ 0x12: 'EFI_SECTION_TE',\r
+ 0x13: 'EFI_SECTION_DXE_DEPEX',\r
+ 0x14: 'EFI_SECTION_VERSION',\r
+ 0x15: 'EFI_SECTION_USER_INTERFACE',\r
+ 0x16: 'EFI_SECTION_COMPATIBILITY16',\r
+ 0x17: 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE',\r
+ 0x18: 'EFI_SECTION_FREEFORM_SUBTYPE_GUID',\r
+ 0x19: 'EFI_SECTION_RAW',\r
+ 0x1B: 'EFI_SECTION_PEI_DEPEX'}\r
+ def GetSize(self):\r
+ return 4\r
+\r
+ def GetSectionSize(self):\r
+ list = self._arr.tolist()\r
+ return list2int(list[0:3])\r
+\r
+ def GetType(self):\r
+ list = self._arr.tolist()\r
+ return int(list[3])\r
+\r
+ def GetTypeString(self):\r
+ type = self.GetType()\r
+ if type not in self.section_type_map.keys():\r
+ return 'Unknown Section Type'\r
+ return self.section_type_map[type]\r
+\r
+ def Dump(self):\r
+ print 'size = 0x%X' % self.GetSectionSize()\r
+ print 'type = 0x%X' % self.GetType()\r
+\r
+\r
+\r
+rMapEntry = re.compile('^(\w+)[ \(\w\)]* \(BaseAddress=([0-9a-fA-F]+), EntryPoint=([0-9a-fA-F]+), GUID=([0-9a-fA-F\-]+)')\r
+class EfiFvMapFile(object):\r
+ def __init__(self):\r
+ self._mapentries = {}\r
+\r
+ def Load(self, path):\r
+ if not os.path.exists(path):\r
+ return False\r
+\r
+ try:\r
+ file = open(path, 'r')\r
+ lines = file.readlines()\r
+ file.close()\r
+ except:\r
+ return False\r
+\r
+ for line in lines:\r
+ if line[0] != ' ':\r
+ # new entry\r
+ ret = rMapEntry.match(line)\r
+ if ret != None:\r
+ name = ret.groups()[0]\r
+ baseaddr = int(ret.groups()[1], 16)\r
+ entry = int(ret.groups()[2], 16)\r
+ guidstr = '{' + ret.groups()[3] + '}'\r
+ guid = uuid.UUID(guidstr)\r
+ self._mapentries[guid] = EfiFvMapFileEntry(name, baseaddr, entry, guid)\r
+ return True\r
+\r
+ def GetEntry(self, guid):\r
+ if guid in self._mapentries.keys():\r
+ return self._mapentries[guid]\r
+ return None\r
+\r
+class EfiFvMapFileEntry(object):\r
+ def __init__(self, name, baseaddr, entry, guid):\r
+ self._name = name\r
+ self._baseaddr = baseaddr\r
+ self._entry = entry\r
+ self._guid = guid\r
+\r
+ def GetName(self):\r
+ return self._name\r
+\r
+ def GetBaseAddress(self):\r
+ return self._baseaddr\r
+\r
+ def GetEntryPoint(self):\r
+ return self._entry\r
+\r
+def list2guid(list):\r
+ val1 = list2int(list[0:4])\r
+ val2 = list2int(list[4:6])\r
+ val3 = list2int(list[6:8])\r
+ val4 = 0\r
+ for item in list[8:16]:\r
+ val4 = (val4 << 8) | int(item)\r
+\r
+ val = val1 << 12 * 8 | val2 << 10 * 8 | val3 << 8 * 8 | val4\r
+ guid = uuid.UUID(int=val)\r
+ return guid\r
+\r
+def list2int(list):\r
+ val = 0\r
+ for index in range(len(list) - 1, -1, -1):\r
+ val = (val << 8) | int(list[index])\r
+ return val\r
+\r
+def align(value, alignment):\r
+ return (value + ((alignment - value) & (alignment - 1)))\r
+\r
+gInvalidGuid = uuid.UUID(int=0xffffffffffffffffffffffffffffffff)\r
+def isValidGuid(guid):\r
+ if guid == gInvalidGuid:\r
+ return False\r
+ return True\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+from message import *\r
+import re\r
+import os\r
+\r
+section_re = re.compile(r'^\[([\w., "]+)\]')\r
+\r
+class BaseINIFile(object):\r
+ _objs = {}\r
+ def __new__(cls, *args, **kwargs):\r
+ """Maintain only a single instance of this object\r
+ @return: instance of this class\r
+\r
+ """\r
+ if len(args) == 0: return object.__new__(cls, *args, **kwargs)\r
+ filename = args[0]\r
+ parent = None\r
+ if len(args) > 1:\r
+ parent = args[1]\r
+\r
+ key = os.path.normpath(filename)\r
+ if key not in cls._objs.keys():\r
+ cls._objs[key] = object.__new__(cls, *args, **kwargs)\r
+\r
+ if parent != None:\r
+ cls._objs[key].AddParent(parent)\r
+\r
+ return cls._objs[key]\r
+\r
+ def __init__(self, filename=None, parent=None):\r
+ self._lines = []\r
+ self._sections = {}\r
+ self._filename = filename\r
+ self._globals = []\r
+ self._isModify = True\r
+\r
+ def AddParent(self, parent):\r
+ if parent == None: return\r
+ if not hasattr(self, "_parents"):\r
+ self._parents = []\r
+\r
+ if parent in self._parents:\r
+ ErrorMsg("Duplicate parent is found for INI file %s" % self._filename)\r
+ return\r
+ self._parents.append(parent)\r
+\r
+ def GetFilename(self):\r
+ return os.path.normpath(self._filename)\r
+\r
+ def IsModified(self):\r
+ return self._isModify\r
+\r
+ def Modify(self, modify=True, obj=None):\r
+ if modify == self._isModify: return\r
+ self._isModify = modify\r
+ if modify:\r
+ for parent in self._parents:\r
+ parent.Modify(True, self)\r
+\r
+ def _ReadLines(self, filename):\r
+ #\r
+ # try to open file\r
+ #\r
+ if not os.path.exists(filename):\r
+ return False\r
+\r
+ try:\r
+ handle = open(filename, 'r')\r
+ self._lines = handle.readlines()\r
+ handle.close()\r
+ except:\r
+ raise EdkException("Fail to open file %s" % filename)\r
+\r
+ return True\r
+\r
+ def GetSectionInstance(self, parent, name, isCombined=False):\r
+ return BaseINISection(parent, name, isCombined)\r
+\r
+ def GetSectionByName(self, name):\r
+ arr = []\r
+ for key in self._sections.keys():\r
+ if '.private' in key:\r
+ continue\r
+ for item in self._sections[key]:\r
+ if item.GetBaseName().lower().find(name.lower()) != -1:\r
+ arr.append(item)\r
+ return arr\r
+\r
+ def GetSectionObjectsByName(self, name):\r
+ arr = []\r
+ sects = self.GetSectionByName(name)\r
+ for sect in sects:\r
+ for obj in sect.GetObjects():\r
+ arr.append(obj)\r
+ return arr\r
+\r
+ def Parse(self):\r
+ if not self._isModify: return True\r
+ if not self._ReadLines(self._filename): return False\r
+\r
+ sObjs = []\r
+ inGlobal = True\r
+ # process line\r
+ for index in range(len(self._lines)):\r
+ templine = self._lines[index].strip()\r
+ # skip comments\r
+ if len(templine) == 0: continue\r
+ if re.match("^\[=*\]", templine) or re.match("^#", templine) or \\r
+ re.match("\*+/", templine):\r
+ continue\r
+\r
+ m = section_re.match(templine)\r
+ if m!= None: # found a section\r
+ inGlobal = False\r
+ # Finish the latest section first\r
+ if len(sObjs) != 0:\r
+ for sObj in sObjs:\r
+ sObj._end = index - 1\r
+ if not sObj.Parse():\r
+ ErrorMsg("Fail to parse section %s" % sObj.GetBaseName(),\r
+ self._filename,\r
+ sObj._start)\r
+\r
+ # start new section\r
+ sname_arr = m.groups()[0].split(',')\r
+ sObjs = []\r
+ for name in sname_arr:\r
+ sObj = self.GetSectionInstance(self, name, (len(sname_arr) > 1))\r
+ sObj._start = index\r
+ sObjs.append(sObj)\r
+ if not self._sections.has_key(name.lower()):\r
+ self._sections[name.lower()] = [sObj]\r
+ else:\r
+ self._sections[name.lower()].append(sObj)\r
+ elif inGlobal: # not start any section and find global object\r
+ gObj = BaseINIGlobalObject(self)\r
+ gObj._start = index\r
+ gObj.Parse()\r
+ self._globals.append(gObj)\r
+\r
+ # Finish the last section\r
+ if len(sObjs) != 0:\r
+ for sObj in sObjs:\r
+ sObj._end = index\r
+ if not sObj.Parse():\r
+ ErrorMsg("Fail to parse section %s" % sObj.GetBaseName(),\r
+ self._filename,\r
+ sObj._start)\r
+\r
+ self._isModify = False\r
+ return True\r
+\r
+ def Destroy(self, parent):\r
+\r
+ # check referenced parent\r
+ if parent != None:\r
+ assert parent in self._parents, "when destory ini object, can not found parent reference!"\r
+ self._parents.remove(parent)\r
+\r
+ if len(self._parents) != 0: return\r
+\r
+ for sects in self._sections.values():\r
+ for sect in sects:\r
+ sect.Destroy()\r
+\r
+ # dereference from _objs array\r
+ assert self.GetFilename() in self._objs.keys(), "When destroy ini object, can not find obj reference!"\r
+ assert self in self._objs.values(), "When destroy ini object, can not find obj reference!"\r
+ del self._objs[self.GetFilename()]\r
+\r
+ # dereference self\r
+ self.Clear()\r
+\r
+ def GetDefine(self, name):\r
+ sects = self.GetSectionByName('Defines')\r
+ for sect in sects:\r
+ for obj in sect.GetObjects():\r
+ line = obj.GetLineByOffset(obj._start).split('#')[0].strip()\r
+ arr = line.split('=')\r
+ if arr[0].strip().lower() == name.strip().lower():\r
+ return arr[1].strip()\r
+ return None\r
+\r
+ def Clear(self):\r
+ for sects in self._sections.values():\r
+ for sect in sects:\r
+ del sect\r
+ self._sections.clear()\r
+ for gObj in self._globals:\r
+ del gObj\r
+\r
+ del self._globals[:]\r
+ del self._lines[:]\r
+\r
+ def Reload(self):\r
+ self.Clear()\r
+ ret = self.Parse()\r
+ if ret:\r
+ self._isModify = False\r
+ return ret\r
+\r
+ def AddNewSection(self, sectName):\r
+ if sectName.lower() in self._sections.keys():\r
+ ErrorMsg('Section %s can not be created for conflict with existing section')\r
+ return None\r
+\r
+ sectionObj = self.GetSectionInstance(self, sectName)\r
+ sectionObj._start = len(self._lines)\r
+ sectionObj._end = len(self._lines) + 1\r
+ self._lines.append('[%s]\n' % sectName)\r
+ self._lines.append('\n\n')\r
+ self._sections[sectName.lower()] = sectionObj\r
+ return sectionObj\r
+\r
+ def CopySectionsByName(self, oldDscObj, nameStr):\r
+ sects = oldDscObj.GetSectionByName(nameStr)\r
+ for sect in sects:\r
+ sectObj = self.AddNewSection(sect.GetName())\r
+ sectObj.Copy(sect)\r
+\r
+ def __str__(self):\r
+ return ''.join(self._lines)\r
+\r
+ ## Get file header's comment from basic INI file.\r
+ # The file comments has two style:\r
+ # 1) #/** @file\r
+ # 2) ## @file\r
+ #\r
+ def GetFileHeader(self):\r
+ desc = []\r
+ lineArr = self._lines\r
+ inHeader = False\r
+ for num in range(len(self._lines)):\r
+ line = lineArr[num].strip()\r
+ if not inHeader and (line.startswith("#/**") or line.startswith("##")) and \\r
+ line.find("@file") != -1:\r
+ inHeader = True\r
+ continue\r
+ if inHeader and (line.startswith("#**/") or line.startswith('##')):\r
+ inHeader = False\r
+ break\r
+ if inHeader:\r
+ prefixIndex = line.find('#')\r
+ if prefixIndex == -1:\r
+ desc.append(line)\r
+ else:\r
+ desc.append(line[prefixIndex + 1:])\r
+ return '<br>\n'.join(desc)\r
+\r
+class BaseINISection(object):\r
+ def __init__(self, parent, name, isCombined=False):\r
+ self._parent = parent\r
+ self._name = name\r
+ self._isCombined = isCombined\r
+ self._start = 0\r
+ self._end = 0\r
+ self._objs = []\r
+\r
+ def __del__(self):\r
+ for obj in self._objs:\r
+ del obj\r
+ del self._objs[:]\r
+\r
+ def GetName(self):\r
+ return self._name\r
+\r
+ def GetObjects(self):\r
+ return self._objs\r
+\r
+ def GetParent(self):\r
+ return self._parent\r
+\r
+ def GetStartLinenumber(self):\r
+ return self._start\r
+\r
+ def GetEndLinenumber(self):\r
+ return self._end\r
+\r
+ def GetLine(self, linenumber):\r
+ return self._parent._lines[linenumber]\r
+\r
+ def GetFilename(self):\r
+ return self._parent.GetFilename()\r
+\r
+ def GetSectionINIObject(self, parent):\r
+ return BaseINISectionObject(parent)\r
+\r
+ def Parse(self):\r
+ # skip first line in section, it is used by section name\r
+ visit = self._start + 1\r
+ iniObj = None\r
+ while (visit <= self._end):\r
+ line = self.GetLine(visit).strip()\r
+ if re.match("^\[=*\]", line) or re.match("^#", line) or len(line) == 0:\r
+ visit += 1\r
+ continue\r
+ line = line.split('#')[0].strip()\r
+ if iniObj != None:\r
+ if line.endswith('}'):\r
+ iniObj._end = visit - self._start\r
+ if not iniObj.Parse():\r
+ ErrorMsg("Fail to parse ini object",\r
+ self.GetFilename(),\r
+ iniObj.GetStartLinenumber())\r
+ else:\r
+ self._objs.append(iniObj)\r
+ iniObj = None\r
+ else:\r
+ iniObj = self.GetSectionINIObject(self)\r
+ iniObj._start = visit - self._start\r
+ if not line.endswith('{'):\r
+ iniObj._end = visit - self._start\r
+ if not iniObj.Parse():\r
+ ErrorMsg("Fail to parse ini object",\r
+ self.GetFilename(),\r
+ iniObj.GetStartLinenumber())\r
+ else:\r
+ self._objs.append(iniObj)\r
+ iniObj = None\r
+ visit += 1\r
+ return True\r
+\r
+ def Destroy(self):\r
+ for obj in self._objs:\r
+ obj.Destroy()\r
+\r
+ def GetBaseName(self):\r
+ return self._name\r
+\r
+ def AddLine(self, line):\r
+ end = self.GetEndLinenumber()\r
+ self._parent._lines.insert(end, line)\r
+ self._end += 1\r
+\r
+ def Copy(self, sectObj):\r
+ index = sectObj.GetStartLinenumber() + 1\r
+ while index < sectObj.GetEndLinenumber():\r
+ line = sectObj.GetLine(index)\r
+ if not line.strip().startswith('#'):\r
+ self.AddLine(line)\r
+ index += 1\r
+\r
+ def AddObject(self, obj):\r
+ lines = obj.GenerateLines()\r
+ for line in lines:\r
+ self.AddLine(line)\r
+\r
+ def GetComment(self):\r
+ comments = []\r
+ start = self._start - 1\r
+ bFound = False\r
+\r
+ while (start > 0):\r
+ line = self.GetLine(start).strip()\r
+ if len(line) == 0:\r
+ start -= 1\r
+ continue\r
+ if line.startswith('##'):\r
+ bFound = True\r
+ index = line.rfind('#')\r
+ if (index + 1) < len(line):\r
+ comments.append(line[index + 1:])\r
+ break\r
+ if line.startswith('#'):\r
+ start -= 1\r
+ continue\r
+ break\r
+ if bFound:\r
+ end = start + 1\r
+ while (end < self._start):\r
+ line = self.GetLine(end).strip()\r
+ if len(line) == 0: break\r
+ if not line.startswith('#'): break\r
+ index = line.rfind('#')\r
+ if (index + 1) < len(line):\r
+ comments.append(line[index + 1:])\r
+ end += 1\r
+ return comments\r
+\r
+class BaseINIGlobalObject(object):\r
+ def __init__(self, parent):\r
+ self._start = 0\r
+ self._end = 0\r
+\r
+ def Parse(self):\r
+ return True\r
+\r
+ def __str__(self):\r
+ return parent._lines[self._start]\r
+\r
+ def __del__(self):\r
+ pass\r
+\r
+class BaseINISectionObject(object):\r
+ def __init__(self, parent):\r
+ self._start = 0\r
+ self._end = 0\r
+ self._parent = parent\r
+\r
+ def __del__(self):\r
+ self._parent = None\r
+\r
+ def GetParent(self):\r
+ return self._parent\r
+\r
+ def GetFilename(self):\r
+ return self.GetParent().GetFilename()\r
+\r
+ def GetPackageName(self):\r
+ return self.GetFilename()\r
+\r
+ def GetFileObj(self):\r
+ return self.GetParent().GetParent()\r
+\r
+ def GetStartLinenumber(self):\r
+ return self.GetParent()._start + self._start\r
+\r
+ def GetLineByOffset(self, offset):\r
+ sect_start = self._parent.GetStartLinenumber()\r
+ linenumber = sect_start + offset\r
+ return self._parent.GetLine(linenumber)\r
+\r
+ def GetLinenumberByOffset(self, offset):\r
+ return offset + self._parent.GetStartLinenumber()\r
+\r
+ def Parse(self):\r
+ return True\r
+\r
+ def Destroy(self):\r
+ pass\r
+\r
+ def __str__(self):\r
+ return self.GetLineByOffset(self._start).strip()\r
+\r
+ def GenerateLines(self):\r
+ return ['default setion object string\n']\r
+\r
+ def GetComment(self):\r
+ comments = []\r
+ start = self.GetStartLinenumber() - 1\r
+ bFound = False\r
+\r
+ while (start > 0):\r
+ line = self.GetParent().GetLine(start).strip()\r
+ if len(line) == 0:\r
+ start -= 1\r
+ continue\r
+ if line.startswith('##'):\r
+ bFound = True\r
+ index = line.rfind('#')\r
+ if (index + 1) < len(line):\r
+ comments.append(line[index + 1:])\r
+ break\r
+ if line.startswith('#'):\r
+ start -= 1\r
+ continue\r
+ break\r
+ if bFound:\r
+ end = start + 1\r
+ while (end <= self.GetStartLinenumber() - 1):\r
+ line = self.GetParent().GetLine(end).strip()\r
+ if len(line) == 0: break\r
+ if not line.startswith('#'): break\r
+ index = line.rfind('#')\r
+ if (index + 1) < len(line):\r
+ comments.append(line[index + 1:])\r
+ end += 1\r
+ return comments\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+import core.editor\r
+\r
+class INIDoc(core.editor.EditorDocument):\r
+ def __init__(self):\r
+ core.editor.EditorDocument.__init__(self)\r
+ self._iniobj = None\r
+\r
+\r
+class INIView(core.editor.EditorView):\r
+ pass\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+def GetEdkLogger():\r
+ import logging\r
+ return logging.getLogger('edk')\r
+\r
+class EdkException(Exception):\r
+ def __init__(self, message, fName=None, fNo=None):\r
+ self._message = message\r
+ ErrorMsg(message, fName, fNo)\r
+\r
+ def GetMessage(self):\r
+ return '[EDK Failure]: %s' %self._message\r
+\r
+def ErrorMsg(mess, fName=None, fNo=None):\r
+ GetEdkLogger().error(NormalMessage('#ERR#', mess, fName, fNo))\r
+\r
+def LogMsg(mess, fName=None, fNo=None):\r
+ GetEdkLogger().info(NormalMessage('@LOG@', mess, fName, fNo))\r
+\r
+def WarnMsg(mess, fName=None, fNo=None):\r
+ GetEdkLogger().warning(NormalMessage('!WAR!', mess, fName, fNo))\r
+\r
+def NormalMessage(type, mess, fName=None, fNo=None):\r
+ strMsg = type\r
+\r
+ if fName != None:\r
+ strMsg += ' %s' % fName.replace('/', '\\')\r
+ if fNo != None:\r
+ strMsg += '(%d):' % fNo\r
+ else:\r
+ strMsg += ' :'\r
+\r
+ if fName == None and fNo == None:\r
+ strMsg += ' '\r
+ strMsg += mess\r
+\r
+ return strMsg\r
+\r
+\r
+\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+import plugins.EdkPlugins.basemodel.ini as ini\r
+import plugins.EdkPlugins.edk2.model.dsc as dsc\r
+import plugins.EdkPlugins.edk2.model.inf as inf\r
+import plugins.EdkPlugins.edk2.model.dec as dec\r
+import os\r
+from plugins.EdkPlugins.basemodel.message import *\r
+\r
+class SurfaceObject(object):\r
+ _objs = {}\r
+\r
+ def __new__(cls, *args, **kwargs):\r
+ """Maintain only a single instance of this object\r
+ @return: instance of this class\r
+\r
+ """\r
+ obj = object.__new__(cls, *args, **kwargs)\r
+ if not cls._objs.has_key("None"):\r
+ cls._objs["None"] = []\r
+ cls._objs["None"].append(obj)\r
+\r
+ return obj\r
+\r
+ def __init__(self, parent, workspace):\r
+ self._parent = parent\r
+ self._fileObj = None\r
+ self._workspace = workspace\r
+ self._isModify = False\r
+ self._modifiedObjs = []\r
+\r
+ def __del__(self):\r
+ pass\r
+\r
+ def Destroy(self):\r
+ key = self.GetRelativeFilename()\r
+ self.GetFileObj().Destroy(self)\r
+ del self._fileObj\r
+ # dereference self from _objs arrary\r
+ assert self._objs.has_key(key), "when destory, object is not in obj list"\r
+ assert self in self._objs[key], "when destory, object is not in obj list"\r
+ self._objs[key].remove(self)\r
+ if len(self._objs[key]) == 0:\r
+ del self._objs[key]\r
+\r
+ def GetParent(self):\r
+ return self._parent\r
+\r
+ def GetWorkspace(self):\r
+ return self._workspace\r
+\r
+ def GetFileObjectClass(self):\r
+ return ini.BaseINIFile\r
+\r
+ def GetFilename(self):\r
+ return self.GetFileObj().GetFilename()\r
+\r
+ def GetFileObj(self):\r
+ return self._fileObj\r
+\r
+ def GetRelativeFilename(self):\r
+ fullPath = self.GetFilename()\r
+ return fullPath[len(self._workspace) + 1:]\r
+\r
+ def Load(self, relativePath):\r
+ # if has been loaded, directly return\r
+ if self._fileObj != None: return True\r
+\r
+ relativePath = os.path.normpath(relativePath)\r
+ fullPath = os.path.join(self._workspace, relativePath)\r
+ fullPath = os.path.normpath(fullPath)\r
+\r
+ if not os.path.exists(fullPath):\r
+ ErrorMsg("file does not exist!", fullPath)\r
+ return False\r
+\r
+ self._fileObj = self.GetFileObjectClass()(fullPath, self)\r
+\r
+ if not self._fileObj.Parse():\r
+ ErrorMsg("Fail to parse file!", fullPath)\r
+ return False\r
+\r
+ # remove self from None list to list with filename as key\r
+ cls = self.__class__\r
+ if self not in cls._objs["None"]:\r
+ ErrorMsg("Sufrace object does not be create into None list")\r
+ cls._objs["None"].remove(self)\r
+ if not cls._objs.has_key(relativePath):\r
+ cls._objs[relativePath] = []\r
+ cls._objs[relativePath].append(self)\r
+\r
+ return True\r
+\r
+ def Reload(self, force=False):\r
+ ret = True\r
+ # whether require must be update\r
+ if force:\r
+ ret = self.GetFileObj().Reload(True)\r
+ else:\r
+ if self.IsModified():\r
+ if self.GetFileObj().IsModified():\r
+ ret = self.GetFileObj().Reload()\r
+ return ret\r
+\r
+ def Modify(self, modify=True, modifiedObj=None):\r
+ if modify:\r
+ #LogMsg("%s is modified, modified object is %s" % (self.GetFilename(), modifiedObj))\r
+ if issubclass(modifiedObj.__class__, ini.BaseINIFile) and self._isModify:\r
+ return\r
+ self._isModify = modify\r
+ self.GetParent().Modify(modify, self)\r
+ else:\r
+ self._isModify = modify\r
+\r
+ def IsModified(self):\r
+ return self._isModify\r
+\r
+ def GetModifiedObjs(self):\r
+ return self._modifiedObjs\r
+\r
+ def FilterObjsByArch(self, objs, arch):\r
+ arr = []\r
+ for obj in objs:\r
+ if obj.GetArch().lower() == 'common':\r
+ arr.append(obj)\r
+ continue\r
+ if obj.GetArch().lower() == arch.lower():\r
+ arr.append(obj)\r
+ continue\r
+ return arr\r
+\r
+class Platform(SurfaceObject):\r
+ def __init__(self, parent, workspace):\r
+ SurfaceObject.__init__(self, parent, workspace)\r
+ self._modules = []\r
+ self._packages = []\r
+\r
+ def Destroy(self):\r
+ for module in self._modules:\r
+ module.Destroy()\r
+ del self._modules[:]\r
+\r
+ del self._packages[:]\r
+ SurfaceObject.Destroy(self)\r
+\r
+ def GetName(self):\r
+ return self.GetFileObj().GetDefine("PLATFORM_NAME")\r
+\r
+ def GetFileObjectClass(self):\r
+ return dsc.DSCFile\r
+\r
+ def GetModuleCount(self):\r
+ if self.GetFileObj() == None:\r
+ ErrorMsg("Fail to get module count because DSC file has not been load!")\r
+\r
+ return len(self.GetFileObj().GetComponents())\r
+\r
+ def GetSupportArchs(self):\r
+ return self.GetFileObj().GetDefine("SUPPORTED_ARCHITECTURES").strip().split('#')[0].split('|')\r
+\r
+ def LoadModules(self, precallback=None, postcallback=None):\r
+ for obj in self.GetFileObj().GetComponents():\r
+ mFilename = obj.GetFilename()\r
+ if precallback != None:\r
+ precallback(self, mFilename)\r
+ arch = obj.GetArch()\r
+ if arch.lower() == 'common':\r
+ archarr = self.GetSupportArchs()\r
+ else:\r
+ archarr = [arch]\r
+ for arch in archarr:\r
+ module = Module(self, self.GetWorkspace())\r
+ if module.Load(mFilename, arch, obj.GetOveridePcds(), obj.GetOverideLibs()):\r
+ self._modules.append(module)\r
+ if postcallback != None:\r
+ postcallback(self, module)\r
+ else:\r
+ del module\r
+ ErrorMsg("Fail to load module %s" % mFilename)\r
+\r
+ def GetModules(self):\r
+ return self._modules\r
+\r
+ def GetLibraryPath(self, classname, arch, type):\r
+ objs = self.GetFileObj().GetSectionObjectsByName("libraryclasses")\r
+\r
+ for obj in objs:\r
+ if classname.lower() != obj.GetClass().lower():\r
+ continue\r
+ if obj.GetArch().lower() != 'common' and \\r
+ obj.GetArch().lower() != arch.lower():\r
+ continue\r
+\r
+ if obj.GetModuleType().lower() != 'common' and \\r
+ obj.GetModuleType().lower() != type.lower():\r
+ continue\r
+\r
+ return obj.GetInstance()\r
+\r
+ ErrorMsg("Fail to get library class %s [%s][%s] from platform %s" % (classname, arch, type, self.GetFilename()))\r
+ return None\r
+\r
+ def GetPackage(self, path):\r
+ package = self.GetParent().GetPackage(path)\r
+ if package not in self._packages:\r
+ self._packages.append(package)\r
+ return package\r
+\r
+ def GetPcdBuildObjs(self, name, arch=None):\r
+ arr = []\r
+ objs = self.GetFileObj().GetSectionObjectsByName('pcds')\r
+ for obj in objs:\r
+ if obj.GetPcdName().lower() == name.lower():\r
+ arr.append(obj)\r
+ if arch != None:\r
+ arr = self.FilterObjsByArch(arr, arch)\r
+ return arr\r
+\r
+ def Reload(self, callback=None):\r
+ # do not care force paramter for platform object\r
+ isFileChanged = self.GetFileObj().IsModified()\r
+ ret = SurfaceObject.Reload(self, False)\r
+ if not ret: return False\r
+ if isFileChanged:\r
+ # destroy all modules and reload them again\r
+ for obj in self._modules:\r
+ obj.Destroy()\r
+ del self._modules[:]\r
+ del self._packages[:]\r
+ self.LoadModules(callback)\r
+ else:\r
+ for obj in self._modules:\r
+ callback(self, obj.GetFilename())\r
+ obj.Reload()\r
+\r
+ self.Modify(False)\r
+ return True\r
+\r
+ def Modify(self, modify=True, modifiedObj=None):\r
+ if modify:\r
+ #LogMsg("%s is modified, modified object is %s" % (self.GetFilename(), modifiedObj))\r
+ if issubclass(modifiedObj.__class__, ini.BaseINIFile) and self._isModify:\r
+ return\r
+ self._isModify = modify\r
+ self.GetParent().Modify(modify, self)\r
+ else:\r
+ if self.GetFileObj().IsModified():\r
+ return\r
+ for obj in self._modules:\r
+ if obj.IsModified():\r
+ return\r
+\r
+ self._isModify = modify\r
+ self.GetParent().Modify(modify, self)\r
+\r
+ def GetModuleObject(self, relativePath, arch):\r
+ path = os.path.normpath(relativePath)\r
+ for obj in self._modules:\r
+ if obj.GetRelativeFilename() == path:\r
+ if arch.lower() == 'common':\r
+ return obj\r
+ if obj.GetArch() == arch:\r
+ return obj\r
+ return None\r
+\r
+ def GenerateFullReferenceDsc(self):\r
+ oldDsc = self.GetFileObj()\r
+ newDsc = dsc.DSCFile()\r
+ newDsc.CopySectionsByName(oldDsc, 'defines')\r
+ newDsc.CopySectionsByName(oldDsc, 'SkuIds')\r
+\r
+ #\r
+ # Dynamic common section should also be copied\r
+ #\r
+ newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicDefault')\r
+ newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicHii')\r
+ newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicVpd')\r
+ newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicEx')\r
+\r
+ sects = oldDsc.GetSectionByName('Components')\r
+ for oldSect in sects:\r
+ newSect = newDsc.AddNewSection(oldSect.GetName())\r
+ for oldComObj in oldSect.GetObjects():\r
+ module = self.GetModuleObject(oldComObj.GetFilename(), oldSect.GetArch())\r
+ if module == None: continue\r
+\r
+ newComObj = dsc.DSCComponentObject(newSect)\r
+ newComObj.SetFilename(oldComObj.GetFilename())\r
+\r
+ # add all library instance for override section\r
+ libdict = module.GetLibraries()\r
+ for libclass in libdict.keys():\r
+ if libdict[libclass] != None:\r
+ newComObj.AddOverideLib(libclass, libdict[libclass].GetRelativeFilename().replace('\\', '/'))\r
+\r
+ # add all pcds for override section\r
+ pcddict = module.GetPcds()\r
+ for pcd in pcddict.values():\r
+ buildPcd = pcd.GetBuildObj()\r
+ buildType = buildPcd.GetPcdType()\r
+ buildValue = None\r
+ if buildType.lower() == 'pcdsdynamichii' or \\r
+ buildType.lower() == 'pcdsdynamicvpd' or \\r
+ buildType.lower() == 'pcdsdynamicdefault':\r
+ buildType = 'PcdsDynamic'\r
+ if buildType != 'PcdsDynamic':\r
+ buildValue = buildPcd.GetPcdValue()\r
+ newComObj.AddOveridePcd(buildPcd.GetPcdName(),\r
+ buildType,\r
+ buildValue)\r
+ newSect.AddObject(newComObj)\r
+ return newDsc\r
+\r
+class Module(SurfaceObject):\r
+ def __init__(self, parent, workspace):\r
+ SurfaceObject.__init__(self, parent, workspace)\r
+ self._arch = 'common'\r
+ self._parent = parent\r
+ self._overidePcds = {}\r
+ self._overideLibs = {}\r
+ self._libs = {}\r
+ self._pcds = {}\r
+ self._ppis = []\r
+ self._protocols = []\r
+ self._depexs = []\r
+ self._guids = []\r
+ self._packages = []\r
+\r
+ def Destroy(self):\r
+ for lib in self._libs.values():\r
+ if lib != None:\r
+ lib.Destroy()\r
+ self._libs.clear()\r
+\r
+ for pcd in self._pcds.values():\r
+ pcd.Destroy()\r
+ self._pcds.clear()\r
+\r
+ for ppi in self._ppis:\r
+ ppi.DeRef(self)\r
+ del self._ppis[:]\r
+\r
+ for protocol in self._protocols:\r
+ if protocol != None:\r
+ protocol.DeRef(self)\r
+ del self._protocols[:]\r
+\r
+ for guid in self._guids:\r
+ if guid != None:\r
+ guid.DeRef(self)\r
+ del self._guids[:]\r
+\r
+ del self._packages[:]\r
+ del self._depexs[:]\r
+ SurfaceObject.Destroy(self)\r
+\r
+ def GetFileObjectClass(self):\r
+ return inf.INFFile\r
+\r
+ def GetLibraries(self):\r
+ return self._libs\r
+\r
+ def Load(self, filename, arch='common', overidePcds=None, overideLibs=None):\r
+ if not SurfaceObject.Load(self, filename):\r
+ return False\r
+\r
+ self._arch = arch\r
+ if overidePcds != None:\r
+ self._overideLibs = overideLibs\r
+ if overideLibs != None:\r
+ self._overidePcds = overidePcds\r
+\r
+ self._SearchLibraries()\r
+ self._SearchPackage()\r
+ self._SearchSurfaceItems()\r
+ return True\r
+\r
+ def GetArch(self):\r
+ return self._arch\r
+\r
+ def GetModuleName(self):\r
+ return self.GetFileObj().GetDefine("BASE_NAME")\r
+\r
+ def GetModuleType(self):\r
+ return self.GetFileObj().GetDefine("MODULE_TYPE")\r
+\r
+ def GetPlatform(self):\r
+ return self.GetParent()\r
+\r
+ def GetModuleObj(self):\r
+ return self\r
+\r
+ def GetPcds(self):\r
+ pcds = self._pcds.copy()\r
+ for lib in self._libs.values():\r
+ if lib == None: continue\r
+ for name in lib._pcds.keys():\r
+ pcds[name] = lib._pcds[name]\r
+ return pcds\r
+\r
+ def GetPpis(self):\r
+ ppis = []\r
+ ppis += self._ppis\r
+ for lib in self._libs.values():\r
+ if lib == None: continue\r
+ ppis += lib._ppis\r
+ return ppis\r
+\r
+ def GetProtocols(self):\r
+ pros = []\r
+ pros = self._protocols\r
+ for lib in self._libs.values():\r
+ if lib == None: continue\r
+ pros += lib._protocols\r
+ return pros\r
+\r
+ def GetGuids(self):\r
+ guids = []\r
+ guids += self._guids\r
+ for lib in self._libs.values():\r
+ if lib == None: continue\r
+ guids += lib._guids\r
+ return guids\r
+\r
+ def GetDepexs(self):\r
+ deps = []\r
+ deps += self._depexs\r
+ for lib in self._libs.values():\r
+ if lib == None: continue\r
+ deps += lib._depexs\r
+ return deps\r
+\r
+ def IsLibrary(self):\r
+ return self.GetFileObj().GetDefine("LIBRARY_CLASS") != None\r
+\r
+ def GetLibraryInstance(self, classname, arch, type):\r
+ if classname not in self._libs.keys():\r
+ # find in overide lib firstly\r
+ if classname in self._overideLibs.keys():\r
+ self._libs[classname] = Library(self, self.GetWorkspace())\r
+ self._libs[classname].Load(self._overideLibs[classname])\r
+ return self._libs[classname]\r
+\r
+ parent = self.GetParent()\r
+ if issubclass(parent.__class__, Platform):\r
+ path = parent.GetLibraryPath(classname, arch, type)\r
+ if path == None:\r
+ ErrorMsg('Fail to get library instance for %s' % classname, self.GetFilename())\r
+ return None\r
+ self._libs[classname] = Library(self, self.GetWorkspace())\r
+ if not self._libs[classname].Load(path, self.GetArch()):\r
+ self._libs[classname] = None\r
+ else:\r
+ self._libs[classname] = parent.GetLibraryInstance(classname, arch, type)\r
+ return self._libs[classname]\r
+\r
+ def GetSourceObjs(self):\r
+ return self.GetFileObj().GetSectionObjectsByName('source')\r
+\r
+ def _SearchLibraries(self):\r
+ objs = self.GetFileObj().GetSectionObjectsByName('libraryclasses')\r
+ arch = self.GetArch()\r
+ type = self.GetModuleType()\r
+ for obj in objs:\r
+ if obj.GetArch().lower() != 'common' and \\r
+ obj.GetArch().lower() not in self.GetPlatform().GetSupportArchs():\r
+ continue\r
+ classname = obj.GetClass()\r
+ instance = self.GetLibraryInstance(classname, arch, type)\r
+ if not self.IsLibrary() and instance != None:\r
+ instance._isInherit = False\r
+\r
+ if classname not in self._libs.keys():\r
+ self._libs[classname] = instance\r
+\r
+ def _SearchSurfaceItems(self):\r
+ # get surface item from self's inf\r
+ pcds = []\r
+ ppis = []\r
+ pros = []\r
+ deps = []\r
+ guids = []\r
+ if self.GetFileObj() != None:\r
+ pcds = self.FilterObjsByArch(self.GetFileObj().GetSectionObjectsByName('pcd'),\r
+ self.GetArch())\r
+ for pcd in pcds:\r
+ if pcd.GetPcdName() not in self._pcds.keys():\r
+ pcdItem = PcdItem(pcd.GetPcdName(), self, pcd)\r
+ self._pcds[pcd.GetPcdName()] = ModulePcd(self,\r
+ pcd.GetPcdName(),\r
+ pcd,\r
+ pcdItem)\r
+\r
+ ppis += self.FilterObjsByArch(self.GetFileObj().GetSectionObjectsByName('ppis'),\r
+ self.GetArch())\r
+\r
+ for ppi in ppis:\r
+ item = PpiItem(ppi.GetName(), self, ppi)\r
+ if item not in self._ppis:\r
+ self._ppis.append(item)\r
+\r
+ pros += self.FilterObjsByArch(self.GetFileObj().GetSectionObjectsByName('protocols'),\r
+ self.GetArch())\r
+\r
+ for pro in pros:\r
+ item = ProtocolItem(pro.GetName(), self, pro)\r
+ if item not in self._protocols:\r
+ self._protocols.append(item)\r
+\r
+ deps += self.FilterObjsByArch(self.GetFileObj().GetSectionObjectsByName('depex'),\r
+ self.GetArch())\r
+ for dep in deps:\r
+ item = DepexItem(self, dep)\r
+ self._depexs.append(item)\r
+\r
+ guids += self.FilterObjsByArch(self.GetFileObj().GetSectionObjectsByName('guids'),\r
+ self.GetArch())\r
+ for guid in guids:\r
+ item = GuidItem(guid.GetName(), self, guid)\r
+ if item not in self._guids:\r
+ self._guids.append(item)\r
+\r
+ def _SearchPackage(self):\r
+ objs = self.GetFileObj().GetSectionObjectsByName('packages')\r
+ for obj in objs:\r
+ package = self.GetPlatform().GetPackage(obj.GetPath())\r
+ if package != None:\r
+ self._packages.append(package)\r
+\r
+ def GetPackages(self):\r
+ return self._packages\r
+\r
+ def GetPcdObjects(self):\r
+ if self.GetFileObj() == None:\r
+ return []\r
+\r
+ return self.GetFileObj().GetSectionObjectsByName('pcd')\r
+\r
+ def GetLibraryClassHeaderFilePath(self):\r
+ lcname = self.GetFileObj().GetProduceLibraryClass()\r
+ if lcname == None: return None\r
+\r
+ pkgs = self.GetPackages()\r
+ for package in pkgs:\r
+ path = package.GetLibraryClassHeaderPathByName(lcname)\r
+ if path != None:\r
+ return os.path.realpath(os.path.join(package.GetFileObj().GetPackageRootPath(), path))\r
+ return None\r
+\r
+ def Reload(self, force=False, callback=None):\r
+ if callback != None:\r
+ callback(self, "Starting reload...")\r
+\r
+ ret = SurfaceObject.Reload(self, force)\r
+ if not ret: return False\r
+\r
+ if not force and not self.IsModified():\r
+ return True\r
+\r
+ for lib in self._libs.values():\r
+ if lib != None:\r
+ lib.Destroy()\r
+ self._libs.clear()\r
+\r
+ for pcd in self._pcds.values():\r
+ pcd.Destroy()\r
+ self._pcds.clear()\r
+\r
+ for ppi in self._ppis:\r
+ ppi.DeRef(self)\r
+ del self._ppis[:]\r
+\r
+ for protocol in self._protocols:\r
+ protocol.DeRef(self)\r
+ del self._protocols[:]\r
+\r
+ for guid in self._guids:\r
+ guid.DeRef(self)\r
+ del self._guids[:]\r
+\r
+ del self._packages[:]\r
+ del self._depexs[:]\r
+\r
+ if callback != None:\r
+ callback(self, "Searching libraries...")\r
+ self._SearchLibraries()\r
+ if callback != None:\r
+ callback(self, "Searching packages...")\r
+ self._SearchPackage()\r
+ if callback != None:\r
+ callback(self, "Searching surface items...")\r
+ self._SearchSurfaceItems()\r
+\r
+ self.Modify(False)\r
+ return True\r
+\r
+ def Modify(self, modify=True, modifiedObj=None):\r
+ if modify:\r
+ #LogMsg("%s is modified, modified object is %s" % (self.GetFilename(), modifiedObj))\r
+ if issubclass(modifiedObj.__class__, ini.BaseINIFile) and self._isModify:\r
+ return\r
+ self._isModify = modify\r
+ self.GetParent().Modify(modify, self)\r
+ else:\r
+ if self.GetFileObj().IsModified():\r
+ return\r
+\r
+ self._isModify = modify\r
+ self.GetParent().Modify(modify, self)\r
+\r
+class Library(Module):\r
+ def __init__(self, parent, workspace):\r
+ Module.__init__(self, parent, workspace)\r
+ self._isInherit = True\r
+\r
+ def IsInherit(self):\r
+ return self._isInherit\r
+\r
+ def GetModuleType(self):\r
+ return self.GetParent().GetModuleType()\r
+\r
+ def GetPlatform(self):\r
+ return self.GetParent().GetParent()\r
+\r
+ def GetModuleObj(self):\r
+ return self.GetParent()\r
+\r
+ def GetArch(self):\r
+ return self.GetParent().GetArch()\r
+\r
+ def Destroy(self):\r
+ self._libs.clear()\r
+ self._pcds.clear()\r
+ SurfaceObject.Destroy(self)\r
+\r
+class Package(SurfaceObject):\r
+ def __init__(self, parent, workspace):\r
+ SurfaceObject.__init__(self, parent, workspace)\r
+ self._pcds = {}\r
+ self._guids = {}\r
+ self._protocols = {}\r
+ self._ppis = {}\r
+\r
+ def GetPcds(self):\r
+ return self._pcds\r
+\r
+ def GetPpis(self):\r
+ return self._ppis.values()\r
+\r
+ def GetProtocols(self):\r
+ return self._protocols.values()\r
+\r
+ def GetGuids(self):\r
+ return self._guids.values()\r
+\r
+ def Destroy(self):\r
+ for pcd in self._pcds.values():\r
+ if pcd != None:\r
+ pcd.Destroy()\r
+ for guid in self._guids.values():\r
+ if guid != None:\r
+ guid.Destroy()\r
+ for protocol in self._protocols.values():\r
+ if protocol != None:\r
+ protocol.Destroy()\r
+ for ppi in self._ppis.values():\r
+ if ppi != None:\r
+ ppi.Destroy()\r
+ self._pcds.clear()\r
+ self._guids.clear()\r
+ self._protocols.clear()\r
+ self._ppis.clear()\r
+ self._pcds.clear()\r
+ SurfaceObject.Destroy(self)\r
+\r
+ def Load(self, relativePath):\r
+ ret = SurfaceObject.Load(self, relativePath)\r
+ if not ret: return False\r
+ pcds = self.GetFileObj().GetSectionObjectsByName('pcds')\r
+ for pcd in pcds:\r
+ if pcd.GetPcdName() in self._pcds.keys():\r
+ if self._pcds[pcd.GetPcdName()] != None:\r
+ self._pcds[pcd.GetPcdName()].AddDecObj(pcd)\r
+ else:\r
+ self._pcds[pcd.GetPcdName()] = PcdItem(pcd.GetPcdName(), self, pcd)\r
+\r
+ guids = self.GetFileObj().GetSectionObjectsByName('guids')\r
+ for guid in guids:\r
+ if guid.GetName() not in self._guids.keys():\r
+ self._guids[guid.GetName()] = GuidItem(guid.GetName(), self, guid)\r
+ else:\r
+ WarnMsg("Duplicate definition for %s" % guid.GetName())\r
+\r
+ ppis = self.GetFileObj().GetSectionObjectsByName('ppis')\r
+ for ppi in ppis:\r
+ if ppi.GetName() not in self._ppis.keys():\r
+ self._ppis[ppi.GetName()] = PpiItem(ppi.GetName(), self, ppi)\r
+ else:\r
+ WarnMsg("Duplicate definition for %s" % ppi.GetName())\r
+\r
+ protocols = self.GetFileObj().GetSectionObjectsByName('protocols')\r
+ for protocol in protocols:\r
+ if protocol.GetName() not in self._protocols.keys():\r
+ self._protocols[protocol.GetName()] = ProtocolItem(protocol.GetName(), self, protocol)\r
+ else:\r
+ WarnMsg("Duplicate definition for %s" % protocol.GetName())\r
+\r
+ return True\r
+\r
+ def GetFileObjectClass(self):\r
+ return dec.DECFile\r
+\r
+ def GetName(self):\r
+ return self.GetFileObj().GetDefine("PACKAGE_NAME")\r
+\r
+ def GetPcdDefineObjs(self, name=None):\r
+ arr = []\r
+ objs = self.GetFileObj().GetSectionObjectsByName('pcds')\r
+ if name == None: return objs\r
+\r
+ for obj in objs:\r
+ if obj.GetPcdName().lower() == name.lower():\r
+ arr.append(obj)\r
+ return arr\r
+\r
+ def GetLibraryClassObjs(self):\r
+ return self.GetFileObj().GetSectionObjectsByName('libraryclasses')\r
+\r
+ def Modify(self, modify=True, modifiedObj=None):\r
+ if modify:\r
+ self._isModify = modify\r
+ self.GetParent().Modify(modify, self)\r
+ else:\r
+ if self.GetFileObj().IsModified():\r
+ return\r
+\r
+ self._isModify = modify\r
+ self.GetParent().Modify(modify, self)\r
+\r
+ def GetLibraryClassHeaderPathByName(self, clsname):\r
+ objs = self.GetLibraryClassObjs()\r
+ for obj in objs:\r
+ if obj.GetClassName() == clsname:\r
+ return obj.GetHeaderFile()\r
+ return None\r
+\r
+class DepexItem(object):\r
+ def __init__(self, parent, infObj):\r
+ self._parent = parent\r
+ self._infObj = infObj\r
+\r
+ def GetDepexString(self):\r
+ return str(self._infObj)\r
+\r
+ def GetInfObject(self):\r
+ return self._infObj\r
+\r
+class ModulePcd(object):\r
+ _type_mapping = {'FeaturePcd': 'PcdsFeatureFlag',\r
+ 'FixedPcd': 'PcdsFixedAtBuild',\r
+ 'PatchPcd': 'PcdsPatchableInModule'}\r
+\r
+ def __init__(self, parent, name, infObj, pcdItem):\r
+ assert issubclass(parent.__class__, Module), "Module's PCD's parent must be module!"\r
+ assert pcdItem != None, 'Pcd %s does not in some package!' % name\r
+\r
+ self._name = name\r
+ self._parent = parent\r
+ self._pcdItem = pcdItem\r
+ self._infObj = infObj\r
+\r
+ def GetName(self):\r
+ return self._name\r
+\r
+ def GetParent(self):\r
+ return self._name\r
+\r
+ def GetArch(self):\r
+ return self._parent.GetArch()\r
+\r
+ def Destroy(self):\r
+ self._pcdItem.DeRef(self._parent)\r
+ self._infObj = None\r
+\r
+ def GetBuildObj(self):\r
+ platformInfos = self._parent.GetPlatform().GetPcdBuildObjs(self._name, self.GetArch())\r
+ modulePcdType = self._infObj.GetPcdType()\r
+\r
+ # if platform do not gives pcd's value, get default value from package\r
+ if len(platformInfos) == 0:\r
+ if modulePcdType.lower() == 'pcd':\r
+ return self._pcdItem.GetDecObject()\r
+ else:\r
+ for obj in self._pcdItem.GetDecObjects():\r
+ if modulePcdType not in self._type_mapping.keys():\r
+ ErrorMsg("Invalid PCD type %s" % modulePcdType)\r
+ return None\r
+\r
+ if self._type_mapping[modulePcdType] == obj.GetPcdType():\r
+ return obj\r
+ ErrorMsg ('Module PCD type %s does not in valied range [%s] in package!' % \\r
+ (modulePcdType))\r
+ else:\r
+ if modulePcdType.lower() == 'pcd':\r
+ if len(platformInfos) > 1:\r
+ WarnMsg("Find more than one value for PCD %s in platform %s" % \\r
+ (self._name, self._parent.GetPlatform().GetFilename()))\r
+ return platformInfos[0]\r
+ else:\r
+ for obj in platformInfos:\r
+ if modulePcdType not in self._type_mapping.keys():\r
+ ErrorMsg("Invalid PCD type %s" % modulePcdType)\r
+ return None\r
+\r
+ if self._type_mapping[modulePcdType] == obj.GetPcdType():\r
+ return obj\r
+\r
+ ErrorMsg('Can not find value for pcd %s in pcd type %s' % \\r
+ (self._name, modulePcdType))\r
+ return None\r
+\r
+\r
+class SurfaceItem(object):\r
+ _objs = {}\r
+\r
+ def __new__(cls, *args, **kwargs):\r
+ """Maintain only a single instance of this object\r
+ @return: instance of this class\r
+\r
+ """\r
+ name = args[0]\r
+ parent = args[1]\r
+ fileObj = args[2]\r
+ if issubclass(parent.__class__, Package):\r
+ if name in cls._objs.keys():\r
+ ErrorMsg("%s item is duplicated defined in packages: %s and %s" %\r
+ (name, parent.GetFilename(), cls._objs[name].GetParent().GetFilename()))\r
+ return None\r
+ obj = object.__new__(cls, *args, **kwargs)\r
+ cls._objs[name] = obj\r
+ return obj\r
+ elif issubclass(parent.__class__, Module):\r
+ if name not in cls._objs.keys():\r
+ ErrorMsg("%s item does not defined in any package! It is used by module %s" % \\r
+ (name, parent.GetFilename()))\r
+ return None\r
+ return cls._objs[name]\r
+\r
+ return None\r
+\r
+\r
+ def __init__(self, name, parent, fileObj):\r
+ if issubclass(parent.__class__, Package):\r
+ self._name = name\r
+ self._parent = parent\r
+ self._decObj = [fileObj]\r
+ self._refMods = {}\r
+ else:\r
+ self.RefModule(parent, fileObj)\r
+\r
+ @classmethod\r
+ def GetObjectDict(cls):\r
+ return cls._objs\r
+\r
+ def GetParent(self):\r
+ return self._parent\r
+\r
+ def GetReference(self):\r
+ return self._refMods\r
+\r
+ def RefModule(self, mObj, infObj):\r
+ if mObj in self._refMods.keys():\r
+ return\r
+ self._refMods[mObj] = infObj\r
+\r
+ def DeRef(self, mObj):\r
+ if mObj not in self._refMods.keys():\r
+ WarnMsg("%s is not referenced by module %s" % (self._name, mObj.GetFilename()))\r
+ return\r
+ del self._refMods[mObj]\r
+\r
+ def Destroy(self):\r
+ self._refMods.clear()\r
+ cls = self.__class__\r
+ del cls._objs[self._name]\r
+\r
+ def GetName(self):\r
+ return self._name\r
+\r
+ def GetDecObject(self):\r
+ return self._decObj[0]\r
+\r
+ def GetDecObjects(self):\r
+ return self._decObj\r
+\r
+class PcdItem(SurfaceItem):\r
+ def AddDecObj(self, fileObj):\r
+ for decObj in self._decObj:\r
+ if decObj.GetFilename() != fileObj.GetFilename():\r
+ ErrorMsg("Pcd %s defined in more than one packages : %s and %s" % \\r
+ (self._name, decObj.GetFilename(), fileObj.GetFilename()))\r
+ return\r
+ if decObj.GetPcdType() == fileObj.GetPcdType() and \\r
+ decObj.GetArch().lower() == fileObj.GetArch():\r
+ ErrorMsg("Pcd %s is duplicated defined in pcd type %s in package %s" % \\r
+ (self._name, decObj.GetPcdType(), decObj.GetFilename()))\r
+ return\r
+ self._decObj.append(fileObj)\r
+\r
+ def GetValidPcdType(self):\r
+ types = []\r
+ for obj in self._decObj:\r
+ if obj.GetPcdType() not in types:\r
+ types += obj.GetPcdType()\r
+ return types\r
+\r
+class GuidItem(SurfaceItem):\r
+ pass\r
+\r
+class PpiItem(SurfaceItem):\r
+ pass\r
+\r
+class ProtocolItem(SurfaceItem):\r
+ pass\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+import plugins.EdkPlugins.basemodel.ini as ini\r
+import re, os\r
+from plugins.EdkPlugins.basemodel.message import *\r
+\r
+class DECFile(ini.BaseINIFile):\r
+\r
+ def GetSectionInstance(self, parent, name, isCombined=False):\r
+ return DECSection(parent, name, isCombined)\r
+\r
+ def GetComponents(self):\r
+ return self.GetSectionByName('Components')\r
+\r
+ def GetPackageRootPath(self):\r
+ return os.path.dirname(self.GetFilename()).strip()\r
+\r
+ def GetBaseName(self):\r
+ return self.GetDefine("PACKAGE_NAME").strip()\r
+\r
+ def GetVersion(self):\r
+ return self.GetDefine("PACKAGE_VERSION").strip()\r
+\r
+ def GetSectionObjectsByName(self, name, arch=None):\r
+ arr = []\r
+ sects = self.GetSectionByName(name)\r
+ for sect in sects:\r
+ # skip unmatched archtecture content\r
+ if not sect.IsArchMatch(arch):\r
+ continue\r
+\r
+ for obj in sect.GetObjects():\r
+ arr.append(obj)\r
+\r
+ return arr\r
+\r
+class DECSection(ini.BaseINISection):\r
+ def GetSectionINIObject(self, parent):\r
+ type = self.GetType()\r
+\r
+ if type.lower().find('defines') != -1:\r
+ return DECDefineSectionObject(self)\r
+ if type.lower().find('includes') != -1:\r
+ return DECIncludeObject(self)\r
+ if type.lower().find('pcd') != -1:\r
+ return DECPcdObject(self)\r
+ if type.lower() == 'libraryclasses':\r
+ return DECLibraryClassObject(self)\r
+ if type.lower() == 'guids':\r
+ return DECGuidObject(self)\r
+ if type.lower() == 'ppis':\r
+ return DECPpiObject(self)\r
+ if type.lower() == 'protocols':\r
+ return DECProtocolObject(self)\r
+\r
+ return DECSectionObject(self)\r
+\r
+ def GetType(self):\r
+ arr = self._name.split('.')\r
+ return arr[0].strip()\r
+\r
+ def GetArch(self):\r
+ arr = self._name.split('.')\r
+ if len(arr) == 1:\r
+ return 'common'\r
+ return arr[1]\r
+\r
+ def IsArchMatch(self, arch):\r
+ if arch == None or self.GetArch() == 'common':\r
+ return True\r
+\r
+ if self.GetArch().lower() != arch.lower():\r
+ return False\r
+\r
+ return True\r
+\r
+class DECSectionObject(ini.BaseINISectionObject):\r
+ def GetArch(self):\r
+ return self.GetParent().GetArch()\r
+\r
+class DECDefineSectionObject(DECSectionObject):\r
+ def __init__(self, parent):\r
+ DECSectionObject.__init__(self, parent)\r
+ self._key = None\r
+ self._value = None\r
+\r
+ def Parse(self):\r
+ assert (self._start == self._end), 'The object in define section must be in single line'\r
+\r
+ line = self.GetLineByOffset(self._start).strip()\r
+\r
+ line = line.split('#')[0]\r
+ arr = line.split('=')\r
+ if len(arr) != 2:\r
+ ErrorMsg('Invalid define section object',\r
+ self.GetFilename(),\r
+ self.GetParent().GetName()\r
+ )\r
+ return False\r
+\r
+ self._key = arr[0].strip()\r
+ self._value = arr[1].strip()\r
+\r
+ return True\r
+\r
+ def GetKey(self):\r
+ return self._key\r
+\r
+ def GetValue(self):\r
+ return self._value\r
+\r
+class DECGuidObject(DECSectionObject):\r
+ _objs = {}\r
+\r
+ def __init__(self, parent):\r
+ DECSectionObject.__init__(self, parent)\r
+ self._name = None\r
+\r
+ def Parse(self):\r
+ line = self.GetLineByOffset(self._start).strip().split('#')[0]\r
+ self._name = line.split('=')[0].strip()\r
+ self._guid = line.split('=')[1].strip()\r
+ objdict = DECGuidObject._objs\r
+ if self._name not in objdict.keys():\r
+ objdict[self._name] = [self]\r
+ else:\r
+ objdict[self._name].append(self)\r
+\r
+ return True\r
+\r
+ def GetName(self):\r
+ return self._name\r
+\r
+ def GetGuid(self):\r
+ return self._guid\r
+\r
+ def Destroy(self):\r
+ objdict = DECGuidObject._objs\r
+ objdict[self._name].remove(self)\r
+ if len(objdict[self._name]) == 0:\r
+ del objdict[self._name]\r
+\r
+ @staticmethod\r
+ def GetObjectDict():\r
+ return DECGuidObject._objs\r
+\r
+class DECPpiObject(DECSectionObject):\r
+ _objs = {}\r
+ def __init__(self, parent):\r
+ DECSectionObject.__init__(self, parent)\r
+ self._name = None\r
+\r
+ def Parse(self):\r
+ line = self.GetLineByOffset(self._start).strip().split('#')[0]\r
+ self._name = line.split('=')[0].strip()\r
+ self._guid = line.split('=')[1].strip()\r
+ objdict = DECPpiObject._objs\r
+ if self._name not in objdict.keys():\r
+ objdict[self._name] = [self]\r
+ else:\r
+ objdict[self._name].append(self)\r
+\r
+ return True\r
+\r
+ def GetName(self):\r
+ return self._name\r
+\r
+ def GetGuid(self):\r
+ return self._guid\r
+\r
+ def Destroy(self):\r
+ objdict = DECPpiObject._objs\r
+ objdict[self._name].remove(self)\r
+ if len(objdict[self._name]) == 0:\r
+ del objdict[self._name]\r
+\r
+ @staticmethod\r
+ def GetObjectDict():\r
+ return DECPpiObject._objs\r
+\r
+class DECProtocolObject(DECSectionObject):\r
+ _objs = {}\r
+\r
+ def __init__(self, parent):\r
+ DECSectionObject.__init__(self, parent)\r
+ self._name = None\r
+\r
+ def Parse(self):\r
+ line = self.GetLineByOffset(self._start).strip().split('#')[0]\r
+ self._name = line.split('=')[0].strip()\r
+ self._guid = line.split('=')[1].strip()\r
+ objdict = DECProtocolObject._objs\r
+ if self._name not in objdict.keys():\r
+ objdict[self._name] = [self]\r
+ else:\r
+ objdict[self._name].append(self)\r
+\r
+ return True\r
+\r
+ def GetName(self):\r
+ return self._name\r
+\r
+ def GetGuid(self):\r
+ return self._guid\r
+\r
+ def Destroy(self):\r
+ objdict = DECProtocolObject._objs\r
+ objdict[self._name].remove(self)\r
+ if len(objdict[self._name]) == 0:\r
+ del objdict[self._name]\r
+\r
+\r
+ @staticmethod\r
+ def GetObjectDict():\r
+ return DECProtocolObject._objs\r
+\r
+class DECLibraryClassObject(DECSectionObject):\r
+ _objs = {}\r
+\r
+ def __init__(self, parent):\r
+ DECSectionObject.__init__(self, parent)\r
+ self.mClassName = None\r
+ self.mHeaderFile = None\r
+\r
+ def Parse(self):\r
+ line = self.GetLineByOffset(self._start).strip().split('#')[0]\r
+ self.mClassName, self.mHeaderFile = line.split('|')\r
+ objdict = DECLibraryClassObject._objs\r
+ if self.mClassName not in objdict.keys():\r
+ objdict[self.mClassName] = [self]\r
+ else:\r
+ objdict[self.mClassName].append(self)\r
+ return True\r
+\r
+ def GetClassName(self):\r
+ return self.mClassName\r
+\r
+ def GetName(self):\r
+ return self.mClassName\r
+\r
+ def GetHeaderFile(self):\r
+ return self.mHeaderFile\r
+\r
+ def Destroy(self):\r
+ objdict = DECLibraryClassObject._objs\r
+ objdict[self.mClassName].remove(self)\r
+ if len(objdict[self.mClassName]) == 0:\r
+ del objdict[self.mClassName]\r
+\r
+ @staticmethod\r
+ def GetObjectDict():\r
+ return DECLibraryClassObject._objs\r
+\r
+class DECIncludeObject(DECSectionObject):\r
+ def __init__(self, parent):\r
+ DECSectionObject.__init__(self, parent)\r
+\r
+ def GetPath(self):\r
+ return self.GetLineByOffset(self._start).split('#')[0].strip()\r
+\r
+class DECPcdObject(DECSectionObject):\r
+ _objs = {}\r
+\r
+ def __init__(self, parent):\r
+ DECSectionObject.__init__(self, parent)\r
+ self.mPcdName = None\r
+ self.mPcdDefaultValue = None\r
+ self.mPcdDataType = None\r
+ self.mPcdToken = None\r
+\r
+ def Parse(self):\r
+ line = self.GetLineByOffset(self._start).strip().split('#')[0]\r
+ (self.mPcdName, self.mPcdDefaultValue, self.mPcdDataType, self.mPcdToken) = line.split('|')\r
+ objdict = DECPcdObject._objs\r
+ if self.mPcdName not in objdict.keys():\r
+ objdict[self.mPcdName] = [self]\r
+ else:\r
+ objdict[self.mPcdName].append(self)\r
+\r
+ return True\r
+\r
+ def Destroy(self):\r
+ objdict = DECPcdObject._objs\r
+ objdict[self.mPcdName].remove(self)\r
+ if len(objdict[self.mPcdName]) == 0:\r
+ del objdict[self.mPcdName]\r
+\r
+ def GetPcdType(self):\r
+ return self.GetParent().GetType()\r
+\r
+ def GetPcdName(self):\r
+ return self.mPcdName\r
+\r
+ def GetPcdValue(self):\r
+ return self.mPcdDefaultValue\r
+\r
+ def GetPcdDataType(self):\r
+ return self.mPcdDataType\r
+\r
+ def GetPcdToken(self):\r
+ return self.mPcdToken\r
+\r
+ def GetName(self):\r
+ return self.GetPcdName().split('.')[1]\r
+\r
+ @staticmethod\r
+ def GetObjectDict():\r
+ return DECPcdObject._objs\r
--- /dev/null
+## @file\r
+#\r
+# This file produce action class to generate doxygen document for edk2 codebase.\r
+# The action classes are shared by GUI and command line tools.\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+"""This file produce action class to generate doxygen document for edk2 codebase.\r
+ The action classes are shared by GUI and command line tools.\r
+"""\r
+import plugins.EdkPlugins.basemodel.doxygen as doxygen\r
+import os\r
+try:\r
+ import wx\r
+ gInGui = True\r
+except:\r
+ gInGui = False\r
+import re\r
+import plugins.EdkPlugins.edk2.model.inf as inf\r
+import plugins.EdkPlugins.edk2.model.dec as dec\r
+from plugins.EdkPlugins.basemodel.message import *\r
+\r
+_ignore_dir = ['.svn', '_svn', 'cvs']\r
+_inf_key_description_mapping_table = {\r
+ 'INF_VERSION':'Version of INF file specification',\r
+ #'BASE_NAME':'Module Name',\r
+ 'FILE_GUID':'Module Guid',\r
+ 'MODULE_TYPE': 'Module Type',\r
+ 'VERSION_STRING': 'Module Version',\r
+ 'LIBRARY_CLASS': 'Produced Library Class',\r
+ 'EFI_SPECIFICATION_VERSION': 'UEFI Specification Version',\r
+ 'PI_SPECIFICATION_VERSION': 'PI Specification Version',\r
+ 'ENTRY_POINT': 'Module Entry Point Function',\r
+ 'CONSTRUCTOR': 'Library Constructor Function'\r
+}\r
+\r
+_dec_key_description_mapping_table = {\r
+ 'DEC_SPECIFICATION': 'Version of DEC file specification',\r
+ 'PACKAGE_GUID': 'Package Guid'\r
+}\r
+class DoxygenAction:\r
+ """This is base class for all doxygen action.\r
+ """\r
+\r
+ def __init__(self, doxPath, chmPath, outputPath, projname, mode='html', log=None, verbose=False):\r
+ """Constructor function.\r
+ @param doxPath the obosolution path of doxygen execute file.\r
+ @param outputPath the obosolution output path.\r
+ @param log log function for output message\r
+ """\r
+ self._doxPath = doxPath\r
+ self._chmPath = chmPath\r
+ self._outputPath = outputPath\r
+ self._projname = projname\r
+ self._configFile = None # doxygen config file is used by doxygen exe file\r
+ self._indexPageFile = None # doxygen page file for index page.\r
+ self._log = log\r
+ self._mode = mode\r
+ self._verbose = verbose\r
+ self._doxygenCallback = None\r
+ self._chmCallback = None\r
+\r
+ def Log(self, message, level='info'):\r
+ if self._log != None:\r
+ self._log(message, level)\r
+\r
+ def IsVerbose(self):\r
+ return self._verbose\r
+\r
+ def Generate(self):\r
+ """Generate interface called by outer directly"""\r
+ self.Log(">>>>>> Start generate doxygen document for %s... Zzz....\n" % self._projname)\r
+\r
+ # create doxygen config file at first\r
+ self._configFile = doxygen.DoxygenConfigFile()\r
+ self._configFile.SetOutputDir(self._outputPath)\r
+\r
+ self._configFile.SetWarningFilePath(os.path.join(self._outputPath, 'warning.txt'))\r
+ if self._mode.lower() == 'html':\r
+ self._configFile.SetHtmlMode()\r
+ else:\r
+ self._configFile.SetChmMode()\r
+\r
+ self.Log(" >>>>>> Initialize doxygen config file...Zzz...\n")\r
+ self.InitializeConfigFile()\r
+\r
+ self.Log(" >>>>>> Generate doxygen index page file...Zzz...\n")\r
+ indexPagePath = self.GenerateIndexPage()\r
+ if indexPagePath == None:\r
+ self.Log("Fail to generate index page!\n", 'error')\r
+ return False\r
+ else:\r
+ self.Log("Success to create doxygen index page file %s \n" % indexPagePath)\r
+\r
+ # Add index page doxygen file to file list.\r
+ self._configFile.AddFile(indexPagePath)\r
+\r
+ # save config file to output path\r
+ configFilePath = os.path.join(self._outputPath, self._projname + '.doxygen_config')\r
+ self._configFile.Generate(configFilePath)\r
+ self.Log(" <<<<<< Success Save doxygen config file to %s...\n" % configFilePath)\r
+\r
+ # launch doxygen tool to generate document\r
+ if self._doxygenCallback != None:\r
+ self.Log(" >>>>>> Start doxygen process...Zzz...\n")\r
+ if not self._doxygenCallback(self._doxPath, configFilePath):\r
+ return False\r
+ else:\r
+ self.Log("Fail to create doxygen process!", 'error')\r
+ return False\r
+\r
+ return True\r
+\r
+ def InitializeConfigFile(self):\r
+ """Initialize config setting for doxygen project. It will be invoked after config file\r
+ object is created. Inherited class should implement it.\r
+ """\r
+\r
+ def GenerateIndexPage(self):\r
+ """Generate doxygen index page. Inherited class should implement it."""\r
+ return None\r
+\r
+ def RegisterCallbackDoxygenProcess(self, callback):\r
+ self._doxygenCallback = callback\r
+\r
+ def RegisterCallbackCHMProcess(self, callback):\r
+ self._chmCallback = callback\r
+\r
+class PlatformDocumentAction(DoxygenAction):\r
+ """Generate platform doxygen document, will be implement at future."""\r
+\r
+class PackageDocumentAction(DoxygenAction):\r
+ """Generate package reference document"""\r
+\r
+ def __init__(self, doxPath, chmPath, outputPath, pObj, mode='html', log=None, arch=None, tooltag=None,\r
+ onlyInclude=False, verbose=False):\r
+ DoxygenAction.__init__(self, doxPath, chmPath, outputPath, pObj.GetName(), mode, log, verbose)\r
+ self._pObj = pObj\r
+ self._arch = arch\r
+ self._tooltag = tooltag\r
+ self._onlyIncludeDocument = onlyInclude\r
+\r
+ def InitializeConfigFile(self):\r
+ if self._arch == 'IA32':\r
+ self._configFile.AddPreDefined('MDE_CPU_IA32')\r
+ elif self._arch == 'X64':\r
+ self._configFile.AddPreDefined('MDE_CPU_X64')\r
+ elif self._arch == 'IPF':\r
+ self._configFile.AddPreDefined('MDE_CPU_IPF')\r
+ elif self._arch == 'EBC':\r
+ self._configFile.AddPreDefined('MDE_CPU_EBC')\r
+ else:\r
+ self._arch = None\r
+ self._configFile.AddPreDefined('MDE_CPU_IA32')\r
+ self._configFile.AddPreDefined('MDE_CPU_X64')\r
+ self._configFile.AddPreDefined('MDE_CPU_IPF')\r
+ self._configFile.AddPreDefined('MDE_CPU_EBC')\r
+ self._configFile.AddPreDefined('MDE_CPU_ARM')\r
+\r
+ namestr = self._pObj.GetName()\r
+ if self._arch != None:\r
+ namestr += '[%s]' % self._arch\r
+ if self._tooltag != None:\r
+ namestr += '[%s]' % self._tooltag\r
+ self._configFile.SetProjectName(namestr)\r
+ self._configFile.SetStripPath(self._pObj.GetWorkspace())\r
+ self._configFile.SetProjectVersion(self._pObj.GetFileObj().GetVersion())\r
+ self._configFile.AddPattern('*.decdoxygen')\r
+\r
+ if self._tooltag.lower() == 'msft':\r
+ self._configFile.AddPreDefined('_MSC_EXTENSIONS')\r
+ elif self._tooltag.lower() == 'gnu':\r
+ self._configFile.AddPreDefined('__GNUC__')\r
+ elif self._tooltag.lower() == 'intel':\r
+ self._configFile.AddPreDefined('__INTEL_COMPILER')\r
+ else:\r
+ self._tooltag = None\r
+ self._configFile.AddPreDefined('_MSC_EXTENSIONS')\r
+ self._configFile.AddPreDefined('__GNUC__')\r
+ self._configFile.AddPreDefined('__INTEL_COMPILER')\r
+\r
+ self._configFile.AddPreDefined('ASM_PFX= ')\r
+ self._configFile.AddPreDefined('OPTIONAL= ')\r
+\r
+ def GenerateIndexPage(self):\r
+ """Generate doxygen index page. Inherited class should implement it."""\r
+ fObj = self._pObj.GetFileObj()\r
+ pdObj = doxygen.DoxygenFile('%s Package Document' % self._pObj.GetName(),\r
+ '%s.decdoxygen' % self._pObj.GetFilename())\r
+ self._configFile.AddFile(pdObj.GetFilename())\r
+ pdObj.AddDescription(fObj.GetFileHeader())\r
+\r
+ defSection = fObj.GetSectionByName('defines')[0]\r
+ baseSection = doxygen.Section('PackageBasicInformation', 'Package Basic Information')\r
+ descr = '<TABLE>'\r
+ for obj in defSection.GetObjects():\r
+ if obj.GetKey() in _dec_key_description_mapping_table.keys():\r
+ descr += '<TR>'\r
+ descr += '<TD><B>%s</B></TD>' % _dec_key_description_mapping_table[obj.GetKey()]\r
+ descr += '<TD>%s</TD>' % obj.GetValue()\r
+ descr += '</TR>'\r
+ descr += '</TABLE><br>'\r
+ baseSection.AddDescription(descr)\r
+ pdObj.AddSection(baseSection)\r
+\r
+ knownIssueSection = doxygen.Section('Known_Issue_section', 'Known Issue')\r
+ knownIssueSection.AddDescription('<ul>')\r
+ knownIssueSection.AddDescription('<li> OPTIONAL macro for function parameter can not be dealed with doxygen, so it disapear in this document! </li>')\r
+ knownIssueSection.AddDescription('</ul>')\r
+ pdObj.AddSection(knownIssueSection)\r
+\r
+ self.AddAllIncludeFiles(self._pObj, self._configFile)\r
+ pages = self.GenerateIncludesSubPage(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ pages = self.GenerateLibraryClassesSubPage(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ pages = self.GeneratePcdSubPages(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ pages = self.GenerateGuidSubPages(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ pages = self.GeneratePpiSubPages(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ pages = self.GenerateProtocolSubPages(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ if not self._onlyIncludeDocument:\r
+ pdObj.AddPages(self.GenerateModulePages(self._pObj, self._configFile))\r
+\r
+ pdObj.Save()\r
+ return pdObj.GetFilename()\r
+\r
+ def GenerateIncludesSubPage(self, pObj, configFile):\r
+ # by default add following path as include path to config file\r
+ pkpath = pObj.GetFileObj().GetPackageRootPath()\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include'))\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Library'))\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Protocol'))\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Ppi'))\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Guid'))\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'IndustryStandard'))\r
+\r
+ rootArray = []\r
+ pageRoot = doxygen.Page("Public Includes", "%s_public_includes" % pObj.GetName())\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('includes')\r
+ if len(objs) == 0: return []\r
+\r
+ for obj in objs:\r
+ # Add path to include path\r
+ path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetPath())\r
+ configFile.AddIncludePath(path)\r
+\r
+ # only list common folder's include file\r
+ if obj.GetArch().lower() != 'common':\r
+ continue\r
+\r
+ bNeedAddIncludePage = False\r
+ topPage = doxygen.Page(self._ConvertPathToDoxygen(path, pObj), 'public_include_top')\r
+\r
+ topPage.AddDescription('<ul>\n')\r
+ for file in os.listdir(path):\r
+ if file.lower() in _ignore_dir: continue\r
+ fullpath = os.path.join(path, file)\r
+ if os.path.isfile(fullpath):\r
+ self.ProcessSourceFileForInclude(fullpath, pObj, configFile)\r
+ topPage.AddDescription('<li> \link %s\endlink </li>\n' % self._ConvertPathToDoxygen(fullpath, pObj))\r
+ else:\r
+ if file.lower() in ['library', 'protocol', 'guid', 'ppi', 'ia32', 'x64', 'ipf', 'ebc', 'arm', 'pi', 'uefi', 'aarch64']:\r
+ continue\r
+ bNeedAddSubPage = False\r
+ subpage = doxygen.Page(self._ConvertPathToDoxygen(fullpath, pObj), 'public_include_%s' % file)\r
+ subpage.AddDescription('<ul>\n')\r
+ for subfile in os.listdir(fullpath):\r
+ if subfile.lower() in _ignore_dir: continue\r
+ bNeedAddSubPage = True\r
+ subfullpath = os.path.join(fullpath, subfile)\r
+ self.ProcessSourceFileForInclude(subfullpath, pObj, configFile)\r
+ subpage.AddDescription('<li> \link %s \endlink </li>\n' % self._ConvertPathToDoxygen(subfullpath, pObj))\r
+ subpage.AddDescription('</ul>\n')\r
+ if bNeedAddSubPage:\r
+ bNeedAddIncludePage = True\r
+ pageRoot.AddPage(subpage)\r
+ topPage.AddDescription('</ul>\n')\r
+ if bNeedAddIncludePage:\r
+ pageRoot.AddPage(topPage)\r
+\r
+ if pageRoot.GetSubpageCount() != 0:\r
+ return [pageRoot]\r
+ else:\r
+ return []\r
+\r
+ def GenerateLibraryClassesSubPage(self, pObj, configFile):\r
+ """\r
+ Generate sub page for library class for package.\r
+ One DEC file maybe contains many library class sections\r
+ for different architecture.\r
+\r
+ @param fObj DEC file object.\r
+ """\r
+ rootArray = []\r
+ pageRoot = doxygen.Page("Library Class", "%s_libraryclass" % pObj.GetName())\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('libraryclass', self._arch)\r
+ if len(objs) == 0: return []\r
+\r
+ if self._arch != None:\r
+ for obj in objs:\r
+ classPage = doxygen.Page(obj.GetClassName(),\r
+ "lc_%s" % obj.GetClassName())\r
+ comments = obj.GetComment()\r
+ if len(comments) != 0:\r
+ classPage.AddDescription('<br>\n'.join(comments) + '<br>\n')\r
+ pageRoot.AddPage(classPage)\r
+ path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+ path = path[len(pObj.GetWorkspace()) + 1:]\r
+ if len(comments) == 0:\r
+ classPage.AddDescription('\copydoc %s<p>' % obj.GetHeaderFile())\r
+ section = doxygen.Section('ref', 'Refer to Header File')\r
+ section.AddDescription('\link %s\n' % obj.GetHeaderFile())\r
+ section.AddDescription(' \endlink<p>\n')\r
+ classPage.AddSection(section)\r
+ fullPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+ self.ProcessSourceFileForInclude(fullPath, pObj, configFile)\r
+ else:\r
+ archPageDict = {}\r
+ for obj in objs:\r
+ if obj.GetArch() not in archPageDict.keys():\r
+ archPageDict[obj.GetArch()] = doxygen.Page(obj.GetArch(),\r
+ 'lc_%s' % obj.GetArch())\r
+ pageRoot.AddPage(archPageDict[obj.GetArch()])\r
+ subArchRoot = archPageDict[obj.GetArch()]\r
+ classPage = doxygen.Page(obj.GetClassName(),\r
+ "lc_%s" % obj.GetClassName())\r
+ comments = obj.GetComment()\r
+ if len(comments) != 0:\r
+ classPage.AddDescription('<br>\n'.join(comments) + '<br>\n')\r
+ subArchRoot.AddPage(classPage)\r
+ path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+ path = path[len(pObj.GetWorkspace()) + 1:]\r
+ if len(comments) == 0:\r
+ classPage.AddDescription('\copydoc %s<p>' % obj.GetHeaderFile())\r
+ section = doxygen.Section('ref', 'Refer to Header File')\r
+ section.AddDescription('\link %s\n' % obj.GetHeaderFile())\r
+ section.AddDescription(' \endlink<p>\n')\r
+ classPage.AddSection(section)\r
+ fullPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+\r
+ self.ProcessSourceFileForInclude(fullPath, pObj, configFile)\r
+ rootArray.append(pageRoot)\r
+ return rootArray\r
+\r
+ def ProcessSourceFileForInclude(self, path, pObj, configFile, infObj=None):\r
+ """\r
+ @param path the analysising file full path\r
+ @param pObj package object\r
+ @param configFile doxygen config file.\r
+ """\r
+ if gInGui:\r
+ wx.Yield()\r
+ if not os.path.exists(path):\r
+ ErrorMsg('Source file path %s does not exist!' % path)\r
+ return\r
+\r
+ if configFile.FileExists(path):\r
+ return\r
+\r
+ try:\r
+ f = open(path, 'r')\r
+ lines = f.readlines()\r
+ f.close()\r
+ except IOError:\r
+ ErrorMsg('Fail to open file %s' % path)\r
+ return\r
+\r
+ configFile.AddFile(path)\r
+\r
+ no = 0\r
+ for no in xrange(len(lines)):\r
+ if len(lines[no].strip()) == 0:\r
+ continue\r
+ if lines[no].strip()[:2] in ['##', '//', '/*', '*/']:\r
+ continue\r
+ index = lines[no].lower().find('include')\r
+ #mo = IncludePattern.finditer(lines[no].lower())\r
+ mo = re.match(r"^#\s*include\s+[<\"]([\\/\w.]+)[>\"]$", lines[no].strip().lower())\r
+ if not mo:\r
+ continue\r
+ mo = re.match(r"^[#\w\s]+[<\"]([\\/\w.]+)[>\"]$", lines[no].strip())\r
+ filePath = mo.groups()[0]\r
+\r
+ if filePath == None or len(filePath) == 0:\r
+ continue\r
+\r
+ # find header file in module's path firstly.\r
+ fullPath = None\r
+\r
+ if os.path.exists(os.path.join(os.path.dirname(path), filePath)):\r
+ # Find the file in current directory\r
+ fullPath = os.path.join(os.path.dirname(path), filePath).replace('\\', '/')\r
+ else:\r
+ # find in depedent package's include path\r
+ incObjs = pObj.GetFileObj().GetSectionObjectsByName('includes')\r
+ for incObj in incObjs:\r
+ incPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), incObj.GetPath()).strip()\r
+ incPath = os.path.realpath(os.path.join(incPath, filePath))\r
+ if os.path.exists(incPath):\r
+ fullPath = incPath\r
+ break\r
+ if infObj != None:\r
+ pkgInfObjs = infObj.GetSectionObjectsByName('packages')\r
+ for obj in pkgInfObjs:\r
+ decObj = dec.DECFile(os.path.join(pObj.GetWorkspace(), obj.GetPath()))\r
+ if not decObj:\r
+ ErrorMsg ('Fail to create pacakge object for %s' % obj.GetPackageName())\r
+ continue\r
+ if not decObj.Parse():\r
+ ErrorMsg ('Fail to load package object for %s' % obj.GetPackageName())\r
+ continue\r
+ incObjs = decObj.GetSectionObjectsByName('includes')\r
+ for incObj in incObjs:\r
+ incPath = os.path.join(decObj.GetPackageRootPath(), incObj.GetPath()).replace('\\', '/')\r
+ if os.path.exists(os.path.join(incPath, filePath)):\r
+ fullPath = os.path.join(os.path.join(incPath, filePath))\r
+ break\r
+ if fullPath != None:\r
+ break\r
+\r
+ if fullPath == None and self.IsVerbose():\r
+ self.Log('Can not resolve header file %s for file %s in package %s\n' % (filePath, path, pObj.GetFileObj().GetFilename()), 'error')\r
+ return\r
+ else:\r
+ fullPath = fullPath.replace('\\', '/')\r
+ if self.IsVerbose():\r
+ self.Log('Preprocessing: Add include file %s for file %s\n' % (fullPath, path))\r
+ #LogMsg ('Preprocessing: Add include file %s for file %s' % (fullPath, path))\r
+ self.ProcessSourceFileForInclude(fullPath, pObj, configFile, infObj)\r
+\r
+ def AddAllIncludeFiles(self, pObj, configFile):\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('includes')\r
+ for obj in objs:\r
+ incPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetPath())\r
+ for root, dirs, files in os.walk(incPath):\r
+ for dir in dirs:\r
+ if dir.lower() in _ignore_dir:\r
+ dirs.remove(dir)\r
+ for file in files:\r
+ path = os.path.normpath(os.path.join(root, file))\r
+ configFile.AddFile(path.replace('/', '\\'))\r
+\r
+ def GeneratePcdSubPages(self, pObj, configFile):\r
+ """\r
+ Generate sub pages for package's PCD definition.\r
+ @param pObj package object\r
+ @param configFile config file object\r
+ """\r
+ rootArray = []\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('pcd')\r
+ if len(objs) == 0:\r
+ return []\r
+\r
+ pcdRootPage = doxygen.Page('PCD', 'pcd_root_page')\r
+ typeRootPageDict = {}\r
+ typeArchRootPageDict = {}\r
+ for obj in objs:\r
+ if obj.GetPcdType() not in typeRootPageDict.keys():\r
+ typeRootPageDict[obj.GetPcdType()] = doxygen.Page(obj.GetPcdType(), 'pcd_%s_root_page' % obj.GetPcdType())\r
+ pcdRootPage.AddPage(typeRootPageDict[obj.GetPcdType()])\r
+ typeRoot = typeRootPageDict[obj.GetPcdType()]\r
+ if self._arch != None:\r
+ pcdPage = doxygen.Page('%s' % obj.GetPcdName(),\r
+ 'pcd_%s_%s_%s' % (obj.GetPcdType(), obj.GetArch(), obj.GetPcdName().split('.')[1]))\r
+ pcdPage.AddDescription('<br>\n'.join(obj.GetComment()) + '<br>\n')\r
+ section = doxygen.Section('PCDinformation', 'PCD Information')\r
+ desc = '<TABLE>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>Name</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Token Space</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Token number</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Data Type</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Default Value</CAPTION></TD>'\r
+ desc += '</TR>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[1]\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[0]\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdToken()\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdDataType()\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdValue()\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ section.AddDescription(desc)\r
+ pcdPage.AddSection(section)\r
+ typeRoot.AddPage(pcdPage)\r
+ else:\r
+ keystr = obj.GetPcdType() + obj.GetArch()\r
+ if keystr not in typeArchRootPageDict.keys():\r
+ typeArchRootPage = doxygen.Page(obj.GetArch(), 'pcd_%s_%s_root_page' % (obj.GetPcdType(), obj.GetArch()))\r
+ typeArchRootPageDict[keystr] = typeArchRootPage\r
+ typeRoot.AddPage(typeArchRootPage)\r
+ typeArchRoot = typeArchRootPageDict[keystr]\r
+ pcdPage = doxygen.Page('%s' % obj.GetPcdName(),\r
+ 'pcd_%s_%s_%s' % (obj.GetPcdType(), obj.GetArch(), obj.GetPcdName().split('.')[1]))\r
+ pcdPage.AddDescription('<br>\n'.join(obj.GetComment()) + '<br>\n')\r
+ section = doxygen.Section('PCDinformation', 'PCD Information')\r
+ desc = '<TABLE>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>Name</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Token Space</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Token number</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Data Type</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Default Value</CAPTION></TD>'\r
+ desc += '</TR>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[1]\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[0]\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdToken()\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdDataType()\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdValue()\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ section.AddDescription(desc)\r
+ pcdPage.AddSection(section)\r
+ typeArchRoot.AddPage(pcdPage)\r
+ return [pcdRootPage]\r
+\r
+ def _GenerateGuidSubPage(self, pObj, obj, configFile):\r
+ guidPage = doxygen.Page('%s' % obj.GetName(),\r
+ 'guid_%s_%s' % (obj.GetArch(), obj.GetName()))\r
+ comments = obj.GetComment()\r
+ if len(comments) != 0:\r
+ guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')\r
+ section = doxygen.Section('BasicGuidInfo', 'GUID Information')\r
+ desc = '<TABLE>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>GUID\'s Guid Name</CAPTION></TD><TD><CAPTION>GUID\'s Guid</CAPTION></TD>'\r
+ desc += '</TR>'\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % obj.GetName()\r
+ desc += '<TD>%s</TD>' % obj.GetGuid()\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ section.AddDescription(desc)\r
+ guidPage.AddSection(section)\r
+ refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)\r
+ if refFile:\r
+ relPath = refFile[len(pObj.GetWorkspace()) + 1:]\r
+ if len(comments) == 0:\r
+ guidPage.AddDescription(' \\copydoc %s <br>' % relPath)\r
+\r
+ section = doxygen.Section('ref', 'Refer to Header File')\r
+ section.AddDescription('\link %s\n' % relPath)\r
+ section.AddDescription('\endlink\n')\r
+ self.ProcessSourceFileForInclude(refFile, pObj, configFile)\r
+ guidPage.AddSection(section)\r
+ return guidPage\r
+\r
+ def GenerateGuidSubPages(self, pObj, configFile):\r
+ """\r
+ Generate sub pages for package's GUID definition.\r
+ @param pObj package object\r
+ @param configFilf doxygen config file object\r
+ """\r
+ pageRoot = doxygen.Page('GUID', 'guid_root_page')\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('guids', self._arch)\r
+ if len(objs) == 0: return []\r
+ if self._arch != None:\r
+ for obj in objs:\r
+ pageRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, configFile))\r
+ else:\r
+ guidArchRootPageDict = {}\r
+ for obj in objs:\r
+ if obj.GetArch() not in guidArchRootPageDict.keys():\r
+ guidArchRoot = doxygen.Page(obj.GetArch(), 'guid_arch_root_%s' % obj.GetArch())\r
+ pageRoot.AddPage(guidArchRoot)\r
+ guidArchRootPageDict[obj.GetArch()] = guidArchRoot\r
+ guidArchRoot = guidArchRootPageDict[obj.GetArch()]\r
+ guidArchRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, configFile))\r
+ return [pageRoot]\r
+\r
+ def _GeneratePpiSubPage(self, pObj, obj, configFile):\r
+ guidPage = doxygen.Page(obj.GetName(), 'ppi_page_%s' % obj.GetName())\r
+ comments = obj.GetComment()\r
+ if len(comments) != 0:\r
+ guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')\r
+ section = doxygen.Section('BasicPpiInfo', 'PPI Information')\r
+ desc = '<TABLE>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>PPI\'s Guid Name</CAPTION></TD><TD><CAPTION>PPI\'s Guid</CAPTION></TD>'\r
+ desc += '</TR>'\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % obj.GetName()\r
+ desc += '<TD>%s</TD>' % obj.GetGuid()\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ section.AddDescription(desc)\r
+ guidPage.AddSection(section)\r
+ refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)\r
+ if refFile:\r
+ relPath = refFile[len(pObj.GetWorkspace()) + 1:]\r
+ if len(comments) == 0:\r
+ guidPage.AddDescription(' \\copydoc %s <br>' % relPath)\r
+ section = doxygen.Section('ref', 'Refer to Header File')\r
+ section.AddDescription('\link %s\n' % relPath)\r
+ section.AddDescription('\endlink\n')\r
+ self.ProcessSourceFileForInclude(refFile, pObj, configFile)\r
+ guidPage.AddSection(section)\r
+\r
+ return guidPage\r
+\r
+ def GeneratePpiSubPages(self, pObj, configFile):\r
+ """\r
+ Generate sub pages for package's GUID definition.\r
+ @param pObj package object\r
+ @param configFilf doxygen config file object\r
+ """\r
+ pageRoot = doxygen.Page('PPI', 'ppi_root_page')\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('ppis', self._arch)\r
+ if len(objs) == 0: return []\r
+ if self._arch != None:\r
+ for obj in objs:\r
+ pageRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, configFile))\r
+ else:\r
+ guidArchRootPageDict = {}\r
+ for obj in objs:\r
+ if obj.GetArch() not in guidArchRootPageDict.keys():\r
+ guidArchRoot = doxygen.Page(obj.GetArch(), 'ppi_arch_root_%s' % obj.GetArch())\r
+ pageRoot.AddPage(guidArchRoot)\r
+ guidArchRootPageDict[obj.GetArch()] = guidArchRoot\r
+ guidArchRoot = guidArchRootPageDict[obj.GetArch()]\r
+ guidArchRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, configFile))\r
+ return [pageRoot]\r
+\r
+ def _GenerateProtocolSubPage(self, pObj, obj, configFile):\r
+ guidPage = doxygen.Page(obj.GetName(), 'protocol_page_%s' % obj.GetName())\r
+ comments = obj.GetComment()\r
+ if len(comments) != 0:\r
+ guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')\r
+ section = doxygen.Section('BasicProtocolInfo', 'PROTOCOL Information')\r
+ desc = '<TABLE>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>PROTOCOL\'s Guid Name</CAPTION></TD><TD><CAPTION>PROTOCOL\'s Guid</CAPTION></TD>'\r
+ desc += '</TR>'\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % obj.GetName()\r
+ desc += '<TD>%s</TD>' % obj.GetGuid()\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ section.AddDescription(desc)\r
+ guidPage.AddSection(section)\r
+\r
+ refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)\r
+ if refFile:\r
+ relPath = refFile[len(pObj.GetWorkspace()) + 1:]\r
+ if len(comments) == 0:\r
+ guidPage.AddDescription(' \\copydoc %s <br>' % relPath)\r
+ section = doxygen.Section('ref', 'Refer to Header File')\r
+ section.AddDescription('\link %s\n' % relPath)\r
+ section.AddDescription('\endlink\n')\r
+ self.ProcessSourceFileForInclude(refFile, pObj, configFile)\r
+ guidPage.AddSection(section)\r
+\r
+ return guidPage\r
+\r
+ def GenerateProtocolSubPages(self, pObj, configFile):\r
+ """\r
+ Generate sub pages for package's GUID definition.\r
+ @param pObj package object\r
+ @param configFilf doxygen config file object\r
+ """\r
+ pageRoot = doxygen.Page('PROTOCOL', 'protocol_root_page')\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('protocols', self._arch)\r
+ if len(objs) == 0: return []\r
+ if self._arch != None:\r
+ for obj in objs:\r
+ pageRoot.AddPage(self._GenerateProtocolSubPage(pObj, obj, configFile))\r
+ else:\r
+ guidArchRootPageDict = {}\r
+ for obj in objs:\r
+ if obj.GetArch() not in guidArchRootPageDict.keys():\r
+ guidArchRoot = doxygen.Page(obj.GetArch(), 'protocol_arch_root_%s' % obj.GetArch())\r
+ pageRoot.AddPage(guidArchRoot)\r
+ guidArchRootPageDict[obj.GetArch()] = guidArchRoot\r
+ guidArchRoot = guidArchRootPageDict[obj.GetArch()]\r
+ guidArchRoot.AddPage(self._GenerateProtocolSubPage(pObj, obj, configFile))\r
+ return [pageRoot]\r
+\r
+ def FindHeaderFileForGuid(self, pObj, name, configFile):\r
+ """\r
+ For declaration header file for GUID/PPI/Protocol.\r
+\r
+ @param pObj package object\r
+ @param name guid/ppi/protocol's name\r
+ @param configFile config file object\r
+\r
+ @return full path of header file and None if not found.\r
+ """\r
+ startPath = pObj.GetFileObj().GetPackageRootPath()\r
+ incPath = os.path.join(startPath, 'Include').replace('\\', '/')\r
+ # if <PackagePath>/include exist, then search header under it.\r
+ if os.path.exists(incPath):\r
+ startPath = incPath\r
+\r
+ for root, dirs, files in os.walk(startPath):\r
+ for dir in dirs:\r
+ if dir.lower() in _ignore_dir:\r
+ dirs.remove(dir)\r
+ for file in files:\r
+ fPath = os.path.join(root, file)\r
+ if not IsCHeaderFile(fPath):\r
+ continue\r
+ try:\r
+ f = open(fPath, 'r')\r
+ lines = f.readlines()\r
+ f.close()\r
+ except IOError:\r
+ self.Log('Fail to open file %s\n' % fPath)\r
+ continue\r
+ for line in lines:\r
+ if line.find(name) != -1 and \\r
+ line.find('extern') != -1:\r
+ return fPath.replace('\\', '/')\r
+ return None\r
+\r
+ def GetPackageModuleList(self, pObj):\r
+ """\r
+ Get all module's INF path under package's root path\r
+ @param pObj package object\r
+ @return arrary of INF full path\r
+ """\r
+ mArray = []\r
+ packPath = pObj.GetFileObj().GetPackageRootPath()\r
+ if not os.path.exists:\r
+ return None\r
+ for root, dirs, files in os.walk(packPath):\r
+ for dir in dirs:\r
+ if dir.lower() in _ignore_dir:\r
+ dirs.remove(dir)\r
+ for file in files:\r
+ if CheckPathPostfix(file, 'inf'):\r
+ fPath = os.path.join(root, file).replace('\\', '/')\r
+ mArray.append(fPath)\r
+ return mArray\r
+\r
+ def GenerateModulePages(self, pObj, configFile):\r
+ """\r
+ Generate sub pages for package's module which is under the package\r
+ root directory.\r
+\r
+ @param pObj package object\r
+ @param configFilf doxygen config file object\r
+ """\r
+ infList = self.GetPackageModuleList(pObj)\r
+ rootPages = []\r
+ libObjs = []\r
+ modObjs = []\r
+ for infpath in infList:\r
+ infObj = inf.INFFile(infpath)\r
+ #infObj = INFFileObject.INFFile (pObj.GetWorkspacePath(),\r
+ # inf)\r
+ if not infObj:\r
+ self.Log('Fail create INF object for %s' % inf)\r
+ continue\r
+ if not infObj.Parse():\r
+ self.Log('Fail to load INF file %s' % inf)\r
+ continue\r
+ if infObj.GetProduceLibraryClass() != None:\r
+ libObjs.append(infObj)\r
+ else:\r
+ modObjs.append(infObj)\r
+\r
+ if len(libObjs) != 0:\r
+ libRootPage = doxygen.Page('Libraries', 'lib_root_page')\r
+ rootPages.append(libRootPage)\r
+ for libInf in libObjs:\r
+ libRootPage.AddPage(self.GenerateModulePage(pObj, libInf, configFile, True))\r
+\r
+ if len(modObjs) != 0:\r
+ modRootPage = doxygen.Page('Modules', 'module_root_page')\r
+ rootPages.append(modRootPage)\r
+ for modInf in modObjs:\r
+ modRootPage.AddPage(self.GenerateModulePage(pObj, modInf, configFile, False))\r
+\r
+ return rootPages\r
+\r
+ def GenerateModulePage(self, pObj, infObj, configFile, isLib):\r
+ """\r
+ Generate page for a module/library.\r
+ @param infObj INF file object for module/library\r
+ @param configFile doxygen config file object\r
+ @param isLib Whether this module is libary\r
+\r
+ @param module doxygen page object\r
+ """\r
+ workspace = pObj.GetWorkspace()\r
+ refDecObjs = []\r
+ for obj in infObj.GetSectionObjectsByName('packages'):\r
+ decObj = dec.DECFile(os.path.join(workspace, obj.GetPath()))\r
+ if not decObj:\r
+ ErrorMsg ('Fail to create pacakge object for %s' % obj.GetPackageName())\r
+ continue\r
+ if not decObj.Parse():\r
+ ErrorMsg ('Fail to load package object for %s' % obj.GetPackageName())\r
+ continue\r
+ refDecObjs.append(decObj)\r
+\r
+ modPage = doxygen.Page('%s' % infObj.GetBaseName(),\r
+ 'module_%s' % infObj.GetBaseName())\r
+ modPage.AddDescription(infObj.GetFileHeader())\r
+\r
+ basicInfSection = doxygen.Section('BasicModuleInformation', 'Basic Module Information')\r
+ desc = "<TABLE>"\r
+ for obj in infObj.GetSectionObjectsByName('defines'):\r
+ key = obj.GetKey()\r
+ value = obj.GetValue()\r
+ if key not in _inf_key_description_mapping_table.keys(): continue\r
+ if key == 'LIBRARY_CLASS' and value.find('|') != -1:\r
+ clsname, types = value.split('|')\r
+ desc += '<TR>'\r
+ desc += '<TD><B>%s</B></TD>' % _inf_key_description_mapping_table[key]\r
+ desc += '<TD>%s</TD>' % clsname\r
+ desc += '</TR>'\r
+\r
+ desc += '<TR>'\r
+ desc += '<TD><B>Supported Module Types</B></TD>'\r
+ desc += '<TD>%s</TD>' % types\r
+ desc += '</TR>'\r
+ else:\r
+ desc += '<TR>'\r
+ desc += '<TD><B>%s</B></TD>' % _inf_key_description_mapping_table[key]\r
+ if key == 'EFI_SPECIFICATION_VERSION' and value == '0x00020000':\r
+ value = '2.0'\r
+ desc += '<TD>%s</TD>' % value\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ basicInfSection.AddDescription(desc)\r
+ modPage.AddSection(basicInfSection)\r
+\r
+ # Add protocol section\r
+ data = []\r
+ for obj in infObj.GetSectionObjectsByName('pcd', self._arch):\r
+ data.append(obj.GetPcdName().strip())\r
+ if len(data) != 0:\r
+ s = doxygen.Section('Pcds', 'Pcds')\r
+ desc = "<TABLE>"\r
+ desc += '<TR><TD><B>PCD Name</B></TD><TD><B>TokenSpace</B></TD><TD><B>Package</B></TD></TR>'\r
+ for item in data:\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % item.split('.')[1]\r
+ desc += '<TD>%s</TD>' % item.split('.')[0]\r
+ pkgbasename = self.SearchPcdPackage(item, workspace, refDecObjs)\r
+ desc += '<TD>%s</TD>' % pkgbasename\r
+ desc += '</TR>'\r
+ desc += "</TABLE>"\r
+ s.AddDescription(desc)\r
+ modPage.AddSection(s)\r
+\r
+ # Add protocol section\r
+ #sects = infObj.GetSectionByString('protocol')\r
+ data = []\r
+ #for sect in sects:\r
+ for obj in infObj.GetSectionObjectsByName('protocol', self._arch):\r
+ data.append(obj.GetName().strip())\r
+ if len(data) != 0:\r
+ s = doxygen.Section('Protocols', 'Protocols')\r
+ desc = "<TABLE>"\r
+ desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'\r
+ for item in data:\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % item\r
+ pkgbasename = self.SearchProtocolPackage(item, workspace, refDecObjs)\r
+ desc += '<TD>%s</TD>' % pkgbasename\r
+ desc += '</TR>'\r
+ desc += "</TABLE>"\r
+ s.AddDescription(desc)\r
+ modPage.AddSection(s)\r
+\r
+ # Add ppi section\r
+ #sects = infObj.GetSectionByString('ppi')\r
+ data = []\r
+ #for sect in sects:\r
+ for obj in infObj.GetSectionObjectsByName('ppi', self._arch):\r
+ data.append(obj.GetName().strip())\r
+ if len(data) != 0:\r
+ s = doxygen.Section('Ppis', 'Ppis')\r
+ desc = "<TABLE>"\r
+ desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'\r
+ for item in data:\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % item\r
+ pkgbasename = self.SearchPpiPackage(item, workspace, refDecObjs)\r
+ desc += '<TD>%s</TD>' % pkgbasename\r
+ desc += '</TR>'\r
+ desc += "</TABLE>"\r
+ s.AddDescription(desc)\r
+ modPage.AddSection(s)\r
+\r
+ # Add guid section\r
+ #sects = infObj.GetSectionByString('guid')\r
+ data = []\r
+ #for sect in sects:\r
+ for obj in infObj.GetSectionObjectsByName('guid', self._arch):\r
+ data.append(obj.GetName().strip())\r
+ if len(data) != 0:\r
+ s = doxygen.Section('Guids', 'Guids')\r
+ desc = "<TABLE>"\r
+ desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'\r
+ for item in data:\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % item\r
+ pkgbasename = self.SearchGuidPackage(item, workspace, refDecObjs)\r
+ desc += '<TD>%s</TD>' % pkgbasename\r
+ desc += '</TR>'\r
+ desc += "</TABLE>"\r
+ s.AddDescription(desc)\r
+ modPage.AddSection(s)\r
+\r
+ section = doxygen.Section('LibraryClasses', 'Library Classes')\r
+ desc = "<TABLE>"\r
+ desc += '<TR><TD><B>Name</B></TD><TD><B>Type</B></TD><TD><B>Package</B></TD><TD><B>Header File</B></TD></TR>'\r
+ if isLib:\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % infObj.GetProduceLibraryClass()\r
+ desc += '<TD>Produce</TD>'\r
+ try:\r
+ pkgname, hPath = self.SearchLibraryClassHeaderFile(infObj.GetProduceLibraryClass(),\r
+ workspace,\r
+ refDecObjs)\r
+ except:\r
+ self.Log ('fail to get package header file for lib class %s' % infObj.GetProduceLibraryClass())\r
+ pkgname = 'NULL'\r
+ hPath = 'NULL'\r
+ desc += '<TD>%s</TD>' % pkgname\r
+ if hPath != "NULL":\r
+ desc += '<TD>\link %s \endlink</TD>' % hPath\r
+ else:\r
+ desc += '<TD>%s</TD>' % hPath\r
+ desc += '</TR>'\r
+ for lcObj in infObj.GetSectionObjectsByName('libraryclasses', self._arch):\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % lcObj.GetClass()\r
+ retarr = self.SearchLibraryClassHeaderFile(lcObj.GetClass(),\r
+ workspace,\r
+ refDecObjs)\r
+ if retarr != None:\r
+ pkgname, hPath = retarr\r
+ else:\r
+ self.Log('Fail find the library class %s definition from module %s dependent package!' % (lcObj.GetClass(), infObj.GetFilename()), 'error')\r
+ pkgname = 'NULL'\r
+ hPath = 'NULL'\r
+ desc += '<TD>Consume</TD>'\r
+ desc += '<TD>%s</TD>' % pkgname\r
+ desc += '<TD>\link %s \endlink</TD>' % hPath\r
+ desc += '</TR>'\r
+ desc += "</TABLE>"\r
+ section.AddDescription(desc)\r
+ modPage.AddSection(section)\r
+\r
+ section = doxygen.Section('SourceFiles', 'Source Files')\r
+ section.AddDescription('<ul>\n')\r
+ for obj in infObj.GetSourceObjects(self._arch, self._tooltag):\r
+ sPath = infObj.GetModuleRootPath()\r
+ sPath = os.path.join(sPath, obj.GetSourcePath()).replace('\\', '/').strip()\r
+ if sPath.lower().endswith('.uni') or sPath.lower().endswith('.s') or sPath.lower().endswith('.asm') or sPath.lower().endswith('.nasm'):\r
+ newPath = self.TranslateUniFile(sPath)\r
+ configFile.AddFile(newPath)\r
+ newPath = newPath[len(pObj.GetWorkspace()) + 1:]\r
+ section.AddDescription('<li> \link %s \endlink </li>' % newPath)\r
+ else:\r
+ self.ProcessSourceFileForInclude(sPath, pObj, configFile, infObj)\r
+ sPath = sPath[len(pObj.GetWorkspace()) + 1:]\r
+ section.AddDescription('<li>\link %s \endlink </li>' % sPath)\r
+ section.AddDescription('</ul>\n')\r
+ modPage.AddSection(section)\r
+\r
+ #sects = infObj.GetSectionByString('depex')\r
+ data = []\r
+ #for sect in sects:\r
+ for obj in infObj.GetSectionObjectsByName('depex'):\r
+ data.append(str(obj))\r
+ if len(data) != 0:\r
+ s = doxygen.Section('DependentSection', 'Module Dependencies')\r
+ s.AddDescription('<br>'.join(data))\r
+ modPage.AddSection(s)\r
+\r
+ return modPage\r
+\r
+ def TranslateUniFile(self, path):\r
+ newpath = path + '.dox'\r
+ #import core.textfile as textfile\r
+ #file = textfile.TextFile(path)\r
+\r
+ try:\r
+ file = open(path, 'rb')\r
+ except (IOError, OSError), msg:\r
+ return None\r
+\r
+ t = file.read()\r
+ file.close()\r
+\r
+ output = '/** @file \n'\r
+ #output = '<html><body>'\r
+ arr = t.split('\r\n')\r
+ for line in arr:\r
+ if line.find('@file') != -1:\r
+ continue\r
+ if line.find('*/') != -1:\r
+ continue\r
+ line = line.strip()\r
+ if line.strip().startswith('/'):\r
+ arr = line.split(' ')\r
+ if len(arr) > 1:\r
+ line = ' '.join(arr[1:])\r
+ else:\r
+ continue\r
+ output += '%s<br>\n' % line\r
+ output += '**/'\r
+\r
+ if os.path.exists(newpath):\r
+ os.remove(newpath)\r
+\r
+ file = open(newpath, "w")\r
+ file.write(output)\r
+ file.close()\r
+ return newpath\r
+\r
+ def SearchPcdPackage(self, pcdname, workspace, decObjs):\r
+ for decObj in decObjs:\r
+ for pcd in decObj.GetSectionObjectsByName('pcd'):\r
+ if pcdname == pcd.GetPcdName():\r
+ return decObj.GetBaseName()\r
+ return None\r
+\r
+ def SearchProtocolPackage(self, protname, workspace, decObjs):\r
+ for decObj in decObjs:\r
+ for proto in decObj.GetSectionObjectsByName('protocol'):\r
+ if protname == proto.GetName():\r
+ return decObj.GetBaseName()\r
+ return None\r
+\r
+ def SearchPpiPackage(self, ppiname, workspace, decObjs):\r
+ for decObj in decObjs:\r
+ for ppi in decObj.GetSectionObjectsByName('ppi'):\r
+ if ppiname == ppi.GetName():\r
+ return decObj.GetBaseName()\r
+ return None\r
+\r
+ def SearchGuidPackage(self, guidname, workspace, decObjs):\r
+ for decObj in decObjs:\r
+ for guid in decObj.GetSectionObjectsByName('guid'):\r
+ if guidname == guid.GetName():\r
+ return decObj.GetBaseName()\r
+ return None\r
+\r
+ def SearchLibraryClassHeaderFile(self, className, workspace, decObjs):\r
+ for decObj in decObjs:\r
+ for cls in decObj.GetSectionObjectsByName('libraryclasses'):\r
+ if cls.GetClassName().strip() == className:\r
+ path = cls.GetHeaderFile().strip()\r
+ path = os.path.join(decObj.GetPackageRootPath(), path)\r
+ path = path[len(workspace) + 1:]\r
+ return decObj.GetBaseName(), path.replace('\\', '/')\r
+\r
+ return None\r
+\r
+ def _ConvertPathToDoxygen(self, path, pObj):\r
+ pRootPath = pObj.GetWorkspace()\r
+ path = path[len(pRootPath) + 1:]\r
+ return path.replace('\\', '/')\r
+\r
+def IsCHeaderFile(path):\r
+ return CheckPathPostfix(path, 'h')\r
+\r
+def CheckPathPostfix(path, str):\r
+ index = path.rfind('.')\r
+ if index == -1:\r
+ return False\r
+ if path[index + 1:].lower() == str.lower():\r
+ return True\r
+ return False\r
--- /dev/null
+## @file\r
+#\r
+# This file produce action class to generate doxygen document for edk2 codebase.\r
+# The action classes are shared by GUI and command line tools.\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+import plugins.EdkPlugins.basemodel.doxygen as doxygen\r
+import os\r
+try:\r
+ import wx\r
+ gInGui = True\r
+except:\r
+ gInGui = False\r
+import re\r
+import plugins.EdkPlugins.edk2.model.inf as inf\r
+import plugins.EdkPlugins.edk2.model.dec as dec\r
+from plugins.EdkPlugins.basemodel.message import *\r
+\r
+_ignore_dir = ['.svn', '_svn', 'cvs']\r
+_inf_key_description_mapping_table = {\r
+ 'INF_VERSION':'Version of INF file specification',\r
+ #'BASE_NAME':'Module Name',\r
+ 'FILE_GUID':'Module Guid',\r
+ 'MODULE_TYPE': 'Module Type',\r
+ 'VERSION_STRING': 'Module Version',\r
+ 'LIBRARY_CLASS': 'Produced Library Class',\r
+ 'EFI_SPECIFICATION_VERSION': 'UEFI Specification Version',\r
+ 'PI_SPECIFICATION_VERSION': 'PI Specification Version',\r
+ 'ENTRY_POINT': 'Module Entry Point Function',\r
+ 'CONSTRUCTOR': 'Library Constructor Function'\r
+}\r
+\r
+_dec_key_description_mapping_table = {\r
+ 'DEC_SPECIFICATION': 'Version of DEC file specification',\r
+ 'PACKAGE_GUID': 'Package Guid'\r
+}\r
+class DoxygenAction:\r
+ """This is base class for all doxygen action.\r
+ """\r
+\r
+ def __init__(self, doxPath, chmPath, outputPath, projname, mode='html', log=None, verbose=False):\r
+ """Constructor function.\r
+ @param doxPath the obosolution path of doxygen execute file.\r
+ @param outputPath the obosolution output path.\r
+ @param log log function for output message\r
+ """\r
+ self._doxPath = doxPath\r
+ self._chmPath = chmPath\r
+ self._outputPath = outputPath\r
+ self._projname = projname\r
+ self._configFile = None # doxygen config file is used by doxygen exe file\r
+ self._indexPageFile = None # doxygen page file for index page.\r
+ self._log = log\r
+ self._mode = mode\r
+ self._verbose = verbose\r
+ self._doxygenCallback = None\r
+ self._chmCallback = None\r
+\r
+ def Log(self, message, level='info'):\r
+ if self._log != None:\r
+ self._log(message, level)\r
+\r
+ def IsVerbose(self):\r
+ return self._verbose\r
+\r
+ def Generate(self):\r
+ """Generate interface called by outer directly"""\r
+ self.Log(">>>>>> Start generate doxygen document for %s... Zzz....\n" % self._projname)\r
+\r
+ # create doxygen config file at first\r
+ self._configFile = doxygen.DoxygenConfigFile()\r
+ self._configFile.SetOutputDir(self._outputPath)\r
+\r
+ self._configFile.SetWarningFilePath(os.path.join(self._outputPath, 'warning.txt'))\r
+ if self._mode.lower() == 'html':\r
+ self._configFile.SetHtmlMode()\r
+ else:\r
+ self._configFile.SetChmMode()\r
+\r
+ self.Log(" >>>>>> Initialize doxygen config file...Zzz...\n")\r
+ self.InitializeConfigFile()\r
+\r
+ self.Log(" >>>>>> Generate doxygen index page file...Zzz...\n")\r
+ indexPagePath = self.GenerateIndexPage()\r
+ if indexPagePath == None:\r
+ self.Log("Fail to generate index page!\n", 'error')\r
+ return False\r
+ else:\r
+ self.Log("Success to create doxygen index page file %s \n" % indexPagePath)\r
+\r
+ # Add index page doxygen file to file list.\r
+ self._configFile.AddFile(indexPagePath)\r
+\r
+ # save config file to output path\r
+ configFilePath = os.path.join(self._outputPath, self._projname + '.doxygen_config')\r
+ self._configFile.Generate(configFilePath)\r
+ self.Log(" <<<<<< Success Save doxygen config file to %s...\n" % configFilePath)\r
+\r
+ # launch doxygen tool to generate document\r
+ if self._doxygenCallback != None:\r
+ self.Log(" >>>>>> Start doxygen process...Zzz...\n")\r
+ if not self._doxygenCallback(self._doxPath, configFilePath):\r
+ return False\r
+ else:\r
+ self.Log("Fail to create doxygen process!", 'error')\r
+ return False\r
+\r
+ return True\r
+\r
+ def InitializeConfigFile(self):\r
+ """Initialize config setting for doxygen project. It will be invoked after config file\r
+ object is created. Inherited class should implement it.\r
+ """\r
+\r
+ def GenerateIndexPage(self):\r
+ """Generate doxygen index page. Inherited class should implement it."""\r
+ return None\r
+\r
+ def RegisterCallbackDoxygenProcess(self, callback):\r
+ self._doxygenCallback = callback\r
+\r
+ def RegisterCallbackCHMProcess(self, callback):\r
+ self._chmCallback = callback\r
+\r
+class PlatformDocumentAction(DoxygenAction):\r
+ """Generate platform doxygen document, will be implement at future."""\r
+\r
+class PackageDocumentAction(DoxygenAction):\r
+ """Generate package reference document"""\r
+\r
+ def __init__(self, doxPath, chmPath, outputPath, pObj, mode='html', log=None, arch=None, tooltag=None,\r
+ macros=[], onlyInclude=False, verbose=False):\r
+ DoxygenAction.__init__(self, doxPath, chmPath, outputPath, pObj.GetName(), mode, log, verbose)\r
+ self._pObj = pObj\r
+ self._arch = arch\r
+ self._tooltag = tooltag\r
+ self._macros = macros\r
+ self._onlyIncludeDocument = onlyInclude\r
+\r
+ def InitializeConfigFile(self):\r
+ if self._arch == 'IA32':\r
+ self._configFile.AddPreDefined('MDE_CPU_IA32')\r
+ elif self._arch == 'X64':\r
+ self._configFile.AddPreDefined('MDE_CPU_X64')\r
+ elif self._arch == 'IPF':\r
+ self._configFile.AddPreDefined('MDE_CPU_IPF')\r
+ elif self._arch == 'EBC':\r
+ self._configFile.AddPreDefined('MDE_CPU_EBC')\r
+ else:\r
+ self._arch = None\r
+ self._configFile.AddPreDefined('MDE_CPU_IA32')\r
+ self._configFile.AddPreDefined('MDE_CPU_X64')\r
+ self._configFile.AddPreDefined('MDE_CPU_IPF')\r
+ self._configFile.AddPreDefined('MDE_CPU_EBC')\r
+ self._configFile.AddPreDefined('MDE_CPU_ARM')\r
+\r
+ for macro in self._macros:\r
+ self._configFile.AddPreDefined(macro)\r
+\r
+ namestr = self._pObj.GetName()\r
+ if self._arch != None:\r
+ namestr += '[%s]' % self._arch\r
+ if self._tooltag != None:\r
+ namestr += '[%s]' % self._tooltag\r
+ self._configFile.SetProjectName(namestr)\r
+ self._configFile.SetStripPath(self._pObj.GetWorkspace())\r
+ self._configFile.SetProjectVersion(self._pObj.GetFileObj().GetVersion())\r
+ self._configFile.AddPattern('*.decdoxygen')\r
+\r
+ if self._tooltag.lower() == 'msft':\r
+ self._configFile.AddPreDefined('_MSC_EXTENSIONS')\r
+ elif self._tooltag.lower() == 'gnu':\r
+ self._configFile.AddPreDefined('__GNUC__')\r
+ elif self._tooltag.lower() == 'intel':\r
+ self._configFile.AddPreDefined('__INTEL_COMPILER')\r
+ else:\r
+ self._tooltag = None\r
+ self._configFile.AddPreDefined('_MSC_EXTENSIONS')\r
+ self._configFile.AddPreDefined('__GNUC__')\r
+ self._configFile.AddPreDefined('__INTEL_COMPILER')\r
+\r
+ self._configFile.AddPreDefined('ASM_PFX= ')\r
+ self._configFile.AddPreDefined('OPTIONAL= ')\r
+\r
+ def GenerateIndexPage(self):\r
+ """Generate doxygen index page. Inherited class should implement it."""\r
+ fObj = self._pObj.GetFileObj()\r
+ pdObj = doxygen.DoxygenFile('%s Package Document' % self._pObj.GetName(),\r
+ '%s.decdoxygen' % self._pObj.GetFilename())\r
+ self._configFile.AddFile(pdObj.GetFilename())\r
+ pdObj.AddDescription(fObj.GetFileHeader())\r
+\r
+ defSection = fObj.GetSectionByName('defines')[0]\r
+ baseSection = doxygen.Section('PackageBasicInformation', 'Package Basic Information')\r
+ descr = '<TABLE>'\r
+ for obj in defSection.GetObjects():\r
+ if obj.GetKey() in _dec_key_description_mapping_table.keys():\r
+ descr += '<TR>'\r
+ descr += '<TD><B>%s</B></TD>' % _dec_key_description_mapping_table[obj.GetKey()]\r
+ descr += '<TD>%s</TD>' % obj.GetValue()\r
+ descr += '</TR>'\r
+ descr += '</TABLE><br>'\r
+ baseSection.AddDescription(descr)\r
+ pdObj.AddSection(baseSection)\r
+\r
+ knownIssueSection = doxygen.Section('Known_Issue_section', 'Known Issue')\r
+ knownIssueSection.AddDescription('<ul>')\r
+ knownIssueSection.AddDescription('<li> OPTIONAL macro for function parameter can not be dealed with doxygen, so it disapear in this document! </li>')\r
+ knownIssueSection.AddDescription('</ul>')\r
+ pdObj.AddSection(knownIssueSection)\r
+\r
+ self.AddAllIncludeFiles(self._pObj, self._configFile)\r
+ pages = self.GenerateIncludesSubPage(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ pages = self.GenerateLibraryClassesSubPage(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ pages = self.GeneratePcdSubPages(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ pages = self.GenerateGuidSubPages(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ pages = self.GeneratePpiSubPages(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ pages = self.GenerateProtocolSubPages(self._pObj, self._configFile)\r
+ if len(pages) != 0:\r
+ pdObj.AddPages(pages)\r
+ if not self._onlyIncludeDocument:\r
+ pdObj.AddPages(self.GenerateModulePages(self._pObj, self._configFile))\r
+\r
+ pdObj.Save()\r
+ return pdObj.GetFilename()\r
+\r
+ def GenerateIncludesSubPage(self, pObj, configFile):\r
+ # by default add following path as include path to config file\r
+ pkpath = pObj.GetFileObj().GetPackageRootPath()\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include'))\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Library'))\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Protocol'))\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Ppi'))\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Guid'))\r
+ configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'IndustryStandard'))\r
+\r
+ rootArray = []\r
+ pageRoot = doxygen.Page("Public Includes", "%s_public_includes" % pObj.GetName())\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('includes')\r
+ if len(objs) == 0: return []\r
+\r
+ for obj in objs:\r
+ # Add path to include path\r
+ path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetPath())\r
+ configFile.AddIncludePath(path)\r
+\r
+ # only list common folder's include file\r
+ if obj.GetArch().lower() != 'common':\r
+ continue\r
+\r
+ bNeedAddIncludePage = False\r
+ topPage = doxygen.Page(self._ConvertPathToDoxygen(path, pObj), 'public_include_top')\r
+\r
+ topPage.AddDescription('<ul>\n')\r
+ for file in os.listdir(path):\r
+ if file.lower() in _ignore_dir: continue\r
+ fullpath = os.path.join(path, file)\r
+ if os.path.isfile(fullpath):\r
+ self.ProcessSourceFileForInclude(fullpath, pObj, configFile)\r
+ topPage.AddDescription('<li> \link %s\endlink </li>\n' % self._ConvertPathToDoxygen(fullpath, pObj))\r
+ else:\r
+ if file.lower() in ['library', 'protocol', 'guid', 'ppi', 'ia32', 'x64', 'ipf', 'ebc', 'arm', 'pi', 'uefi', 'aarch64']:\r
+ continue\r
+ bNeedAddSubPage = False\r
+ subpage = doxygen.Page(self._ConvertPathToDoxygen(fullpath, pObj), 'public_include_%s' % file)\r
+ subpage.AddDescription('<ul>\n')\r
+ for subfile in os.listdir(fullpath):\r
+ if subfile.lower() in _ignore_dir: continue\r
+ bNeedAddSubPage = True\r
+ subfullpath = os.path.join(fullpath, subfile)\r
+ self.ProcessSourceFileForInclude(subfullpath, pObj, configFile)\r
+ subpage.AddDescription('<li> \link %s \endlink </li>\n' % self._ConvertPathToDoxygen(subfullpath, pObj))\r
+ subpage.AddDescription('</ul>\n')\r
+ if bNeedAddSubPage:\r
+ bNeedAddIncludePage = True\r
+ pageRoot.AddPage(subpage)\r
+ topPage.AddDescription('</ul>\n')\r
+ if bNeedAddIncludePage:\r
+ pageRoot.AddPage(topPage)\r
+\r
+ if pageRoot.GetSubpageCount() != 0:\r
+ return [pageRoot]\r
+ else:\r
+ return []\r
+\r
+ def GenerateLibraryClassesSubPage(self, pObj, configFile):\r
+ """\r
+ Generate sub page for library class for package.\r
+ One DEC file maybe contains many library class sections\r
+ for different architecture.\r
+\r
+ @param fObj DEC file object.\r
+ """\r
+ rootArray = []\r
+ pageRoot = doxygen.Page("Library Class", "%s_libraryclass" % pObj.GetName())\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('libraryclass', self._arch)\r
+ if len(objs) == 0: return []\r
+\r
+ if self._arch != None:\r
+ for obj in objs:\r
+ classPage = doxygen.Page(obj.GetClassName(),\r
+ "lc_%s" % obj.GetClassName())\r
+ comments = obj.GetComment()\r
+ if len(comments) != 0:\r
+ classPage.AddDescription('<br>\n'.join(comments) + '<br>\n')\r
+ pageRoot.AddPage(classPage)\r
+ path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+ path = path[len(pObj.GetWorkspace()) + 1:]\r
+ if len(comments) == 0:\r
+ classPage.AddDescription('\copydoc %s<p>' % obj.GetHeaderFile())\r
+ section = doxygen.Section('ref', 'Refer to Header File')\r
+ section.AddDescription('\link %s\n' % obj.GetHeaderFile())\r
+ section.AddDescription(' \endlink<p>\n')\r
+ classPage.AddSection(section)\r
+ fullPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+ self.ProcessSourceFileForInclude(fullPath, pObj, configFile)\r
+ else:\r
+ archPageDict = {}\r
+ for obj in objs:\r
+ if obj.GetArch() not in archPageDict.keys():\r
+ archPageDict[obj.GetArch()] = doxygen.Page(obj.GetArch(),\r
+ 'lc_%s' % obj.GetArch())\r
+ pageRoot.AddPage(archPageDict[obj.GetArch()])\r
+ subArchRoot = archPageDict[obj.GetArch()]\r
+ classPage = doxygen.Page(obj.GetClassName(),\r
+ "lc_%s" % obj.GetClassName())\r
+ comments = obj.GetComment()\r
+ if len(comments) != 0:\r
+ classPage.AddDescription('<br>\n'.join(comments) + '<br>\n')\r
+ subArchRoot.AddPage(classPage)\r
+ path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+ path = path[len(pObj.GetWorkspace()) + 1:]\r
+ if len(comments) == 0:\r
+ classPage.AddDescription('\copydoc %s<p>' % obj.GetHeaderFile())\r
+ section = doxygen.Section('ref', 'Refer to Header File')\r
+ section.AddDescription('\link %s\n' % obj.GetHeaderFile())\r
+ section.AddDescription(' \endlink<p>\n')\r
+ classPage.AddSection(section)\r
+ fullPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+\r
+ self.ProcessSourceFileForInclude(fullPath, pObj, configFile)\r
+ rootArray.append(pageRoot)\r
+ return rootArray\r
+\r
+ def ProcessSourceFileForInclude(self, path, pObj, configFile, infObj=None):\r
+ """\r
+ @param path the analysising file full path\r
+ @param pObj package object\r
+ @param configFile doxygen config file.\r
+ """\r
+\r
+ if gInGui:\r
+ wx.Yield()\r
+ if not os.path.exists(path):\r
+ ErrorMsg('Source file path %s does not exist!' % path)\r
+ return\r
+\r
+ if configFile.FileExists(path):\r
+ return\r
+\r
+ try:\r
+ f = open(path, 'r')\r
+ lines = f.readlines()\r
+ f.close()\r
+ except IOError:\r
+ ErrorMsg('Fail to open file %s' % path)\r
+ return\r
+\r
+ configFile.AddFile(path)\r
+ return\r
+ no = 0\r
+ for no in xrange(len(lines)):\r
+ if len(lines[no].strip()) == 0:\r
+ continue\r
+ if lines[no].strip()[:2] in ['##', '//', '/*', '*/']:\r
+ continue\r
+ index = lines[no].lower().find('include')\r
+ #mo = IncludePattern.finditer(lines[no].lower())\r
+ mo = re.match(r"^#\s*include\s+[<\"]([\\/\w.]+)[>\"]$", lines[no].strip().lower())\r
+ if not mo:\r
+ continue\r
+ mo = re.match(r"^[#\w\s]+[<\"]([\\/\w.]+)[>\"]$", lines[no].strip())\r
+ filePath = mo.groups()[0]\r
+\r
+ if filePath == None or len(filePath) == 0:\r
+ continue\r
+\r
+ # find header file in module's path firstly.\r
+ fullPath = None\r
+\r
+ if os.path.exists(os.path.join(os.path.dirname(path), filePath)):\r
+ # Find the file in current directory\r
+ fullPath = os.path.join(os.path.dirname(path), filePath).replace('\\', '/')\r
+ else:\r
+ # find in depedent package's include path\r
+ incObjs = pObj.GetFileObj().GetSectionObjectsByName('includes')\r
+ for incObj in incObjs:\r
+ incPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), incObj.GetPath()).strip()\r
+ incPath = os.path.realpath(os.path.join(incPath, filePath))\r
+ if os.path.exists(incPath):\r
+ fullPath = incPath\r
+ break\r
+ if infObj != None:\r
+ pkgInfObjs = infObj.GetSectionObjectsByName('packages')\r
+ for obj in pkgInfObjs:\r
+ decObj = dec.DECFile(os.path.join(pObj.GetWorkspace(), obj.GetPath()))\r
+ if not decObj:\r
+ ErrorMsg ('Fail to create pacakge object for %s' % obj.GetPackageName())\r
+ continue\r
+ if not decObj.Parse():\r
+ ErrorMsg ('Fail to load package object for %s' % obj.GetPackageName())\r
+ continue\r
+ incObjs = decObj.GetSectionObjectsByName('includes')\r
+ for incObj in incObjs:\r
+ incPath = os.path.join(decObj.GetPackageRootPath(), incObj.GetPath()).replace('\\', '/')\r
+ if os.path.exists(os.path.join(incPath, filePath)):\r
+ fullPath = os.path.join(os.path.join(incPath, filePath))\r
+ break\r
+ if fullPath != None:\r
+ break\r
+\r
+ if fullPath == None and self.IsVerbose():\r
+ self.Log('Can not resolve header file %s for file %s in package %s\n' % (filePath, path, pObj.GetFileObj().GetFilename()), 'error')\r
+ return\r
+ else:\r
+ fullPath = fullPath.replace('\\', '/')\r
+ if self.IsVerbose():\r
+ self.Log('Preprocessing: Add include file %s for file %s\n' % (fullPath, path))\r
+ #LogMsg ('Preprocessing: Add include file %s for file %s' % (fullPath, path))\r
+ self.ProcessSourceFileForInclude(fullPath, pObj, configFile, infObj)\r
+\r
+ def AddAllIncludeFiles(self, pObj, configFile):\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('includes')\r
+ for obj in objs:\r
+ incPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetPath())\r
+ for root, dirs, files in os.walk(incPath):\r
+ for dir in dirs:\r
+ if dir.lower() in _ignore_dir:\r
+ dirs.remove(dir)\r
+ for file in files:\r
+ path = os.path.normpath(os.path.join(root, file))\r
+ configFile.AddFile(path.replace('/', '\\'))\r
+\r
+ def GeneratePcdSubPages(self, pObj, configFile):\r
+ """\r
+ Generate sub pages for package's PCD definition.\r
+ @param pObj package object\r
+ @param configFile config file object\r
+ """\r
+ rootArray = []\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('pcd')\r
+ if len(objs) == 0:\r
+ return []\r
+\r
+ pcdRootPage = doxygen.Page('PCD', 'pcd_root_page')\r
+ typeRootPageDict = {}\r
+ typeArchRootPageDict = {}\r
+ for obj in objs:\r
+ if obj.GetPcdType() not in typeRootPageDict.keys():\r
+ typeRootPageDict[obj.GetPcdType()] = doxygen.Page(obj.GetPcdType(), 'pcd_%s_root_page' % obj.GetPcdType())\r
+ pcdRootPage.AddPage(typeRootPageDict[obj.GetPcdType()])\r
+ typeRoot = typeRootPageDict[obj.GetPcdType()]\r
+ if self._arch != None:\r
+ pcdPage = doxygen.Page('%s' % obj.GetPcdName(),\r
+ 'pcd_%s_%s_%s' % (obj.GetPcdType(), obj.GetArch(), obj.GetPcdName().split('.')[1]))\r
+ pcdPage.AddDescription('<br>\n'.join(obj.GetComment()) + '<br>\n')\r
+ section = doxygen.Section('PCDinformation', 'PCD Information')\r
+ desc = '<TABLE>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>Name</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Token Space</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Token number</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Data Type</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Default Value</CAPTION></TD>'\r
+ desc += '</TR>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[1]\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[0]\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdToken()\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdDataType()\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdValue()\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ section.AddDescription(desc)\r
+ pcdPage.AddSection(section)\r
+ typeRoot.AddPage(pcdPage)\r
+ else:\r
+ keystr = obj.GetPcdType() + obj.GetArch()\r
+ if keystr not in typeArchRootPageDict.keys():\r
+ typeArchRootPage = doxygen.Page(obj.GetArch(), 'pcd_%s_%s_root_page' % (obj.GetPcdType(), obj.GetArch()))\r
+ typeArchRootPageDict[keystr] = typeArchRootPage\r
+ typeRoot.AddPage(typeArchRootPage)\r
+ typeArchRoot = typeArchRootPageDict[keystr]\r
+ pcdPage = doxygen.Page('%s' % obj.GetPcdName(),\r
+ 'pcd_%s_%s_%s' % (obj.GetPcdType(), obj.GetArch(), obj.GetPcdName().split('.')[1]))\r
+ pcdPage.AddDescription('<br>\n'.join(obj.GetComment()) + '<br>\n')\r
+ section = doxygen.Section('PCDinformation', 'PCD Information')\r
+ desc = '<TABLE>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>Name</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Token Space</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Token number</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Data Type</CAPTION></TD>'\r
+ desc += '<TD><CAPTION>Default Value</CAPTION></TD>'\r
+ desc += '</TR>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[1]\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[0]\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdToken()\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdDataType()\r
+ desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdValue()\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ section.AddDescription(desc)\r
+ pcdPage.AddSection(section)\r
+ typeArchRoot.AddPage(pcdPage)\r
+ return [pcdRootPage]\r
+\r
+ def _GenerateGuidSubPage(self, pObj, obj, configFile):\r
+ guidPage = doxygen.Page('%s' % obj.GetName(),\r
+ 'guid_%s_%s' % (obj.GetArch(), obj.GetName()))\r
+ comments = obj.GetComment()\r
+ if len(comments) != 0:\r
+ guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')\r
+ section = doxygen.Section('BasicGuidInfo', 'GUID Information')\r
+ desc = '<TABLE>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>GUID\'s Guid Name</CAPTION></TD><TD><CAPTION>GUID\'s Guid</CAPTION></TD>'\r
+ desc += '</TR>'\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % obj.GetName()\r
+ desc += '<TD>%s</TD>' % obj.GetGuid()\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ section.AddDescription(desc)\r
+ guidPage.AddSection(section)\r
+ refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)\r
+ if refFile:\r
+ relPath = refFile[len(pObj.GetWorkspace()) + 1:]\r
+ if len(comments) == 0:\r
+ guidPage.AddDescription(' \\copydoc %s <br>' % relPath)\r
+\r
+ section = doxygen.Section('ref', 'Refer to Header File')\r
+ section.AddDescription('\link %s\n' % relPath)\r
+ section.AddDescription('\endlink\n')\r
+ self.ProcessSourceFileForInclude(refFile, pObj, configFile)\r
+ guidPage.AddSection(section)\r
+ return guidPage\r
+\r
+ def GenerateGuidSubPages(self, pObj, configFile):\r
+ """\r
+ Generate sub pages for package's GUID definition.\r
+ @param pObj package object\r
+ @param configFilf doxygen config file object\r
+ """\r
+ pageRoot = doxygen.Page('GUID', 'guid_root_page')\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('guids', self._arch)\r
+ if len(objs) == 0: return []\r
+ if self._arch != None:\r
+ for obj in objs:\r
+ pageRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, configFile))\r
+ else:\r
+ guidArchRootPageDict = {}\r
+ for obj in objs:\r
+ if obj.GetArch() not in guidArchRootPageDict.keys():\r
+ guidArchRoot = doxygen.Page(obj.GetArch(), 'guid_arch_root_%s' % obj.GetArch())\r
+ pageRoot.AddPage(guidArchRoot)\r
+ guidArchRootPageDict[obj.GetArch()] = guidArchRoot\r
+ guidArchRoot = guidArchRootPageDict[obj.GetArch()]\r
+ guidArchRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, configFile))\r
+ return [pageRoot]\r
+\r
+ def _GeneratePpiSubPage(self, pObj, obj, configFile):\r
+ guidPage = doxygen.Page(obj.GetName(), 'ppi_page_%s' % obj.GetName())\r
+ comments = obj.GetComment()\r
+ if len(comments) != 0:\r
+ guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')\r
+ section = doxygen.Section('BasicPpiInfo', 'PPI Information')\r
+ desc = '<TABLE>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>PPI\'s Guid Name</CAPTION></TD><TD><CAPTION>PPI\'s Guid</CAPTION></TD>'\r
+ desc += '</TR>'\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % obj.GetName()\r
+ desc += '<TD>%s</TD>' % obj.GetGuid()\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ section.AddDescription(desc)\r
+ guidPage.AddSection(section)\r
+ refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)\r
+ if refFile:\r
+ relPath = refFile[len(pObj.GetWorkspace()) + 1:]\r
+ if len(comments) == 0:\r
+ guidPage.AddDescription(' \\copydoc %s <br>' % relPath)\r
+ section = doxygen.Section('ref', 'Refer to Header File')\r
+ section.AddDescription('\link %s\n' % relPath)\r
+ section.AddDescription('\endlink\n')\r
+ self.ProcessSourceFileForInclude(refFile, pObj, configFile)\r
+ guidPage.AddSection(section)\r
+\r
+ return guidPage\r
+\r
+ def GeneratePpiSubPages(self, pObj, configFile):\r
+ """\r
+ Generate sub pages for package's GUID definition.\r
+ @param pObj package object\r
+ @param configFilf doxygen config file object\r
+ """\r
+ pageRoot = doxygen.Page('PPI', 'ppi_root_page')\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('ppis', self._arch)\r
+ if len(objs) == 0: return []\r
+ if self._arch != None:\r
+ for obj in objs:\r
+ pageRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, configFile))\r
+ else:\r
+ guidArchRootPageDict = {}\r
+ for obj in objs:\r
+ if obj.GetArch() not in guidArchRootPageDict.keys():\r
+ guidArchRoot = doxygen.Page(obj.GetArch(), 'ppi_arch_root_%s' % obj.GetArch())\r
+ pageRoot.AddPage(guidArchRoot)\r
+ guidArchRootPageDict[obj.GetArch()] = guidArchRoot\r
+ guidArchRoot = guidArchRootPageDict[obj.GetArch()]\r
+ guidArchRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, configFile))\r
+ return [pageRoot]\r
+\r
+ def _GenerateProtocolSubPage(self, pObj, obj, configFile):\r
+ guidPage = doxygen.Page(obj.GetName(), 'protocol_page_%s' % obj.GetName())\r
+ comments = obj.GetComment()\r
+ if len(comments) != 0:\r
+ guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')\r
+ section = doxygen.Section('BasicProtocolInfo', 'PROTOCOL Information')\r
+ desc = '<TABLE>'\r
+ desc += '<TR>'\r
+ desc += '<TD><CAPTION>PROTOCOL\'s Guid Name</CAPTION></TD><TD><CAPTION>PROTOCOL\'s Guid</CAPTION></TD>'\r
+ desc += '</TR>'\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % obj.GetName()\r
+ desc += '<TD>%s</TD>' % obj.GetGuid()\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ section.AddDescription(desc)\r
+ guidPage.AddSection(section)\r
+\r
+ refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)\r
+ if refFile:\r
+ relPath = refFile[len(pObj.GetWorkspace()) + 1:]\r
+ if len(comments) == 0:\r
+ guidPage.AddDescription(' \\copydoc %s <br>' % relPath)\r
+ section = doxygen.Section('ref', 'Refer to Header File')\r
+ section.AddDescription('\link %s\n' % relPath)\r
+ section.AddDescription('\endlink\n')\r
+ self.ProcessSourceFileForInclude(refFile, pObj, configFile)\r
+ guidPage.AddSection(section)\r
+\r
+ return guidPage\r
+\r
+ def GenerateProtocolSubPages(self, pObj, configFile):\r
+ """\r
+ Generate sub pages for package's GUID definition.\r
+ @param pObj package object\r
+ @param configFilf doxygen config file object\r
+ """\r
+ pageRoot = doxygen.Page('PROTOCOL', 'protocol_root_page')\r
+ objs = pObj.GetFileObj().GetSectionObjectsByName('protocols', self._arch)\r
+ if len(objs) == 0: return []\r
+ if self._arch != None:\r
+ for obj in objs:\r
+ pageRoot.AddPage(self._GenerateProtocolSubPage(pObj, obj, configFile))\r
+ else:\r
+ guidArchRootPageDict = {}\r
+ for obj in objs:\r
+ if obj.GetArch() not in guidArchRootPageDict.keys():\r
+ guidArchRoot = doxygen.Page(obj.GetArch(), 'protocol_arch_root_%s' % obj.GetArch())\r
+ pageRoot.AddPage(guidArchRoot)\r
+ guidArchRootPageDict[obj.GetArch()] = guidArchRoot\r
+ guidArchRoot = guidArchRootPageDict[obj.GetArch()]\r
+ guidArchRoot.AddPage(self._GenerateProtocolSubPage(pObj, obj, configFile))\r
+ return [pageRoot]\r
+\r
+ def FindHeaderFileForGuid(self, pObj, name, configFile):\r
+ """\r
+ For declaration header file for GUID/PPI/Protocol.\r
+\r
+ @param pObj package object\r
+ @param name guid/ppi/protocol's name\r
+ @param configFile config file object\r
+\r
+ @return full path of header file and None if not found.\r
+ """\r
+ startPath = pObj.GetFileObj().GetPackageRootPath()\r
+ incPath = os.path.join(startPath, 'Include').replace('\\', '/')\r
+ # if <PackagePath>/include exist, then search header under it.\r
+ if os.path.exists(incPath):\r
+ startPath = incPath\r
+\r
+ for root, dirs, files in os.walk(startPath):\r
+ for dir in dirs:\r
+ if dir.lower() in _ignore_dir:\r
+ dirs.remove(dir)\r
+ for file in files:\r
+ fPath = os.path.join(root, file)\r
+ if not IsCHeaderFile(fPath):\r
+ continue\r
+ try:\r
+ f = open(fPath, 'r')\r
+ lines = f.readlines()\r
+ f.close()\r
+ except IOError:\r
+ self.Log('Fail to open file %s\n' % fPath)\r
+ continue\r
+ for line in lines:\r
+ if line.find(name) != -1 and \\r
+ line.find('extern') != -1:\r
+ return fPath.replace('\\', '/')\r
+ return None\r
+\r
+ def GetPackageModuleList(self, pObj):\r
+ """\r
+ Get all module's INF path under package's root path\r
+ @param pObj package object\r
+ @return arrary of INF full path\r
+ """\r
+ mArray = []\r
+ packPath = pObj.GetFileObj().GetPackageRootPath()\r
+ if not os.path.exists:\r
+ return None\r
+ for root, dirs, files in os.walk(packPath):\r
+ for dir in dirs:\r
+ if dir.lower() in _ignore_dir:\r
+ dirs.remove(dir)\r
+ for file in files:\r
+ if CheckPathPostfix(file, 'inf'):\r
+ fPath = os.path.join(root, file).replace('\\', '/')\r
+ mArray.append(fPath)\r
+ return mArray\r
+\r
+ def GenerateModulePages(self, pObj, configFile):\r
+ """\r
+ Generate sub pages for package's module which is under the package\r
+ root directory.\r
+\r
+ @param pObj package object\r
+ @param configFilf doxygen config file object\r
+ """\r
+ infList = self.GetPackageModuleList(pObj)\r
+ rootPages = []\r
+ libObjs = []\r
+ modObjs = []\r
+ for infpath in infList:\r
+ infObj = inf.INFFile(infpath)\r
+ #infObj = INFFileObject.INFFile (pObj.GetWorkspacePath(),\r
+ # inf)\r
+ if not infObj:\r
+ self.Log('Fail create INF object for %s' % inf)\r
+ continue\r
+ if not infObj.Parse():\r
+ self.Log('Fail to load INF file %s' % inf)\r
+ continue\r
+ if infObj.GetProduceLibraryClass() != None:\r
+ libObjs.append(infObj)\r
+ else:\r
+ modObjs.append(infObj)\r
+\r
+ if len(libObjs) != 0:\r
+ libRootPage = doxygen.Page('Libraries', 'lib_root_page')\r
+ rootPages.append(libRootPage)\r
+ for libInf in libObjs:\r
+ libRootPage.AddPage(self.GenerateModulePage(pObj, libInf, configFile, True))\r
+\r
+ if len(modObjs) != 0:\r
+ modRootPage = doxygen.Page('Modules', 'module_root_page')\r
+ rootPages.append(modRootPage)\r
+ for modInf in modObjs:\r
+ modRootPage.AddPage(self.GenerateModulePage(pObj, modInf, configFile, False))\r
+\r
+ return rootPages\r
+\r
+ def GenerateModulePage(self, pObj, infObj, configFile, isLib):\r
+ """\r
+ Generate page for a module/library.\r
+ @param infObj INF file object for module/library\r
+ @param configFile doxygen config file object\r
+ @param isLib Whether this module is libary\r
+\r
+ @param module doxygen page object\r
+ """\r
+ workspace = pObj.GetWorkspace()\r
+ refDecObjs = []\r
+ for obj in infObj.GetSectionObjectsByName('packages'):\r
+ decObj = dec.DECFile(os.path.join(workspace, obj.GetPath()))\r
+ if not decObj:\r
+ ErrorMsg ('Fail to create pacakge object for %s' % obj.GetPackageName())\r
+ continue\r
+ if not decObj.Parse():\r
+ ErrorMsg ('Fail to load package object for %s' % obj.GetPackageName())\r
+ continue\r
+ refDecObjs.append(decObj)\r
+\r
+ modPage = doxygen.Page('%s' % infObj.GetBaseName(),\r
+ 'module_%s' % infObj.GetBaseName())\r
+ modPage.AddDescription(infObj.GetFileHeader())\r
+\r
+ basicInfSection = doxygen.Section('BasicModuleInformation', 'Basic Module Information')\r
+ desc = "<TABLE>"\r
+ for obj in infObj.GetSectionObjectsByName('defines'):\r
+ key = obj.GetKey()\r
+ value = obj.GetValue()\r
+ if key not in _inf_key_description_mapping_table.keys(): continue\r
+ if key == 'LIBRARY_CLASS' and value.find('|') != -1:\r
+ clsname, types = value.split('|')\r
+ desc += '<TR>'\r
+ desc += '<TD><B>%s</B></TD>' % _inf_key_description_mapping_table[key]\r
+ desc += '<TD>%s</TD>' % clsname\r
+ desc += '</TR>'\r
+\r
+ desc += '<TR>'\r
+ desc += '<TD><B>Supported Module Types</B></TD>'\r
+ desc += '<TD>%s</TD>' % types\r
+ desc += '</TR>'\r
+ else:\r
+ desc += '<TR>'\r
+ desc += '<TD><B>%s</B></TD>' % _inf_key_description_mapping_table[key]\r
+ if key == 'EFI_SPECIFICATION_VERSION' and value == '0x00020000':\r
+ value = '2.0'\r
+ desc += '<TD>%s</TD>' % value\r
+ desc += '</TR>'\r
+ desc += '</TABLE>'\r
+ basicInfSection.AddDescription(desc)\r
+ modPage.AddSection(basicInfSection)\r
+\r
+ # Add protocol section\r
+ data = []\r
+ for obj in infObj.GetSectionObjectsByName('pcd', self._arch):\r
+ data.append(obj.GetPcdName().strip())\r
+ if len(data) != 0:\r
+ s = doxygen.Section('Pcds', 'Pcds')\r
+ desc = "<TABLE>"\r
+ desc += '<TR><TD><B>PCD Name</B></TD><TD><B>TokenSpace</B></TD><TD><B>Package</B></TD></TR>'\r
+ for item in data:\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % item.split('.')[1]\r
+ desc += '<TD>%s</TD>' % item.split('.')[0]\r
+ pkgbasename = self.SearchPcdPackage(item, workspace, refDecObjs)\r
+ desc += '<TD>%s</TD>' % pkgbasename\r
+ desc += '</TR>'\r
+ desc += "</TABLE>"\r
+ s.AddDescription(desc)\r
+ modPage.AddSection(s)\r
+\r
+ # Add protocol section\r
+ #sects = infObj.GetSectionByString('protocol')\r
+ data = []\r
+ #for sect in sects:\r
+ for obj in infObj.GetSectionObjectsByName('protocol', self._arch):\r
+ data.append(obj.GetName().strip())\r
+ if len(data) != 0:\r
+ s = doxygen.Section('Protocols', 'Protocols')\r
+ desc = "<TABLE>"\r
+ desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'\r
+ for item in data:\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % item\r
+ pkgbasename = self.SearchProtocolPackage(item, workspace, refDecObjs)\r
+ desc += '<TD>%s</TD>' % pkgbasename\r
+ desc += '</TR>'\r
+ desc += "</TABLE>"\r
+ s.AddDescription(desc)\r
+ modPage.AddSection(s)\r
+\r
+ # Add ppi section\r
+ #sects = infObj.GetSectionByString('ppi')\r
+ data = []\r
+ #for sect in sects:\r
+ for obj in infObj.GetSectionObjectsByName('ppi', self._arch):\r
+ data.append(obj.GetName().strip())\r
+ if len(data) != 0:\r
+ s = doxygen.Section('Ppis', 'Ppis')\r
+ desc = "<TABLE>"\r
+ desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'\r
+ for item in data:\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % item\r
+ pkgbasename = self.SearchPpiPackage(item, workspace, refDecObjs)\r
+ desc += '<TD>%s</TD>' % pkgbasename\r
+ desc += '</TR>'\r
+ desc += "</TABLE>"\r
+ s.AddDescription(desc)\r
+ modPage.AddSection(s)\r
+\r
+ # Add guid section\r
+ #sects = infObj.GetSectionByString('guid')\r
+ data = []\r
+ #for sect in sects:\r
+ for obj in infObj.GetSectionObjectsByName('guid', self._arch):\r
+ data.append(obj.GetName().strip())\r
+ if len(data) != 0:\r
+ s = doxygen.Section('Guids', 'Guids')\r
+ desc = "<TABLE>"\r
+ desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'\r
+ for item in data:\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % item\r
+ pkgbasename = self.SearchGuidPackage(item, workspace, refDecObjs)\r
+ desc += '<TD>%s</TD>' % pkgbasename\r
+ desc += '</TR>'\r
+ desc += "</TABLE>"\r
+ s.AddDescription(desc)\r
+ modPage.AddSection(s)\r
+\r
+ section = doxygen.Section('LibraryClasses', 'Library Classes')\r
+ desc = "<TABLE>"\r
+ desc += '<TR><TD><B>Name</B></TD><TD><B>Type</B></TD><TD><B>Package</B></TD><TD><B>Header File</B></TD></TR>'\r
+ if isLib:\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % infObj.GetProduceLibraryClass()\r
+ desc += '<TD>Produce</TD>'\r
+ try:\r
+ pkgname, hPath = self.SearchLibraryClassHeaderFile(infObj.GetProduceLibraryClass(),\r
+ workspace,\r
+ refDecObjs)\r
+ except:\r
+ self.Log ('fail to get package header file for lib class %s' % infObj.GetProduceLibraryClass())\r
+ pkgname = 'NULL'\r
+ hPath = 'NULL'\r
+ desc += '<TD>%s</TD>' % pkgname\r
+ if hPath != "NULL":\r
+ #desc += '<TD>\link %s \endlink</TD>' % hPath\r
+ desc += '<TD>%s</TD>' % hPath\r
+ else:\r
+ desc += '<TD>%s</TD>' % hPath\r
+ desc += '</TR>'\r
+ for lcObj in infObj.GetSectionObjectsByName('libraryclasses', self._arch):\r
+ desc += '<TR>'\r
+ desc += '<TD>%s</TD>' % lcObj.GetClass()\r
+ retarr = self.SearchLibraryClassHeaderFile(lcObj.GetClass(),\r
+ workspace,\r
+ refDecObjs)\r
+ if retarr != None:\r
+ pkgname, hPath = retarr\r
+ else:\r
+ self.Log('Fail find the library class %s definition from module %s dependent package!' % (lcObj.GetClass(), infObj.GetFilename()), 'error')\r
+ pkgname = 'NULL'\r
+ hPath = 'NULL'\r
+ desc += '<TD>Consume</TD>'\r
+ desc += '<TD>%s</TD>' % pkgname\r
+ desc += '<TD>%s</TD>' % hPath\r
+ desc += '</TR>'\r
+ desc += "</TABLE>"\r
+ section.AddDescription(desc)\r
+ modPage.AddSection(section)\r
+\r
+ section = doxygen.Section('SourceFiles', 'Source Files')\r
+ section.AddDescription('<ul>\n')\r
+ for obj in infObj.GetSourceObjects(self._arch, self._tooltag):\r
+ sPath = infObj.GetModuleRootPath()\r
+ sPath = os.path.join(sPath, obj.GetSourcePath()).replace('\\', '/').strip()\r
+ if sPath.lower().endswith('.uni') or sPath.lower().endswith('.s') or sPath.lower().endswith('.asm') or sPath.lower().endswith('.nasm'):\r
+ newPath = self.TranslateUniFile(sPath)\r
+ configFile.AddFile(newPath)\r
+ newPath = newPath[len(pObj.GetWorkspace()) + 1:]\r
+ section.AddDescription('<li> \link %s \endlink </li>' % newPath)\r
+ else:\r
+ self.ProcessSourceFileForInclude(sPath, pObj, configFile, infObj)\r
+ sPath = sPath[len(pObj.GetWorkspace()) + 1:]\r
+ section.AddDescription('<li>\link %s \endlink </li>' % sPath)\r
+ section.AddDescription('</ul>\n')\r
+ modPage.AddSection(section)\r
+\r
+ #sects = infObj.GetSectionByString('depex')\r
+ data = []\r
+ #for sect in sects:\r
+ for obj in infObj.GetSectionObjectsByName('depex'):\r
+ data.append(str(obj))\r
+ if len(data) != 0:\r
+ s = doxygen.Section('DependentSection', 'Module Dependencies')\r
+ s.AddDescription('<br>'.join(data))\r
+ modPage.AddSection(s)\r
+\r
+ return modPage\r
+\r
+ def TranslateUniFile(self, path):\r
+ newpath = path + '.dox'\r
+ #import core.textfile as textfile\r
+ #file = textfile.TextFile(path)\r
+\r
+ try:\r
+ file = open(path, 'rb')\r
+ except (IOError, OSError), msg:\r
+ return None\r
+\r
+ t = file.read()\r
+ file.close()\r
+\r
+ output = '/** @file \n'\r
+ #output = '<html><body>'\r
+ arr = t.split('\r\n')\r
+ for line in arr:\r
+ if line.find('@file') != -1:\r
+ continue\r
+ if line.find('*/') != -1:\r
+ continue\r
+ line = line.strip()\r
+ if line.strip().startswith('/'):\r
+ arr = line.split(' ')\r
+ if len(arr) > 1:\r
+ line = ' '.join(arr[1:])\r
+ else:\r
+ continue\r
+ output += '%s<br>\n' % line\r
+ output += '**/'\r
+\r
+ if os.path.exists(newpath):\r
+ os.remove(newpath)\r
+\r
+ file = open(newpath, "w")\r
+ file.write(output)\r
+ file.close()\r
+ return newpath\r
+\r
+ def SearchPcdPackage(self, pcdname, workspace, decObjs):\r
+ for decObj in decObjs:\r
+ for pcd in decObj.GetSectionObjectsByName('pcd'):\r
+ if pcdname == pcd.GetPcdName():\r
+ return decObj.GetBaseName()\r
+ return None\r
+\r
+ def SearchProtocolPackage(self, protname, workspace, decObjs):\r
+ for decObj in decObjs:\r
+ for proto in decObj.GetSectionObjectsByName('protocol'):\r
+ if protname == proto.GetName():\r
+ return decObj.GetBaseName()\r
+ return None\r
+\r
+ def SearchPpiPackage(self, ppiname, workspace, decObjs):\r
+ for decObj in decObjs:\r
+ for ppi in decObj.GetSectionObjectsByName('ppi'):\r
+ if ppiname == ppi.GetName():\r
+ return decObj.GetBaseName()\r
+ return None\r
+\r
+ def SearchGuidPackage(self, guidname, workspace, decObjs):\r
+ for decObj in decObjs:\r
+ for guid in decObj.GetSectionObjectsByName('guid'):\r
+ if guidname == guid.GetName():\r
+ return decObj.GetBaseName()\r
+ return None\r
+\r
+ def SearchLibraryClassHeaderFile(self, className, workspace, decObjs):\r
+ for decObj in decObjs:\r
+ for cls in decObj.GetSectionObjectsByName('libraryclasses'):\r
+ if cls.GetClassName().strip() == className:\r
+ path = cls.GetHeaderFile().strip()\r
+ path = os.path.join(decObj.GetPackageRootPath(), path)\r
+ path = path[len(workspace) + 1:]\r
+ return decObj.GetBaseName(), path.replace('\\', '/')\r
+\r
+ return None\r
+\r
+ def _ConvertPathToDoxygen(self, path, pObj):\r
+ pRootPath = pObj.GetWorkspace()\r
+ path = path[len(pRootPath) + 1:]\r
+ return path.replace('\\', '/')\r
+\r
+def IsCHeaderFile(path):\r
+ return CheckPathPostfix(path, 'h')\r
+\r
+def CheckPathPostfix(path, str):\r
+ index = path.rfind('.')\r
+ if index == -1:\r
+ return False\r
+ if path[index + 1:].lower() == str.lower():\r
+ return True\r
+ return False\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+import plugins.EdkPlugins.basemodel.ini as ini\r
+import re, os\r
+from plugins.EdkPlugins.basemodel.message import *\r
+\r
+class DSCFile(ini.BaseINIFile):\r
+ def GetSectionInstance(self, parent, name, isCombined=False):\r
+ return DSCSection(parent, name, isCombined)\r
+\r
+ def GetComponents(self):\r
+ return self.GetSectionObjectsByName('Components')\r
+\r
+class DSCSection(ini.BaseINISection):\r
+ def GetSectionINIObject(self, parent):\r
+ type = self.GetType()\r
+\r
+ if type.lower() == 'components':\r
+ return DSCComponentObject(self)\r
+ if type.lower() == 'libraryclasses':\r
+ return DSCLibraryClassObject(self)\r
+ if type.lower() == 'defines':\r
+ return ini.BaseINISectionObject(self)\r
+ if type.lower() == 'pcdsfeatureflag' or \\r
+ type.lower() == 'pcdsfixedatbuild' or \\r
+ type.lower() == 'pcdspatchableinmodule' or\\r
+ type.lower() == 'pcdsdynamicdefault' or \\r
+ type.lower() == 'pcdsdynamicex' or \\r
+ type.lower() == 'pcdsdynamichii' or \\r
+ type.lower() == 'pcdsdynamicvpd':\r
+ return DSCPcdObject(self)\r
+\r
+ return DSCSectionObject(self)\r
+\r
+ def GetType(self):\r
+ arr = self._name.split('.')\r
+ return arr[0].strip()\r
+\r
+ def GetArch(self):\r
+ arr = self._name.split('.')\r
+ if len(arr) == 1:\r
+ return 'common'\r
+ return arr[1]\r
+\r
+ def GetModuleType(self):\r
+ arr = self._name.split('.')\r
+ if len(arr) < 3:\r
+ return 'common'\r
+ return arr[2]\r
+\r
+class DSCSectionObject(ini.BaseINISectionObject):\r
+ def GetArch(self):\r
+ return self.GetParent().GetArch()\r
+\r
+class DSCPcdObject(DSCSectionObject):\r
+\r
+ def __init__(self, parent):\r
+ ini.BaseINISectionObject.__init__(self, parent)\r
+ self._name = None\r
+\r
+ def Parse(self):\r
+ line = self.GetLineByOffset(self._start).strip().split('#')[0]\r
+ self._name = line.split('|')[0]\r
+ self._value = line.split('|')[1]\r
+ return True\r
+\r
+ def GetPcdName(self):\r
+ return self._name\r
+\r
+ def GetPcdType(self):\r
+ return self.GetParent().GetType()\r
+\r
+ def GetPcdValue(self):\r
+ return self._value\r
+\r
+class DSCLibraryClassObject(DSCSectionObject):\r
+ def __init__(self, parent):\r
+ ini.BaseINISectionObject.__init__(self, parent)\r
+\r
+ def GetClass(self):\r
+ line = self.GetLineByOffset(self._start)\r
+ return line.split('#')[0].split('|')[0].strip()\r
+\r
+ def GetInstance(self):\r
+ line = self.GetLineByOffset(self._start)\r
+ return line.split('#')[0].split('|')[1].strip()\r
+\r
+ def GetArch(self):\r
+ return self.GetParent().GetArch()\r
+\r
+ def GetModuleType(self):\r
+ return self.GetParent().GetModuleType()\r
+\r
+class DSCComponentObject(DSCSectionObject):\r
+\r
+ def __init__(self, parent):\r
+ ini.BaseINISectionObject.__init__(self, parent)\r
+ self._OveridePcds = {}\r
+ self._OverideLibraries = {}\r
+ self._Filename = ''\r
+\r
+ def __del__(self):\r
+ self._OverideLibraries.clear()\r
+ self._OverideLibraries.clear()\r
+ ini.BaseINISectionObject.__del__(self)\r
+\r
+ def AddOverideLib(self, libclass, libinstPath):\r
+ if libclass not in self._OverideLibraries.keys():\r
+ self._OverideLibraries[libclass] = libinstPath\r
+\r
+ def AddOveridePcd(self, name, type, value=None):\r
+ if type not in self._OveridePcds.keys():\r
+ self._OveridePcds[type] = []\r
+ self._OveridePcds[type].append((name, value))\r
+\r
+ def GetOverideLibs(self):\r
+ return self._OverideLibraries\r
+\r
+ def GetArch(self):\r
+ return self.GetParent().GetArch()\r
+\r
+ def GetOveridePcds(self):\r
+ return self._OveridePcds\r
+\r
+ def GetFilename(self):\r
+ return self.GetLineByOffset(self._start).split('#')[0].split('{')[0].strip()\r
+\r
+ def SetFilename(self, fName):\r
+ self._Filename = fName\r
+\r
+ def Parse(self):\r
+ if (self._start < self._end):\r
+ #\r
+ # The first line is inf path and could be ignored\r
+ # The end line is '}' and could be ignored\r
+ #\r
+ curr = self._start + 1\r
+ end = self._end - 1\r
+ OverideName = ''\r
+ while (curr <= end):\r
+ line = self.GetLineByOffset(curr).strip()\r
+ if len(line) > 0 and line[0] != '#':\r
+ line = line.split('#')[0].strip()\r
+ if line[0] == '<':\r
+ OverideName = line[1:len(line)-1]\r
+ elif OverideName.lower() == 'libraryclasses':\r
+ arr = line.split('|')\r
+ self._OverideLibraries[arr[0].strip()] = arr[1].strip()\r
+ elif OverideName.lower() == 'pcds':\r
+ ErrorMsg('EDES does not support PCD overide',\r
+ self.GetFileName(),\r
+ self.GetParent().GetLinenumberByOffset(curr))\r
+ curr = curr + 1\r
+ return True\r
+\r
+ def GenerateLines(self):\r
+ lines = []\r
+ hasLib = False\r
+ hasPcd = False\r
+ if len(self._OverideLibraries) != 0:\r
+ hasLib = True\r
+ if len(self._OveridePcds) != 0:\r
+ hasPcd = True\r
+\r
+ if hasLib or hasPcd:\r
+ lines.append((' %s {\n' % self._Filename))\r
+ else:\r
+ lines.append((' %s \n' % self._Filename))\r
+ return lines\r
+\r
+ if hasLib:\r
+ lines.append(' <LibraryClasses>\n')\r
+ for libKey in self._OverideLibraries.keys():\r
+ lines.append(' %s|%s\n' % (libKey, self._OverideLibraries[libKey]))\r
+\r
+ if hasPcd:\r
+ for key in self._OveridePcds.keys():\r
+ lines.append(' <%s>\n' % key)\r
+\r
+ for name, value in self._OveridePcds[key]:\r
+ if value != None:\r
+ lines.append(' %s|%s\n' % (name, value))\r
+ else:\r
+ lines.append(' %s\n' % name)\r
+\r
+ if hasLib or hasPcd:\r
+ lines.append(' }\n')\r
+\r
+ return lines\r
+\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+import plugins.EdkPlugins.basemodel.ini as ini\r
+import re, os\r
+from plugins.EdkPlugins.basemodel.message import *\r
+\r
+class INFFile(ini.BaseINIFile):\r
+ _libobjs = {}\r
+\r
+ def GetSectionInstance(self, parent, name, isCombined=False):\r
+ return INFSection(parent, name, isCombined)\r
+\r
+ def GetProduceLibraryClass(self):\r
+ obj = self.GetDefine("LIBRARY_CLASS")\r
+ if obj == None: return None\r
+\r
+ return obj.split('|')[0].strip()\r
+\r
+ def GetSectionObjectsByName(self, name, arch=None):\r
+ arr = []\r
+ sects = self.GetSectionByName(name)\r
+ for sect in sects:\r
+ # skip unmatched archtecture content\r
+ if not sect.IsArchMatch(arch):\r
+ continue\r
+\r
+ for obj in sect.GetObjects():\r
+ arr.append(obj)\r
+\r
+ return arr\r
+\r
+ def GetSourceObjects(self, arch=None, tool=None):\r
+ arr = []\r
+ sects = self.GetSectionByName('sources')\r
+ for sect in sects:\r
+ # skip unmatched archtecture content\r
+ if not sect.IsArchMatch(arch):\r
+ continue\r
+\r
+ for obj in sect.GetObjects():\r
+ if not obj.IsMatchFamily(tool):\r
+ continue\r
+ arr.append(obj)\r
+\r
+ return arr\r
+\r
+ def Parse(self):\r
+ if not ini.BaseINIFile.Parse(self):\r
+ return False\r
+ classname = self.GetProduceLibraryClass()\r
+ if classname != None:\r
+ libobjdict = INFFile._libobjs\r
+ if libobjdict.has_key(classname):\r
+ if self not in libobjdict[classname]:\r
+ libobjdict[classname].append(self)\r
+ else:\r
+ libobjdict[classname] = [self]\r
+\r
+ return True\r
+\r
+ def GetBaseName(self):\r
+ return self.GetDefine("BASE_NAME").strip()\r
+\r
+ def GetModuleRootPath(self):\r
+ return os.path.dirname(self.GetFilename())\r
+\r
+ def Clear(self):\r
+ classname = self.GetProduceLibraryClass()\r
+ if classname != None:\r
+ libobjdict = INFFile._libobjs\r
+ libobjdict[classname].remove(self)\r
+ if len(libobjdict[classname]) == 0:\r
+ del libobjdict[classname]\r
+ ini.BaseINIFile.Clear(self)\r
+\r
+\r
+class INFSection(ini.BaseINISection):\r
+ def GetSectionINIObject(self, parent):\r
+ type = self.GetType()\r
+\r
+ if type.lower() == 'libraryclasses':\r
+ return INFLibraryClassObject(self)\r
+ if type.lower() == 'sources':\r
+ return INFSourceObject(self)\r
+ if type.lower().find('pcd') != -1:\r
+ return INFPcdObject(self)\r
+ if type.lower() == 'packages':\r
+ return INFDependentPackageObject(self)\r
+ if type.lower() in ['guids', 'protocols', 'ppis']:\r
+ return INFGuidObject(self)\r
+ if type.lower() == 'defines':\r
+ return INFDefineSectionObject(self)\r
+ return INFSectionObject(self)\r
+\r
+ def GetType(self):\r
+ arr = self._name.split('.')\r
+ return arr[0].strip()\r
+\r
+ def GetArch(self):\r
+ arr = self._name.split('.')\r
+ if len(arr) == 1:\r
+ return 'common'\r
+ return arr[1]\r
+\r
+ def IsArchMatch(self, arch):\r
+ if arch == None or self.GetArch() == 'common':\r
+ return True\r
+\r
+ if self.GetArch().lower() != arch.lower():\r
+ return False\r
+\r
+ return True\r
+\r
+class INFSectionObject(ini.BaseINISectionObject):\r
+ def GetArch(self):\r
+ return self.GetParent().GetArch()\r
+\r
+class INFDefineSectionObject(INFSectionObject):\r
+ def __init__(self, parent):\r
+ INFSectionObject.__init__(self, parent)\r
+ self._key = None\r
+ self._value = None\r
+\r
+ def Parse(self):\r
+ assert (self._start == self._end), 'The object in define section must be in single line'\r
+\r
+ line = self.GetLineByOffset(self._start).strip()\r
+\r
+ line = line.split('#')[0]\r
+ arr = line.split('=')\r
+ if len(arr) != 2:\r
+ ErrorMsg('Invalid define section object',\r
+ self.GetFilename(),\r
+ self._start\r
+ )\r
+ return False\r
+\r
+ self._key = arr[0].strip()\r
+ self._value = arr[1].strip()\r
+\r
+ return True\r
+\r
+ def GetKey(self):\r
+ return self._key\r
+\r
+ def GetValue(self):\r
+ return self._value\r
+\r
+class INFLibraryClassObject(INFSectionObject):\r
+ _objs = {}\r
+ def __init__(self, parent):\r
+ INFSectionObject.__init__(self, parent)\r
+ self._classname = None\r
+\r
+ def GetClass(self):\r
+ return self._classname\r
+\r
+ def Parse(self):\r
+ self._classname = self.GetLineByOffset(self._start).split('#')[0].strip()\r
+ objdict = INFLibraryClassObject._objs\r
+ if objdict.has_key(self._classname):\r
+ objdict[self._classname].append(self)\r
+ else:\r
+ objdict[self._classname] = [self]\r
+ return True\r
+\r
+ def Destroy(self):\r
+ objdict = INFLibraryClassObject._objs\r
+ objdict[self._classname].remove(self)\r
+ if len(objdict[self._classname]) == 0:\r
+ del objdict[self._classname]\r
+\r
+ def GetName(self):\r
+ return self._classname\r
+\r
+ @staticmethod\r
+ def GetObjectDict():\r
+ return INFLibraryClassObject._objs\r
+\r
+class INFDependentPackageObject(INFSectionObject):\r
+ def GetPath(self):\r
+ return self.GetLineByOffset(self._start).split('#')[0].strip()\r
+\r
+class INFSourceObject(INFSectionObject):\r
+ _objs = {}\r
+ def __init__(self, parent):\r
+ INFSectionObject.__init__(self, parent)\r
+\r
+ self.mSourcename = None\r
+ self.mToolCode = None\r
+ self.mFamily = None\r
+ self.mTagName = None\r
+ self.mFeaturePcd = None\r
+ self.mFilename = None\r
+\r
+ def GetSourcePath(self):\r
+ return self.mSourcename\r
+\r
+ def GetSourceFullPath(self):\r
+ path = os.path.dirname(self.GetFilename())\r
+ path = os.path.join(path, self.GetSourcePath())\r
+ return os.path.normpath(path)\r
+\r
+ def GetToolCode(self):\r
+ return self.mToolCode\r
+\r
+ def GetFamily(self):\r
+ return self.mFamily\r
+\r
+ def GetTagName(self):\r
+ return self.mTagName\r
+\r
+ def GetFeaturePcd(self):\r
+ return self.mFeaturePcd\r
+\r
+ def Parse(self):\r
+ line = self.GetLineByOffset(self._start).strip().split('#')[0]\r
+\r
+ arr = line.split('|')\r
+\r
+ self.mSourcename = arr[0].strip()\r
+ if len(arr) >= 2:\r
+ self.mFamily = arr[1].strip()\r
+ if len(arr) >= 3:\r
+ self.mTagName = arr[2].strip()\r
+ if len(arr) >= 4:\r
+ self.mToolCode = arr[3].strip()\r
+ if len(arr) >= 5:\r
+ self.mFeaturePcd = arr[4].strip()\r
+\r
+ self.mFilename = os.path.basename(self.GetSourceFullPath())\r
+ objdict = INFSourceObject._objs\r
+ if not objdict.has_key(self.mFilename):\r
+ objdict[self.mFilename] = [self]\r
+ else:\r
+ objdict[self.mFilename].append(self)\r
+\r
+ return True\r
+\r
+ def GetName(self):\r
+ return self.mFilename\r
+\r
+ def Destroy(self):\r
+ objdict = INFSourceObject._objs\r
+ objdict[self.mFilename].remove(self)\r
+ if len(objdict[self.mFilename]) == 0:\r
+ del objdict[self.mFilename]\r
+\r
+ def IsMatchFamily(self, family):\r
+ if family == None:\r
+ return True\r
+ if self.mFamily != None:\r
+ if family.strip().lower() == self.mFamily.lower():\r
+ return True\r
+ else:\r
+ return False\r
+ else:\r
+ fname = self.GetSourcePath()\r
+ if fname.endswith('.S') and family.lower() != 'gcc':\r
+ return False\r
+ if fname.endswith('.s') and (self.GetArch().lower() != 'ipf' and self.GetArch().lower() != 'common'):\r
+ return False\r
+ if fname.lower().endswith('.asm') and (family.lower() != 'msft' and family.lower() != 'intel'):\r
+ return False\r
+ return True\r
+\r
+ @staticmethod\r
+ def GetObjectDict():\r
+ return INFSourceObject._objs\r
+\r
+class INFPcdObject(INFSectionObject):\r
+ _objs = {}\r
+\r
+ def __init__(self, parent):\r
+ INFSectionObject.__init__(self, parent)\r
+\r
+ self.mPcdType = None\r
+ self.mDefaultValue = None\r
+ self.mPcdName = None\r
+\r
+ @staticmethod\r
+ def GetObjectDict():\r
+ return INFPcdObject._objs\r
+\r
+ def Parse(self):\r
+ line = self.GetLineByOffset(self._start).strip().split('#')[0]\r
+\r
+ arr = line.split('|')\r
+ self.mPcdName = arr[0].strip()\r
+\r
+ if len(arr) >= 2:\r
+ self.mDefaultValue = arr[1].strip()\r
+\r
+ objdict = INFPcdObject._objs\r
+ if objdict.has_key(self.GetName()):\r
+ if self not in objdict[self.GetName()]:\r
+ objdict[self.GetName()].append(self)\r
+ else:\r
+ objdict[self.GetName()] = [self]\r
+ return True\r
+\r
+ def GetPcdName(self):\r
+ return self.mPcdName\r
+\r
+ def GetPcdType(self):\r
+ return self.GetParent().GetType()\r
+\r
+ def GetName(self):\r
+ return self.mPcdName.split('.')[1]\r
+\r
+ def Destroy(self):\r
+ objdict = INFPcdObject._objs\r
+ objdict[self.GetName()].remove(self)\r
+ if len(objdict[self.GetName()]) == 0:\r
+ del objdict[self.GetName()]\r
+\r
+class INFGuidObject(INFSectionObject):\r
+ def __init__(self, parent):\r
+ INFSectionObject.__init__(self, parent)\r
+ self._name = None\r
+\r
+ def Parse(self):\r
+ line = self.GetLineByOffset(self._start).strip().split('#')[0].split("|")[0]\r
+ self._name = line.strip()\r
+ return True\r
+\r
+ def GetName(self):\r
+ return self._name\r
+\r
+\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r