BaseTools: Add PackageDocumentTools into Scripts folder

This tool is used to generate the document for edk2 packages. The
generated document will be in UDK release. For example, UDK2017
document can be found in:
https://github.com/tianocore/tianocore.github.io/wiki/UDK2017#documentation

Cc: Star Zeng <star.zeng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
This commit is contained in:
Yonghong Zhu 2018-03-15 14:40:57 +08:00
parent 316b43dee5
commit 7ccc9c954c
20 changed files with 7177 additions and 0 deletions

View File

@ -0,0 +1,19 @@
Prerequisite Tools:
1. Install Python 2.7.3 from https://www.python.org/download/releases/2.7.3/
2. Install wxPython 2.8.12.1 from https://sourceforge.net/projects/wxpython/files/wxPython/2.8.12.1/
generally the libraries will be installed at python's subfolder, for example in windows: c:\python27\Lib\site-packages\
3. Install DoxyGen 1.8.6 from https://sourceforge.net/projects/doxygen/files/rel-1.8.6/
4. (Windows only) Install Htmlhelp tool from https://msdn.microsoft.com/en-us/library/windows/desktop/ms669985(v=vs.85).aspx
Limitation:
1. Current tool doesn't work on latest wxPython and DoxyGen tool. Please use the sepecific version in above.
Run the Tool:
a) Run with GUI:
1. Enter src folder, double click "packagedocapp.pyw" or run command "python packagedocapp.pyw" to open the GUI.
2. Make sure all the information in blank are correct.
3. Click "Generate Package Document!"
b) Run with command line:
1. Open command line window
2. Enter src folder, for example: "cd C:\PackageDocumentTools\src"
3. Run "python packagedoc_cli.py --help" for detail command.

View File

@ -0,0 +1,12 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#

View File

@ -0,0 +1,429 @@
## @file
# This module provide command line entry for generating package document!
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
import os, sys, logging, traceback, subprocess
from optparse import OptionParser
import plugins.EdkPlugins.edk2.model.baseobject as baseobject
import plugins.EdkPlugins.edk2.model.doxygengen as doxygengen
gArchMarcoDict = {'ALL' : 'MDE_CPU_IA32 MDE_CPU_X64 MDE_CPU_EBC MDE_CPU_IPF _MSC_EXTENSIONS __GNUC__ __INTEL_COMPILER',
'IA32_MSFT': 'MDE_CPU_IA32 _MSC_EXTENSIONS',
'IA32_GNU' : 'MDE_CPU_IA32 __GNUC__',
'X64_MSFT' : 'MDE_CPU_X64 _MSC_EXTENSIONS ASM_PFX= OPTIONAL= ',
'X64_GNU' : 'MDE_CPU_X64 __GNUC__ ASM_PFX= OPTIONAL= ',
'IPF_MSFT' : 'MDE_CPU_IPF _MSC_EXTENSIONS ASM_PFX= OPTIONAL= ',
'IPF_GNU' : 'MDE_CPU_IPF __GNUC__ ASM_PFX= OPTIONAL= ',
'EBC_INTEL': 'MDE_CPU_EBC __INTEL_COMPILER ASM_PFX= OPTIONAL= '}
def parseCmdArgs():
parser = OptionParser(version="Package Document Generation Tools - Version 0.1")
parser.add_option('-w', '--workspace', action='store', type='string', dest='WorkspacePath',
help='Specify workspace absolute path. For example: c:\\tianocore')
parser.add_option('-p', '--decfile', action='store', dest='PackagePath',
help='Specify the absolute path for package DEC file. For example: c:\\tianocore\\MdePkg\\MdePkg.dec')
parser.add_option('-x', '--doxygen', action='store', dest='DoxygenPath',
help='Specify the absolute path of doxygen tools installation. For example: C:\\Program Files\\doxygen\bin\doxygen.exe')
parser.add_option('-o', '--output', action='store', dest='OutputPath',
help='Specify the document output path. For example: c:\\docoutput')
parser.add_option('-a', '--arch', action='store', dest='Arch', choices=gArchMarcoDict.keys(),
help='Specify the architecture used in preprocess package\'s source. For example: -a IA32_MSFT')
parser.add_option('-m', '--mode', action='store', dest='DocumentMode', choices=['CHM', 'HTML'],
help='Specify the document mode from : CHM or HTML')
parser.add_option('-i', '--includeonly', action='store_true', dest='IncludeOnly',
help='Only generate document for package\'s public interfaces produced by include folder. ')
parser.add_option('-c', '--htmlworkshop', dest='HtmlWorkshopPath',
help='Specify the absolute path for Microsoft HTML Workshop\'s hhc.exe file. For example: C:\\Program Files\\HTML Help Workshop\\hhc.exe')
(options, args) = parser.parse_args()
# validate the options
errors = []
if options.WorkspacePath == None:
errors.append('- Please specify workspace path via option -w!')
elif not os.path.exists(options.WorkspacePath):
errors.append("- Invalid workspace path %s! The workspace path should be exist in absolute path!" % options.WorkspacePath)
if options.PackagePath == None:
errors.append('- Please specify package DEC file path via option -p!')
elif not os.path.exists(options.PackagePath):
errors.append("- Invalid package's DEC file path %s! The DEC path should be exist in absolute path!" % options.PackagePath)
default = "C:\\Program Files\\doxygen\\bin\\doxygen.exe"
if options.DoxygenPath == None:
if os.path.exists(default):
print "Warning: Assume doxygen tool is installed at %s. If not, please specify via -x" % default
options.DoxygenPath = default
else:
errors.append('- Please specify the path of doxygen tool installation via option -x! or install it in default path %s' % default)
elif not os.path.exists(options.DoxygenPath):
errors.append("- Invalid doxygen tool path %s! The doxygen tool path should be exist in absolute path!" % options.DoxygenPath)
if options.OutputPath != None:
if not os.path.exists(options.OutputPath):
# create output
try:
os.makedirs(options.OutputPath)
except:
errors.append('- Fail to create the output directory %s' % options.OutputPath)
else:
if options.PackagePath != None and os.path.exists(options.PackagePath):
dirpath = os.path.dirname(options.PackagePath)
default = os.path.join (dirpath, "Document")
print 'Warning: Assume document output at %s. If not, please specify via option -o' % default
options.OutputPath = default
if not os.path.exists(default):
try:
os.makedirs(default)
except:
errors.append('- Fail to create default output directory %s! Please specify document output diretory via option -o' % default)
else:
errors.append('- Please specify document output path via option -o!')
if options.Arch == None:
options.Arch = 'ALL'
print "Warning: Assume arch is \"ALL\". If not, specify via -a"
if options.DocumentMode == None:
options.DocumentMode = "HTML"
print "Warning: Assume document mode is \"HTML\". If not, specify via -m"
if options.IncludeOnly == None:
options.IncludeOnly = False
print "Warning: Assume generate package document for all package\'s source including publich interfaces and implementation libraries and modules."
if options.DocumentMode.lower() == 'chm':
default = "C:\\Program Files\\HTML Help Workshop\\hhc.exe"
if options.HtmlWorkshopPath == None:
if os.path.exists(default):
print 'Warning: Assume the installation path of Microsoft HTML Workshop is %s. If not, specify via option -c.' % default
options.HtmlWorkshopPath = default
else:
errors.append('- Please specify the installation path of Microsoft HTML Workshop via option -c!')
elif not os.path.exists(options.HtmlWorkshopPath):
errors.append('- The installation path of Microsoft HTML Workshop %s does not exists. ' % options.HtmlWorkshopPath)
if len(errors) != 0:
print '\n'
parser.error('Fail to start due to following reasons: \n%s' %'\n'.join(errors))
return (options.WorkspacePath, options.PackagePath, options.DoxygenPath, options.OutputPath,
options.Arch, options.DocumentMode, options.IncludeOnly, options.HtmlWorkshopPath)
def createPackageObject(wsPath, pkgPath):
try:
pkgObj = baseobject.Package(None, wsPath)
pkgObj.Load(pkgPath)
except:
logging.getLogger().error ('Fail to create package object!')
return None
return pkgObj
def callbackLogMessage(msg, level):
print msg.strip()
def callbackCreateDoxygenProcess(doxPath, configPath):
if sys.platform == 'win32':
cmd = '"%s" %s' % (doxPath, configPath)
else:
cmd = '%s %s' % (doxPath, configPath)
print cmd
subprocess.call(cmd, shell=True)
def DocumentFixup(outPath, arch):
# find BASE_LIBRARY_JUMP_BUFFER structure reference page
print '\n >>> Start fixup document \n'
for root, dirs, files in os.walk(outPath):
for dir in dirs:
if dir.lower() in ['.svn', '_svn', 'cvs']:
dirs.remove(dir)
for file in files:
if not file.lower().endswith('.html'): continue
fullpath = os.path.join(outPath, root, file)
try:
f = open(fullpath, 'r')
text = f.read()
f.close()
except:
logging.getLogger().error('\nFail to open file %s\n' % fullpath)
continue
if arch.lower() == 'all':
if text.find('BASE_LIBRARY_JUMP_BUFFER Struct Reference') != -1:
FixPageBASE_LIBRARY_JUMP_BUFFER(fullpath, text)
if text.find('MdePkg/Include/Library/BaseLib.h File Reference') != -1:
FixPageBaseLib(fullpath, text)
if text.find('IA32_IDT_GATE_DESCRIPTOR Union Reference') != -1:
FixPageIA32_IDT_GATE_DESCRIPTOR(fullpath, text)
if text.find('MdePkg/Include/Library/UefiDriverEntryPoint.h File Reference') != -1:
FixPageUefiDriverEntryPoint(fullpath, text)
if text.find('MdePkg/Include/Library/UefiApplicationEntryPoint.h File Reference') != -1:
FixPageUefiApplicationEntryPoint(fullpath, text)
print ' >>> Finish all document fixing up! \n'
def FixPageBaseLib(path, text):
print ' >>> Fixup BaseLib file page at file %s \n' % path
lines = text.split('\n')
lastBaseJumpIndex = -1
lastIdtGateDescriptor = -1
for index in range(len(lines) - 1, -1, -1):
line = lines[index]
if line.strip() == '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT&nbsp;&nbsp;&nbsp;4 </td>':
lines[index] = '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT&nbsp;&nbsp;&nbsp;4&nbsp;[IA32] </td>'
if line.strip() == '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT&nbsp;&nbsp;&nbsp;0x10 </td>':
lines[index] = '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT&nbsp;&nbsp;&nbsp;0x10&nbsp;[IPF] </td>'
if line.strip() == '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT&nbsp;&nbsp;&nbsp;8 </td>':
lines[index] = '<td class="memname">#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT&nbsp;&nbsp;&nbsp;9&nbsp;[EBC, x64] </td>'
if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a>&nbsp;&nbsp;&nbsp;4') != -1:
lines[index] = lines[index].replace('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a>&nbsp;&nbsp;&nbsp;4',
'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a>&nbsp;&nbsp;&nbsp;4&nbsp;[IA32]')
if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a>&nbsp;&nbsp;&nbsp;0x10') != -1:
lines[index] = lines[index].replace('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a>&nbsp;&nbsp;&nbsp;0x10',
'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a>&nbsp;&nbsp;&nbsp;0x10&nbsp;[IPF]')
if line.find('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a>&nbsp;&nbsp;&nbsp;8') != -1:
lines[index] = lines[index].replace('BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a>&nbsp;&nbsp;&nbsp;8',
'BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT</a>&nbsp;&nbsp;&nbsp;8&nbsp;[x64, EBC]')
if line.find('>BASE_LIBRARY_JUMP_BUFFER</a>') != -1:
if lastBaseJumpIndex != -1:
del lines[lastBaseJumpIndex]
lastBaseJumpIndex = index
if line.find('>IA32_IDT_GATE_DESCRIPTOR</a></td>') != -1:
if lastIdtGateDescriptor != -1:
del lines[lastIdtGateDescriptor]
lastIdtGateDescriptor = index
try:
f = open(path, 'w')
f.write('\n'.join(lines))
f.close()
except:
logging.getLogger().error(" <<< Fail to fixup file %s\n" % path)
return
print " <<< Finish to fixup file %s\n" % path
def FixPageIA32_IDT_GATE_DESCRIPTOR(path, text):
print ' >>> Fixup structure reference IA32_IDT_GATE_DESCRIPTOR at file %s \n' % path
lines = text.split('\n')
for index in range(len(lines) - 1, -1, -1):
line = lines[index].strip()
if line.find('struct {</td>') != -1 and lines[index - 2].find('>Uint64</a></td>') != -1:
lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For X64</h2></td></tr>')
if line.find('struct {</td>') != -1 and lines[index - 1].find('Data Fields') != -1:
lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For IA32</h2></td></tr>')
try:
f = open(path, 'w')
f.write('\n'.join(lines))
f.close()
except:
logging.getLogger().error(" <<< Fail to fixup file %s\n" % path)
return
print " <<< Finish to fixup file %s\n" % path
def FixPageBASE_LIBRARY_JUMP_BUFFER(path, text):
print ' >>> Fixup structure reference BASE_LIBRARY_JUMP_BUFFER at file %s \n' % path
lines = text.split('\n')
bInDetail = True
bNeedRemove = False
for index in range(len(lines) - 1, -1, -1):
line = lines[index]
if line.find('Detailed Description') != -1:
bInDetail = False
if line.startswith('EBC context buffer used by') and lines[index - 1].startswith('x64 context buffer'):
lines[index] = "IA32/IPF/X64/" + line
bNeedRemove = True
if line.startswith("x64 context buffer") or line.startswith('IPF context buffer used by') or \
line.startswith('IA32 context buffer used by'):
if bNeedRemove:
lines.remove(line)
if line.find('>R0</a>') != -1 and not bInDetail:
if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For EBC</h2></td></tr>':
lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For EBC</h2></td></tr>')
if line.find('>Rbx</a>') != -1 and not bInDetail:
if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For X64</h2></td></tr>':
lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For X64</h2></td></tr>')
if line.find('>F2</a>') != -1 and not bInDetail:
if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For IPF</h2></td></tr>':
lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For IPF</h2></td></tr>')
if line.find('>Ebx</a>') != -1 and not bInDetail:
if lines[index - 1] != '<tr><td colspan="2"><br><h2>Data Fields For IA32</h2></td></tr>':
lines.insert(index, '<tr><td colspan="2"><br><h2>Data Fields For IA32</h2></td></tr>')
try:
f = open(path, 'w')
f.write('\n'.join(lines))
f.close()
except:
logging.getLogger().error(" <<< Fail to fixup file %s" % path)
return
print " <<< Finish to fixup file %s\n" % path
def FixPageUefiDriverEntryPoint(path, text):
print ' >>> Fixup file reference MdePkg/Include/Library/UefiDriverEntryPoint.h at file %s \n' % path
lines = text.split('\n')
bInModuleEntry = False
bInEfiMain = False
ModuleEntryDlCount = 0
ModuleEntryDelStart = 0
ModuleEntryDelEnd = 0
EfiMainDlCount = 0
EfiMainDelStart = 0
EfiMainDelEnd = 0
for index in range(len(lines)):
line = lines[index].strip()
if line.find('EFI_STATUS</a> EFIAPI _ModuleEntryPoint </td>') != -1:
bInModuleEntry = True
if line.find('EFI_STATUS</a> EFIAPI EfiMain </td>') != -1:
bInEfiMain = True
if line.startswith('<p>References <a'):
if bInModuleEntry:
ModuleEntryDelEnd = index - 1
bInModuleEntry = False
elif bInEfiMain:
EfiMainDelEnd = index - 1
bInEfiMain = False
if bInModuleEntry:
if line.startswith('</dl>'):
ModuleEntryDlCount = ModuleEntryDlCount + 1
if ModuleEntryDlCount == 1:
ModuleEntryDelStart = index + 1
if bInEfiMain:
if line.startswith('</dl>'):
EfiMainDlCount = EfiMainDlCount + 1
if EfiMainDlCount == 1:
EfiMainDelStart = index + 1
if EfiMainDelEnd > EfiMainDelStart:
for index in range(EfiMainDelEnd, EfiMainDelStart, -1):
del lines[index]
if ModuleEntryDelEnd > ModuleEntryDelStart:
for index in range(ModuleEntryDelEnd, ModuleEntryDelStart, -1):
del lines[index]
try:
f = open(path, 'w')
f.write('\n'.join(lines))
f.close()
except:
logging.getLogger().error(" <<< Fail to fixup file %s" % path)
return
print " <<< Finish to fixup file %s\n" % path
def FixPageUefiApplicationEntryPoint(path, text):
print ' >>> Fixup file reference MdePkg/Include/Library/UefiApplicationEntryPoint.h at file %s \n' % path
lines = text.split('\n')
bInModuleEntry = False
bInEfiMain = False
ModuleEntryDlCount = 0
ModuleEntryDelStart = 0
ModuleEntryDelEnd = 0
EfiMainDlCount = 0
EfiMainDelStart = 0
EfiMainDelEnd = 0
for index in range(len(lines)):
line = lines[index].strip()
if line.find('EFI_STATUS</a> EFIAPI _ModuleEntryPoint </td>') != -1:
bInModuleEntry = True
if line.find('EFI_STATUS</a> EFIAPI EfiMain </td>') != -1:
bInEfiMain = True
if line.startswith('<p>References <a'):
if bInModuleEntry:
ModuleEntryDelEnd = index - 1
bInModuleEntry = False
elif bInEfiMain:
EfiMainDelEnd = index - 1
bInEfiMain = False
if bInModuleEntry:
if line.startswith('</dl>'):
ModuleEntryDlCount = ModuleEntryDlCount + 1
if ModuleEntryDlCount == 1:
ModuleEntryDelStart = index + 1
if bInEfiMain:
if line.startswith('</dl>'):
EfiMainDlCount = EfiMainDlCount + 1
if EfiMainDlCount == 1:
EfiMainDelStart = index + 1
if EfiMainDelEnd > EfiMainDelStart:
for index in range(EfiMainDelEnd, EfiMainDelStart, -1):
del lines[index]
if ModuleEntryDelEnd > ModuleEntryDelStart:
for index in range(ModuleEntryDelEnd, ModuleEntryDelStart, -1):
del lines[index]
try:
f = open(path, 'w')
f.write('\n'.join(lines))
f.close()
except:
logging.getLogger().error(" <<< Fail to fixup file %s" % path)
return
print " <<< Finish to fixup file %s\n" % path
if __name__ == '__main__':
wspath, pkgpath, doxpath, outpath, archtag, docmode, isinc, hwpath = parseCmdArgs()
# configure logging system
logfilepath = os.path.join(outpath, 'log.txt')
logging.basicConfig(format='%(levelname)-8s %(message)s', level=logging.DEBUG)
# create package model object firstly
pkgObj = createPackageObject(wspath, pkgpath)
if pkgObj == None:
sys.exit(-1)
# create doxygen action model
arch = None
tooltag = None
if archtag.lower() != 'all':
arch = archtag.split('_')[0]
tooltag = archtag.split('_')[1]
else:
arch = 'all'
tooltag = 'all'
# preprocess package and call doxygen
try:
action = doxygengen.PackageDocumentAction(doxpath,
hwpath,
outpath,
pkgObj,
docmode,
callbackLogMessage,
arch,
tooltag,
isinc,
True)
action.RegisterCallbackDoxygenProcess(callbackCreateDoxygenProcess)
action.Generate()
except:
message = traceback.format_exception(*sys.exc_info())
logging.getLogger().error('Fail to create doxygen action! \n%s' % ''.join(message))
sys.exit(-1)
DocumentFixup(outpath, arch)
# generate CHM is necessary
if docmode.lower() == 'chm':
indexpath = os.path.join(outpath, 'html', 'index.hhp')
if sys.platform == 'win32':
cmd = '"%s" %s' % (hwpath, indexpath)
else:
cmd = '%s %s' % (hwpath, indexpath)
subprocess.call(cmd)
print '\nFinish to generate package document! Please open %s for review' % os.path.join(outpath, 'html', 'index.chm')
else:
print '\nFinish to generate package document! Please open %s for review' % os.path.join(outpath, 'html', 'index.html')

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#

View File

@ -0,0 +1,12 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#

View File

@ -0,0 +1,449 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
import os
from message import *
class BaseDoxygeItem:
def __init__(self, name, tag=''):
self.mName = name
self.mTag = tag
self.mDescription = ''
self.mText = []
def AddDescription(self, desc):
self.mDescription = '%s%s' % (self.mDescription, desc)
def __str__(self):
return '\n'.join(self.mText)
def Generate(self):
"""This interface need to be override"""
class Section(BaseDoxygeItem):
def Generate(self):
"""This interface need to be override"""
if len(self.mTag) != 0:
self.mText.append(' \section %s %s' % (self.mName, self.mTag))
else:
self.mText.append(' \section %s' % self.mName)
self.mText.append(self.mDescription)
return self.mText
class Page(BaseDoxygeItem):
def __init__(self, name, tag=None, isSort=True):
BaseDoxygeItem.__init__(self, name, tag)
self.mSubPages = []
self.mIsMainPage = False
self.mSections = []
self.mIsSort = isSort
def GetSubpageCount(self):
return len(self.mSubPages)
def AddPage(self, subpage):
self.mSubPages.append(subpage)
return subpage
def AddPages(self, pageArray):
if pageArray == None:
return
for page in pageArray:
self.AddPage(page)
def AddSection(self, section):
self.mSections.append(section)
self.mSections.sort(cmp=lambda x,y: cmp(x.mName.lower(), y.mName.lower()))
def Generate(self):
if self.mIsMainPage:
self.mText.append('/** \mainpage %s' % self.mName)
self.mIsSort = False
else:
self.mText.append('/** \page %s %s' % (self.mTag, self.mName))
if len(self.mDescription) != 0:
self.mText.append(self.mDescription)
endIndex = len(self.mText)
self.mSections.sort()
for sect in self.mSections:
self.mText += sect.Generate()
endIndex = len(self.mText)
if len(self.mSubPages) != 0:
self.mText.insert(endIndex, "<p> \section content_index INDEX")
endIndex = len(self.mText)
self.mText.insert(endIndex, '<ul>')
endIndex += 1
if self.mIsSort:
self.mSubPages.sort(cmp=lambda x,y: cmp(x.mName.lower(), y.mName.lower()))
for page in self.mSubPages:
self.mText.insert(endIndex, '<li>\subpage %s \"%s\" </li>' % (page.mTag, page.mName))
endIndex += 1
self.mText += page.Generate()
self.mText.insert(endIndex, '</ul>')
endIndex += 1
self.mText.insert(endIndex, ' **/')
return self.mText
class DoxygenFile(Page):
def __init__(self, name, file):
Page.__init__(self, name)
self.mFilename = file
self.mIsMainPage = True
def GetFilename(self):
return self.mFilename.replace('/', '\\')
def Save(self):
str = self.Generate()
try:
f = open(self.mFilename, 'w')
f.write('\n'.join(str))
f.close()
except IOError, e:
ErrorMsg ('Fail to write file %s' % self.mFilename)
return False
return True
doxygenConfigTemplate = """
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = %(ProjectName)s
PROJECT_NUMBER = %(ProjectVersion)s
OUTPUT_DIRECTORY = %(OutputDir)s
CREATE_SUBDIRS = YES
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class " \\
"The $name widget " \\
"The $name file " \\
is \\
provides \\
specifies \\
contains \\
represents \\
a \\
an \\
the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH = %(StripPath)s
STRIP_FROM_INC_PATH =
SHORT_NAMES = YES
JAVADOC_AUTOBRIEF = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = YES
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 1
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
DISTRIBUTE_GROUP_DOC = YES
SUBGROUPING = YES
TYPEDEF_HIDES_STRUCT = NO
EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = NO
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_BY_SCOPE_NAME = YES
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = NO
SHOW_DIRECTORIES = NO
FILE_VERSION_FILTER =
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = YES
WARN_FORMAT = "$file:$line: $text "
WARN_LOGFILE = %(WarningFile)s
INPUT = %(FileList)s
INPUT_ENCODING = UTF-8
FILE_PATTERNS = %(Pattern)s
RECURSIVE = NO
EXCLUDE = *.svn
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = .svn
EXCLUDE_SYMBOLS =
EXAMPLE_PATH = %(ExamplePath)s
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = NO
USE_HTAGS = NO
VERBATIM_HEADERS = NO
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = %(WhetherGenerateHtmlHelp)s
HTML_DYNAMIC_SECTIONS = NO
CHM_FILE = index.chm
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = %(WhetherGenerateTreeView)s
TREEVIEW_WIDTH = 250
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
GENERATE_AUTOGEN_DEF = NO
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH = %(IncludePath)s
INCLUDE_FILE_PATTERNS = *.h
PREDEFINED = %(PreDefined)s
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = NO
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
CLASS_DIAGRAMS = NO
MSCGEN_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = YES
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
SEARCHENGINE = NO
"""
class DoxygenConfigFile:
def __init__(self):
self.mProjectName = ''
self.mOutputDir = ''
self.mFileList = []
self.mIncludeList = []
self.mStripPath = ''
self.mExamplePath = ''
self.mPattern = ['*.c', '*.h',
'*.asm', '*.s', '.nasm', '*.html', '*.dox']
self.mMode = 'HTML'
self.mWarningFile = ''
self.mPreDefined = []
self.mProjectVersion = 0.1
def SetChmMode(self):
self.mMode = 'CHM'
def SetHtmlMode(self):
self.mMode = 'HTML'
def SetProjectName(self, str):
self.mProjectName = str
def SetProjectVersion(self, str):
self.mProjectVersion = str
def SetOutputDir(self, str):
self.mOutputDir = str
def SetStripPath(self, str):
self.mStripPath = str
def SetExamplePath(self, str):
self.mExamplePath = str
def SetWarningFilePath(self, str):
self.mWarningFile = str.replace('\\', '/')
def FileExists(self, path):
if path == None:
return False
if len(path) == 0:
return False
for p in self.mFileList:
if path.lower() == p.lower():
return True
return False
def AddFile(self, path):
if path == None:
return
if len(path) == 0:
return
path = path.replace('\\', '/')
if not self.FileExists(path):
self.mFileList.append(path)
def AddIncludePath(self, path):
path = path.replace('\\', '/')
if path not in self.mIncludeList:
self.mIncludeList.append(path)
def AddPattern(self, pattern):
self.mPattern.append(pattern)
def AddPreDefined(self, macro):
self.mPreDefined.append(macro)
def Generate(self, path):
files = ' \\\n'.join(self.mFileList)
includes = ' \\\n'.join(self.mIncludeList)
patterns = ' \\\n'.join(self.mPattern)
if self.mMode.lower() == 'html':
sHtmlHelp = 'NO'
sTreeView = 'YES'
else:
sHtmlHelp = 'YES'
sTreeView = 'NO'
text = doxygenConfigTemplate % {'ProjectName':self.mProjectName,
'OutputDir':self.mOutputDir,
'StripPath':self.mStripPath,
'ExamplePath':self.mExamplePath,
'FileList':files,
'Pattern':patterns,
'WhetherGenerateHtmlHelp':sHtmlHelp,
'WhetherGenerateTreeView':sTreeView,
'IncludePath':includes,
'WarningFile':self.mWarningFile,
'PreDefined':' '.join(self.mPreDefined),
'ProjectVersion':self.mProjectVersion}
try:
f = open(path, 'w')
f.write(text)
f.close()
except IOError, e:
ErrorMsg ('Fail to generate doxygen config file %s' % path)
return False
return True
########################################################################
# TEST CODE
########################################################################
if __name__== '__main__':
df = DoxygenFile('Platform Document', 'm:\tree')
df.AddPage(Page('Module', 'module'))
p = df.AddPage(Page('Library', 'library'))
p.AddDescription(desc)
p.AddPage(Page('PCD', 'pcds'))
df.Generate()
print df

View File

@ -0,0 +1,611 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
import array
import uuid
import re
import os
import logging
import core.pe as pe
def GetLogger():
return logging.getLogger('EFI Binary File')
class EFIBinaryError(Exception):
def __init__(self, message):
Exception.__init__(self)
self._message = message
def GetMessage(self):
return self._message
class EfiFd(object):
EFI_FV_HEADER_SIZE = 0x48
def __init__(self):
self._fvs = []
def Load(self, fd, size):
index = fd.tell()
while (index + self.EFI_FV_HEADER_SIZE < size):
fv = EfiFv(self)
fv.Load(fd)
self._fvs.append(fv)
index += fv.GetHeader().GetFvLength()
index = align(index, 8)
fd.seek(index)
def GetFvs(self):
return self._fvs
class EfiFv(object):
FILE_SYSTEM_GUID = uuid.UUID('{8c8ce578-8a3d-4f1c-9935-896185c32dd3}')
def __init__(self, parent=None):
self._size = 0
self._filename = None
self._fvheader = None
self._blockentries = []
self._ffs = []
# following field is for FV in FD
self._parent = parent
self._offset = 0
self._raw = array.array('B')
def Load(self, fd):
self._offset = fd.tell()
self._filename = fd.name
# get file header
self._fvheader = EfiFirmwareVolumeHeader.Read(fd)
#self._fvheader.Dump()
self._size = self._fvheader.GetFvLength()
if self._fvheader.GetFileSystemGuid() != self.FILE_SYSTEM_GUID:
fd.seek(self._offset)
self._raw.fromfile(fd, self.GetHeader().GetFvLength())
return
# read block map
blockentry = BlockMapEntry.Read(fd)
self._blockentries.append(blockentry)
while (blockentry.GetNumberBlocks() != 0 and blockentry.GetLength() != 0):
self._blockentries.append(blockentry)
blockentry = BlockMapEntry.Read(fd)
if self._fvheader.GetSize() + (len(self._blockentries)) * 8 != \
self._fvheader.GetHeaderLength():
raise EFIBinaryError("Volume Header length not consistent with block map!")
index = align(fd.tell(), 8)
count = 0
while ((index + EfiFfs.FFS_HEADER_SIZE) < self._size):
ffs = EfiFfs.Read(fd, self)
if not isValidGuid(ffs.GetNameGuid()):
break
self._ffs.append(ffs)
count += 1
index = align(fd.tell(), 8)
fd.seek(self._offset)
self._raw.fromfile(fd, self.GetHeader().GetFvLength())
def GetFfs(self):
return self._ffs
def GetHeader(self):
return self._fvheader
def GetBlockEntries(self):
return self._blockentries
def GetHeaderRawData(self):
ret = []
ret += self._fvheader.GetRawData()
for block in self._blockentries:
ret += block.GetRawData()
return ret
def GetOffset(self):
return 0
def GetRawData(self):
return self._raw.tolist()
class BinaryItem(object):
def __init__(self, parent=None):
self._size = 0
self._arr = array.array('B')
self._parent = parent
@classmethod
def Read(cls, fd, parent=None):
item = cls(parent)
item.fromfile(fd)
return item
def Load(self, fd):
self.fromfile(fd)
def GetSize(self):
"""should be implemented by inherited class"""
def fromfile(self, fd):
self._arr.fromfile(fd, self.GetSize())
def GetParent(self):
return self._parent
class EfiFirmwareVolumeHeader(BinaryItem):
def GetSize(self):
return 56
def GetSigunature(self):
list = self._arr.tolist()
sig = ''
for x in list[40:44]:
sig += chr(x)
return sig
def GetAttribute(self):
return list2int(self._arr.tolist()[44:48])
def GetErasePolarity(self):
list = self.GetAttrStrings()
if 'EFI_FVB2_ERASE_POLARITY' in list:
return True
return False
def GetAttrStrings(self):
list = []
value = self.GetAttribute()
if (value & 0x01) != 0:
list.append('EFI_FVB2_READ_DISABLED_CAP')
if (value & 0x02) != 0:
list.append('EFI_FVB2_READ_ENABLED_CAP')
if (value & 0x04) != 0:
list.append('EFI_FVB2_READ_STATUS')
if (value & 0x08) != 0:
list.append('EFI_FVB2_WRITE_DISABLED_CAP')
if (value & 0x10) != 0:
list.append('EFI_FVB2_WRITE_ENABLED_CAP')
if (value & 0x20) != 0:
list.append('EFI_FVB2_WRITE_STATUS')
if (value & 0x40) != 0:
list.append('EFI_FVB2_LOCK_CAP')
if (value & 0x80) != 0:
list.append('EFI_FVB2_LOCK_STATUS')
if (value & 0x200) != 0:
list.append('EFI_FVB2_STICKY_WRITE')
if (value & 0x400) != 0:
list.append('EFI_FVB2_MEMORY_MAPPED')
if (value & 0x800) != 0:
list.append('EFI_FVB2_ERASE_POLARITY')
if (value & 0x1000) != 0:
list.append('EFI_FVB2_READ_LOCK_CAP')
if (value & 0x00002000) != 0:
list.append('EFI_FVB2_READ_LOCK_STATUS')
if (value & 0x00004000) != 0:
list.append('EFI_FVB2_WRITE_LOCK_CAP')
if (value & 0x00008000) != 0:
list.append('EFI_FVB2_WRITE_LOCK_STATUS')
if (value == 0):
list.append('EFI_FVB2_ALIGNMENT_1')
if (value & 0x001F0000) == 0x00010000:
list.append('EFI_FVB2_ALIGNMENT_2')
if (value & 0x001F0000) == 0x00020000:
list.append('EFI_FVB2_ALIGNMENT_4')
if (value & 0x001F0000) == 0x00030000:
list.append('EFI_FVB2_ALIGNMENT_8')
if (value & 0x001F0000) == 0x00040000:
list.append('EFI_FVB2_ALIGNMENT_16')
if (value & 0x001F0000) == 0x00050000:
list.append('EFI_FVB2_ALIGNMENT_32')
if (value & 0x001F0000) == 0x00060000:
list.append('EFI_FVB2_ALIGNMENT_64')
if (value & 0x001F0000) == 0x00070000:
list.append('EFI_FVB2_ALIGNMENT_128')
if (value & 0x001F0000) == 0x00080000:
list.append('EFI_FVB2_ALIGNMENT_256')
if (value & 0x001F0000) == 0x00090000:
list.append('EFI_FVB2_ALIGNMENT_512')
if (value & 0x001F0000) == 0x000A0000:
list.append('EFI_FVB2_ALIGNMENT_1K')
if (value & 0x001F0000) == 0x000B0000:
list.append('EFI_FVB2_ALIGNMENT_2K')
if (value & 0x001F0000) == 0x000C0000:
list.append('EFI_FVB2_ALIGNMENT_4K')
if (value & 0x001F0000) == 0x000D0000:
list.append('EFI_FVB2_ALIGNMENT_8K')
if (value & 0x001F0000) == 0x000E0000:
list.append('EFI_FVB2_ALIGNMENT_16K')
if (value & 0x001F0000) == 0x000F0000:
list.append('EFI_FVB2_ALIGNMENT_32K')
if (value & 0x001F0000) == 0x00100000:
list.append('EFI_FVB2_ALIGNMENT_64K')
if (value & 0x001F0000) == 0x00110000:
list.append('EFI_FVB2_ALIGNMENT_128K')
if (value & 0x001F0000) == 0x00120000:
list.append('EFI_FVB2_ALIGNMENT_256K')
if (value & 0x001F0000) == 0x00130000:
list.append('EFI_FVB2_ALIGNMENT_512K')
return list
def GetHeaderLength(self):
return list2int(self._arr.tolist()[48:50])
def Dump(self):
print 'Signature: %s' % self.GetSigunature()
print 'Attribute: 0x%X' % self.GetAttribute()
print 'Header Length: 0x%X' % self.GetHeaderLength()
print 'File system Guid: ', self.GetFileSystemGuid()
print 'Revision: 0x%X' % self.GetRevision()
print 'FvLength: 0x%X' % self.GetFvLength()
def GetFileSystemGuid(self):
list = self._arr.tolist()
return list2guid(list[16:32])
def GetRevision(self):
list = self._arr.tolist()
return int(list[55])
def GetFvLength(self):
list = self._arr.tolist()
return list2int(list[32:40])
def GetRawData(self):
return self._arr.tolist()
class BlockMapEntry(BinaryItem):
def GetSize(self):
return 8
def GetNumberBlocks(self):
list = self._arr.tolist()
return list2int(list[0:4])
def GetLength(self):
list = self._arr.tolist()
return list2int(list[4:8])
def GetRawData(self):
return self._arr.tolist()
def __str__(self):
return '[BlockEntry] Number = 0x%X, length=0x%X' % (self.GetNumberBlocks(), self.GetLength())
class EfiFfs(object):
FFS_HEADER_SIZE = 24
def __init__(self, parent=None):
self._header = None
# following field is for FFS in FV file.
self._parent = parent
self._offset = 0
self._sections = []
def Load(self, fd):
self._offset = align(fd.tell(), 8)
self._header = EfiFfsHeader.Read(fd, self)
if not isValidGuid(self.GetNameGuid()):
return
index = self._offset
fileend = self._offset + self.GetSize()
while (index + EfiSection.EFI_SECTION_HEADER_SIZE < fileend):
section = EfiSection(self)
section.Load(fd)
if section.GetSize() == 0 and section.GetHeader().GetType() == 0:
break
self._sections.append(section)
index = fd.tell()
# rebase file pointer to next ffs file
index = self._offset + self._header.GetFfsSize()
index = align(index, 8)
fd.seek(index)
def GetOffset(self):
return self._offset
def GetSize(self):
return self._header.GetFfsSize()
@classmethod
def Read(cls, fd, parent=None):
item = cls(parent)
item.Load(fd)
return item
def GetNameGuid(self):
return self._header.GetNameGuid()
def DumpContent(self):
list = self._content.tolist()
line = []
count = 0
for item in list:
if count < 32:
line.append('0x%X' % int(item))
count += 1
else:
print ' '.join(line)
count = 0
line = []
line.append('0x%X' % int(item))
count += 1
def GetHeader(self):
return self._header
def GetParent(self):
return self._parent
def GetSections(self):
return self._sections
class EfiFfsHeader(BinaryItem):
ffs_state_map = {0x01:'EFI_FILE_HEADER_CONSTRUCTION',
0x02:'EFI_FILE_HEADER_VALID',
0x04:'EFI_FILE_DATA_VALID',
0x08:'EFI_FILE_MARKED_FOR_UPDATE',
0x10:'EFI_FILE_DELETED',
0x20:'EFI_FILE_HEADER_INVALID'}
def GetSize(self):
return 24
def GetNameGuid(self):
list = self._arr.tolist()
return list2guid(list[0:16])
def GetType(self):
list = self._arr.tolist()
return int(list[18])
def GetTypeString(self):
value = self.GetType()
if value == 0x01:
return 'EFI_FV_FILETYPE_RAW'
if value == 0x02:
return 'EFI_FV_FILETYPE_FREEFORM'
if value == 0x03:
return 'EFI_FV_FILETYPE_SECURITY_CORE'
if value == 0x04:
return 'EFI_FV_FILETYPE_PEI_CORE'
if value == 0x05:
return 'EFI_FV_FILETYPE_DXE_CORE'
if value == 0x06:
return 'EFI_FV_FILETYPE_PEIM'
if value == 0x07:
return 'EFI_FV_FILETYPE_DRIVER'
if value == 0x08:
return 'EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER'
if value == 0x09:
return 'EFI_FV_FILETYPE_APPLICATION'
if value == 0x0B:
return 'EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE'
if value == 0xc0:
return 'EFI_FV_FILETYPE_OEM_MIN'
if value == 0xdf:
return 'EFI_FV_FILETYPE_OEM_MAX'
if value == 0xe0:
return 'EFI_FV_FILETYPE_DEBUG_MIN'
if value == 0xef:
return 'EFI_FV_FILETYPE_DEBUG_MAX'
if value == 0xf0:
return 'EFI_FV_FILETYPE_FFS_PAD'
if value == 0xff:
return 'EFI_FV_FILETYPE_FFS_MAX'
return 'Unknown FFS Type'
def GetAttributes(self):
list = self._arr.tolist()
return int(list[19])
def GetFfsSize(self):
list = self._arr.tolist()
return list2int(list[20:23])
def GetState(self):
list = self._arr.tolist()
state = int(list[23])
polarity = self.GetParent().GetParent().GetHeader().GetErasePolarity()
if polarity:
state = (~state) & 0xFF
HighestBit = 0x80
while (HighestBit != 0) and (HighestBit & state) == 0:
HighestBit = HighestBit >> 1
return HighestBit
def GetStateString(self):
state = self.GetState()
if state in self.ffs_state_map.keys():
return self.ffs_state_map[state]
return 'Unknown Ffs State'
def Dump(self):
print "FFS name: ", self.GetNameGuid()
print "FFS type: ", self.GetType()
print "FFS attr: 0x%X" % self.GetAttributes()
print "FFS size: 0x%X" % self.GetFfsSize()
print "FFS state: 0x%X" % self.GetState()
def GetRawData(self):
return self._arr.tolist()
class EfiSection(object):
EFI_SECTION_HEADER_SIZE = 4
def __init__(self, parent=None):
self._size = 0
self._parent = parent
self._offset = 0
self._contents = array.array('B')
def Load(self, fd):
self._offset = align(fd.tell(), 4)
self._header = EfiSectionHeader.Read(fd, self)
if self._header.GetTypeString() == "EFI_SECTION_PE32":
pefile = pe.PEFile(self)
pefile.Load(fd, self.GetContentSize())
fd.seek(self._offset)
self._contents.fromfile(fd, self.GetContentSize())
# rebase file pointer to next section
index = self._offset + self.GetSize()
index = align(index, 4)
fd.seek(index)
def GetContentSize(self):
return self.GetSize() - self.EFI_SECTION_HEADER_SIZE
def GetContent(self):
return self._contents.tolist()
def GetSize(self):
return self._header.GetSectionSize()
def GetHeader(self):
return self._header
def GetSectionOffset(self):
return self._offset + self.EFI_SECTION_HEADER_SIZE
class EfiSectionHeader(BinaryItem):
section_type_map = {0x01: 'EFI_SECTION_COMPRESSION',
0x02: 'EFI_SECTION_GUID_DEFINED',
0x10: 'EFI_SECTION_PE32',
0x11: 'EFI_SECTION_PIC',
0x12: 'EFI_SECTION_TE',
0x13: 'EFI_SECTION_DXE_DEPEX',
0x14: 'EFI_SECTION_VERSION',
0x15: 'EFI_SECTION_USER_INTERFACE',
0x16: 'EFI_SECTION_COMPATIBILITY16',
0x17: 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE',
0x18: 'EFI_SECTION_FREEFORM_SUBTYPE_GUID',
0x19: 'EFI_SECTION_RAW',
0x1B: 'EFI_SECTION_PEI_DEPEX'}
def GetSize(self):
return 4
def GetSectionSize(self):
list = self._arr.tolist()
return list2int(list[0:3])
def GetType(self):
list = self._arr.tolist()
return int(list[3])
def GetTypeString(self):
type = self.GetType()
if type not in self.section_type_map.keys():
return 'Unknown Section Type'
return self.section_type_map[type]
def Dump(self):
print 'size = 0x%X' % self.GetSectionSize()
print 'type = 0x%X' % self.GetType()
rMapEntry = re.compile('^(\w+)[ \(\w\)]* \(BaseAddress=([0-9a-fA-F]+), EntryPoint=([0-9a-fA-F]+), GUID=([0-9a-fA-F\-]+)')
class EfiFvMapFile(object):
def __init__(self):
self._mapentries = {}
def Load(self, path):
if not os.path.exists(path):
return False
try:
file = open(path, 'r')
lines = file.readlines()
file.close()
except:
return False
for line in lines:
if line[0] != ' ':
# new entry
ret = rMapEntry.match(line)
if ret != None:
name = ret.groups()[0]
baseaddr = int(ret.groups()[1], 16)
entry = int(ret.groups()[2], 16)
guidstr = '{' + ret.groups()[3] + '}'
guid = uuid.UUID(guidstr)
self._mapentries[guid] = EfiFvMapFileEntry(name, baseaddr, entry, guid)
return True
def GetEntry(self, guid):
if guid in self._mapentries.keys():
return self._mapentries[guid]
return None
class EfiFvMapFileEntry(object):
def __init__(self, name, baseaddr, entry, guid):
self._name = name
self._baseaddr = baseaddr
self._entry = entry
self._guid = guid
def GetName(self):
return self._name
def GetBaseAddress(self):
return self._baseaddr
def GetEntryPoint(self):
return self._entry
def list2guid(list):
val1 = list2int(list[0:4])
val2 = list2int(list[4:6])
val3 = list2int(list[6:8])
val4 = 0
for item in list[8:16]:
val4 = (val4 << 8) | int(item)
val = val1 << 12 * 8 | val2 << 10 * 8 | val3 << 8 * 8 | val4
guid = uuid.UUID(int=val)
return guid
def list2int(list):
val = 0
for index in range(len(list) - 1, -1, -1):
val = (val << 8) | int(list[index])
return val
def align(value, alignment):
return (value + ((alignment - value) & (alignment - 1)))
gInvalidGuid = uuid.UUID(int=0xffffffffffffffffffffffffffffffff)
def isValidGuid(guid):
if guid == gInvalidGuid:
return False
return True

View File

@ -0,0 +1,480 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
from message import *
import re
import os
section_re = re.compile(r'^\[([\w., "]+)\]')
class BaseINIFile(object):
_objs = {}
def __new__(cls, *args, **kwargs):
"""Maintain only a single instance of this object
@return: instance of this class
"""
if len(args) == 0: return object.__new__(cls, *args, **kwargs)
filename = args[0]
parent = None
if len(args) > 1:
parent = args[1]
key = os.path.normpath(filename)
if key not in cls._objs.keys():
cls._objs[key] = object.__new__(cls, *args, **kwargs)
if parent != None:
cls._objs[key].AddParent(parent)
return cls._objs[key]
def __init__(self, filename=None, parent=None):
self._lines = []
self._sections = {}
self._filename = filename
self._globals = []
self._isModify = True
def AddParent(self, parent):
if parent == None: return
if not hasattr(self, "_parents"):
self._parents = []
if parent in self._parents:
ErrorMsg("Duplicate parent is found for INI file %s" % self._filename)
return
self._parents.append(parent)
def GetFilename(self):
return os.path.normpath(self._filename)
def IsModified(self):
return self._isModify
def Modify(self, modify=True, obj=None):
if modify == self._isModify: return
self._isModify = modify
if modify:
for parent in self._parents:
parent.Modify(True, self)
def _ReadLines(self, filename):
#
# try to open file
#
if not os.path.exists(filename):
return False
try:
handle = open(filename, 'r')
self._lines = handle.readlines()
handle.close()
except:
raise EdkException("Fail to open file %s" % filename)
return True
def GetSectionInstance(self, parent, name, isCombined=False):
return BaseINISection(parent, name, isCombined)
def GetSectionByName(self, name):
arr = []
for key in self._sections.keys():
if '.private' in key:
continue
for item in self._sections[key]:
if item.GetBaseName().lower().find(name.lower()) != -1:
arr.append(item)
return arr
def GetSectionObjectsByName(self, name):
arr = []
sects = self.GetSectionByName(name)
for sect in sects:
for obj in sect.GetObjects():
arr.append(obj)
return arr
def Parse(self):
if not self._isModify: return True
if not self._ReadLines(self._filename): return False
sObjs = []
inGlobal = True
# process line
for index in range(len(self._lines)):
templine = self._lines[index].strip()
# skip comments
if len(templine) == 0: continue
if re.match("^\[=*\]", templine) or re.match("^#", templine) or \
re.match("\*+/", templine):
continue
m = section_re.match(templine)
if m!= None: # found a section
inGlobal = False
# Finish the latest section first
if len(sObjs) != 0:
for sObj in sObjs:
sObj._end = index - 1
if not sObj.Parse():
ErrorMsg("Fail to parse section %s" % sObj.GetBaseName(),
self._filename,
sObj._start)
# start new section
sname_arr = m.groups()[0].split(',')
sObjs = []
for name in sname_arr:
sObj = self.GetSectionInstance(self, name, (len(sname_arr) > 1))
sObj._start = index
sObjs.append(sObj)
if not self._sections.has_key(name.lower()):
self._sections[name.lower()] = [sObj]
else:
self._sections[name.lower()].append(sObj)
elif inGlobal: # not start any section and find global object
gObj = BaseINIGlobalObject(self)
gObj._start = index
gObj.Parse()
self._globals.append(gObj)
# Finish the last section
if len(sObjs) != 0:
for sObj in sObjs:
sObj._end = index
if not sObj.Parse():
ErrorMsg("Fail to parse section %s" % sObj.GetBaseName(),
self._filename,
sObj._start)
self._isModify = False
return True
def Destroy(self, parent):
# check referenced parent
if parent != None:
assert parent in self._parents, "when destory ini object, can not found parent reference!"
self._parents.remove(parent)
if len(self._parents) != 0: return
for sects in self._sections.values():
for sect in sects:
sect.Destroy()
# dereference from _objs array
assert self.GetFilename() in self._objs.keys(), "When destroy ini object, can not find obj reference!"
assert self in self._objs.values(), "When destroy ini object, can not find obj reference!"
del self._objs[self.GetFilename()]
# dereference self
self.Clear()
def GetDefine(self, name):
sects = self.GetSectionByName('Defines')
for sect in sects:
for obj in sect.GetObjects():
line = obj.GetLineByOffset(obj._start).split('#')[0].strip()
arr = line.split('=')
if arr[0].strip().lower() == name.strip().lower():
return arr[1].strip()
return None
def Clear(self):
for sects in self._sections.values():
for sect in sects:
del sect
self._sections.clear()
for gObj in self._globals:
del gObj
del self._globals[:]
del self._lines[:]
def Reload(self):
self.Clear()
ret = self.Parse()
if ret:
self._isModify = False
return ret
def AddNewSection(self, sectName):
if sectName.lower() in self._sections.keys():
ErrorMsg('Section %s can not be created for conflict with existing section')
return None
sectionObj = self.GetSectionInstance(self, sectName)
sectionObj._start = len(self._lines)
sectionObj._end = len(self._lines) + 1
self._lines.append('[%s]\n' % sectName)
self._lines.append('\n\n')
self._sections[sectName.lower()] = sectionObj
return sectionObj
def CopySectionsByName(self, oldDscObj, nameStr):
sects = oldDscObj.GetSectionByName(nameStr)
for sect in sects:
sectObj = self.AddNewSection(sect.GetName())
sectObj.Copy(sect)
def __str__(self):
return ''.join(self._lines)
## Get file header's comment from basic INI file.
# The file comments has two style:
# 1) #/** @file
# 2) ## @file
#
def GetFileHeader(self):
desc = []
lineArr = self._lines
inHeader = False
for num in range(len(self._lines)):
line = lineArr[num].strip()
if not inHeader and (line.startswith("#/**") or line.startswith("##")) and \
line.find("@file") != -1:
inHeader = True
continue
if inHeader and (line.startswith("#**/") or line.startswith('##')):
inHeader = False
break
if inHeader:
prefixIndex = line.find('#')
if prefixIndex == -1:
desc.append(line)
else:
desc.append(line[prefixIndex + 1:])
return '<br>\n'.join(desc)
class BaseINISection(object):
def __init__(self, parent, name, isCombined=False):
self._parent = parent
self._name = name
self._isCombined = isCombined
self._start = 0
self._end = 0
self._objs = []
def __del__(self):
for obj in self._objs:
del obj
del self._objs[:]
def GetName(self):
return self._name
def GetObjects(self):
return self._objs
def GetParent(self):
return self._parent
def GetStartLinenumber(self):
return self._start
def GetEndLinenumber(self):
return self._end
def GetLine(self, linenumber):
return self._parent._lines[linenumber]
def GetFilename(self):
return self._parent.GetFilename()
def GetSectionINIObject(self, parent):
return BaseINISectionObject(parent)
def Parse(self):
# skip first line in section, it is used by section name
visit = self._start + 1
iniObj = None
while (visit <= self._end):
line = self.GetLine(visit).strip()
if re.match("^\[=*\]", line) or re.match("^#", line) or len(line) == 0:
visit += 1
continue
line = line.split('#')[0].strip()
if iniObj != None:
if line.endswith('}'):
iniObj._end = visit - self._start
if not iniObj.Parse():
ErrorMsg("Fail to parse ini object",
self.GetFilename(),
iniObj.GetStartLinenumber())
else:
self._objs.append(iniObj)
iniObj = None
else:
iniObj = self.GetSectionINIObject(self)
iniObj._start = visit - self._start
if not line.endswith('{'):
iniObj._end = visit - self._start
if not iniObj.Parse():
ErrorMsg("Fail to parse ini object",
self.GetFilename(),
iniObj.GetStartLinenumber())
else:
self._objs.append(iniObj)
iniObj = None
visit += 1
return True
def Destroy(self):
for obj in self._objs:
obj.Destroy()
def GetBaseName(self):
return self._name
def AddLine(self, line):
end = self.GetEndLinenumber()
self._parent._lines.insert(end, line)
self._end += 1
def Copy(self, sectObj):
index = sectObj.GetStartLinenumber() + 1
while index < sectObj.GetEndLinenumber():
line = sectObj.GetLine(index)
if not line.strip().startswith('#'):
self.AddLine(line)
index += 1
def AddObject(self, obj):
lines = obj.GenerateLines()
for line in lines:
self.AddLine(line)
def GetComment(self):
comments = []
start = self._start - 1
bFound = False
while (start > 0):
line = self.GetLine(start).strip()
if len(line) == 0:
start -= 1
continue
if line.startswith('##'):
bFound = True
index = line.rfind('#')
if (index + 1) < len(line):
comments.append(line[index + 1:])
break
if line.startswith('#'):
start -= 1
continue
break
if bFound:
end = start + 1
while (end < self._start):
line = self.GetLine(end).strip()
if len(line) == 0: break
if not line.startswith('#'): break
index = line.rfind('#')
if (index + 1) < len(line):
comments.append(line[index + 1:])
end += 1
return comments
class BaseINIGlobalObject(object):
def __init__(self, parent):
self._start = 0
self._end = 0
def Parse(self):
return True
def __str__(self):
return parent._lines[self._start]
def __del__(self):
pass
class BaseINISectionObject(object):
def __init__(self, parent):
self._start = 0
self._end = 0
self._parent = parent
def __del__(self):
self._parent = None
def GetParent(self):
return self._parent
def GetFilename(self):
return self.GetParent().GetFilename()
def GetPackageName(self):
return self.GetFilename()
def GetFileObj(self):
return self.GetParent().GetParent()
def GetStartLinenumber(self):
return self.GetParent()._start + self._start
def GetLineByOffset(self, offset):
sect_start = self._parent.GetStartLinenumber()
linenumber = sect_start + offset
return self._parent.GetLine(linenumber)
def GetLinenumberByOffset(self, offset):
return offset + self._parent.GetStartLinenumber()
def Parse(self):
return True
def Destroy(self):
pass
def __str__(self):
return self.GetLineByOffset(self._start).strip()
def GenerateLines(self):
return ['default setion object string\n']
def GetComment(self):
comments = []
start = self.GetStartLinenumber() - 1
bFound = False
while (start > 0):
line = self.GetParent().GetLine(start).strip()
if len(line) == 0:
start -= 1
continue
if line.startswith('##'):
bFound = True
index = line.rfind('#')
if (index + 1) < len(line):
comments.append(line[index + 1:])
break
if line.startswith('#'):
start -= 1
continue
break
if bFound:
end = start + 1
while (end <= self.GetStartLinenumber() - 1):
line = self.GetParent().GetLine(end).strip()
if len(line) == 0: break
if not line.startswith('#'): break
index = line.rfind('#')
if (index + 1) < len(line):
comments.append(line[index + 1:])
end += 1
return comments

View File

@ -0,0 +1,23 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
import core.editor
class INIDoc(core.editor.EditorDocument):
def __init__(self):
core.editor.EditorDocument.__init__(self)
self._iniobj = None
class INIView(core.editor.EditorView):
pass

View File

@ -0,0 +1,52 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
def GetEdkLogger():
import logging
return logging.getLogger('edk')
class EdkException(Exception):
def __init__(self, message, fName=None, fNo=None):
self._message = message
ErrorMsg(message, fName, fNo)
def GetMessage(self):
return '[EDK Failure]: %s' %self._message
def ErrorMsg(mess, fName=None, fNo=None):
GetEdkLogger().error(NormalMessage('#ERR#', mess, fName, fNo))
def LogMsg(mess, fName=None, fNo=None):
GetEdkLogger().info(NormalMessage('@LOG@', mess, fName, fNo))
def WarnMsg(mess, fName=None, fNo=None):
GetEdkLogger().warning(NormalMessage('!WAR!', mess, fName, fNo))
def NormalMessage(type, mess, fName=None, fNo=None):
strMsg = type
if fName != None:
strMsg += ' %s' % fName.replace('/', '\\')
if fNo != None:
strMsg += '(%d):' % fNo
else:
strMsg += ' :'
if fName == None and fNo == None:
strMsg += ' '
strMsg += mess
return strMsg

View File

@ -0,0 +1,12 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#

View File

@ -0,0 +1,12 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#

View File

@ -0,0 +1,934 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
import plugins.EdkPlugins.basemodel.ini as ini
import plugins.EdkPlugins.edk2.model.dsc as dsc
import plugins.EdkPlugins.edk2.model.inf as inf
import plugins.EdkPlugins.edk2.model.dec as dec
import os
from plugins.EdkPlugins.basemodel.message import *
class SurfaceObject(object):
_objs = {}
def __new__(cls, *args, **kwargs):
"""Maintain only a single instance of this object
@return: instance of this class
"""
obj = object.__new__(cls, *args, **kwargs)
if not cls._objs.has_key("None"):
cls._objs["None"] = []
cls._objs["None"].append(obj)
return obj
def __init__(self, parent, workspace):
self._parent = parent
self._fileObj = None
self._workspace = workspace
self._isModify = False
self._modifiedObjs = []
def __del__(self):
pass
def Destroy(self):
key = self.GetRelativeFilename()
self.GetFileObj().Destroy(self)
del self._fileObj
# dereference self from _objs arrary
assert self._objs.has_key(key), "when destory, object is not in obj list"
assert self in self._objs[key], "when destory, object is not in obj list"
self._objs[key].remove(self)
if len(self._objs[key]) == 0:
del self._objs[key]
def GetParent(self):
return self._parent
def GetWorkspace(self):
return self._workspace
def GetFileObjectClass(self):
return ini.BaseINIFile
def GetFilename(self):
return self.GetFileObj().GetFilename()
def GetFileObj(self):
return self._fileObj
def GetRelativeFilename(self):
fullPath = self.GetFilename()
return fullPath[len(self._workspace) + 1:]
def Load(self, relativePath):
# if has been loaded, directly return
if self._fileObj != None: return True
relativePath = os.path.normpath(relativePath)
fullPath = os.path.join(self._workspace, relativePath)
fullPath = os.path.normpath(fullPath)
if not os.path.exists(fullPath):
ErrorMsg("file does not exist!", fullPath)
return False
self._fileObj = self.GetFileObjectClass()(fullPath, self)
if not self._fileObj.Parse():
ErrorMsg("Fail to parse file!", fullPath)
return False
# remove self from None list to list with filename as key
cls = self.__class__
if self not in cls._objs["None"]:
ErrorMsg("Sufrace object does not be create into None list")
cls._objs["None"].remove(self)
if not cls._objs.has_key(relativePath):
cls._objs[relativePath] = []
cls._objs[relativePath].append(self)
return True
def Reload(self, force=False):
ret = True
# whether require must be update
if force:
ret = self.GetFileObj().Reload(True)
else:
if self.IsModified():
if self.GetFileObj().IsModified():
ret = self.GetFileObj().Reload()
return ret
def Modify(self, modify=True, modifiedObj=None):
if modify:
#LogMsg("%s is modified, modified object is %s" % (self.GetFilename(), modifiedObj))
if issubclass(modifiedObj.__class__, ini.BaseINIFile) and self._isModify:
return
self._isModify = modify
self.GetParent().Modify(modify, self)
else:
self._isModify = modify
def IsModified(self):
return self._isModify
def GetModifiedObjs(self):
return self._modifiedObjs
def FilterObjsByArch(self, objs, arch):
arr = []
for obj in objs:
if obj.GetArch().lower() == 'common':
arr.append(obj)
continue
if obj.GetArch().lower() == arch.lower():
arr.append(obj)
continue
return arr
class Platform(SurfaceObject):
def __init__(self, parent, workspace):
SurfaceObject.__init__(self, parent, workspace)
self._modules = []
self._packages = []
def Destroy(self):
for module in self._modules:
module.Destroy()
del self._modules[:]
del self._packages[:]
SurfaceObject.Destroy(self)
def GetName(self):
return self.GetFileObj().GetDefine("PLATFORM_NAME")
def GetFileObjectClass(self):
return dsc.DSCFile
def GetModuleCount(self):
if self.GetFileObj() == None:
ErrorMsg("Fail to get module count because DSC file has not been load!")
return len(self.GetFileObj().GetComponents())
def GetSupportArchs(self):
return self.GetFileObj().GetDefine("SUPPORTED_ARCHITECTURES").strip().split('#')[0].split('|')
def LoadModules(self, precallback=None, postcallback=None):
for obj in self.GetFileObj().GetComponents():
mFilename = obj.GetFilename()
if precallback != None:
precallback(self, mFilename)
arch = obj.GetArch()
if arch.lower() == 'common':
archarr = self.GetSupportArchs()
else:
archarr = [arch]
for arch in archarr:
module = Module(self, self.GetWorkspace())
if module.Load(mFilename, arch, obj.GetOveridePcds(), obj.GetOverideLibs()):
self._modules.append(module)
if postcallback != None:
postcallback(self, module)
else:
del module
ErrorMsg("Fail to load module %s" % mFilename)
def GetModules(self):
return self._modules
def GetLibraryPath(self, classname, arch, type):
objs = self.GetFileObj().GetSectionObjectsByName("libraryclasses")
for obj in objs:
if classname.lower() != obj.GetClass().lower():
continue
if obj.GetArch().lower() != 'common' and \
obj.GetArch().lower() != arch.lower():
continue
if obj.GetModuleType().lower() != 'common' and \
obj.GetModuleType().lower() != type.lower():
continue
return obj.GetInstance()
ErrorMsg("Fail to get library class %s [%s][%s] from platform %s" % (classname, arch, type, self.GetFilename()))
return None
def GetPackage(self, path):
package = self.GetParent().GetPackage(path)
if package not in self._packages:
self._packages.append(package)
return package
def GetPcdBuildObjs(self, name, arch=None):
arr = []
objs = self.GetFileObj().GetSectionObjectsByName('pcds')
for obj in objs:
if obj.GetPcdName().lower() == name.lower():
arr.append(obj)
if arch != None:
arr = self.FilterObjsByArch(arr, arch)
return arr
def Reload(self, callback=None):
# do not care force paramter for platform object
isFileChanged = self.GetFileObj().IsModified()
ret = SurfaceObject.Reload(self, False)
if not ret: return False
if isFileChanged:
# destroy all modules and reload them again
for obj in self._modules:
obj.Destroy()
del self._modules[:]
del self._packages[:]
self.LoadModules(callback)
else:
for obj in self._modules:
callback(self, obj.GetFilename())
obj.Reload()
self.Modify(False)
return True
def Modify(self, modify=True, modifiedObj=None):
if modify:
#LogMsg("%s is modified, modified object is %s" % (self.GetFilename(), modifiedObj))
if issubclass(modifiedObj.__class__, ini.BaseINIFile) and self._isModify:
return
self._isModify = modify
self.GetParent().Modify(modify, self)
else:
if self.GetFileObj().IsModified():
return
for obj in self._modules:
if obj.IsModified():
return
self._isModify = modify
self.GetParent().Modify(modify, self)
def GetModuleObject(self, relativePath, arch):
path = os.path.normpath(relativePath)
for obj in self._modules:
if obj.GetRelativeFilename() == path:
if arch.lower() == 'common':
return obj
if obj.GetArch() == arch:
return obj
return None
def GenerateFullReferenceDsc(self):
oldDsc = self.GetFileObj()
newDsc = dsc.DSCFile()
newDsc.CopySectionsByName(oldDsc, 'defines')
newDsc.CopySectionsByName(oldDsc, 'SkuIds')
#
# Dynamic common section should also be copied
#
newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicDefault')
newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicHii')
newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicVpd')
newDsc.CopySectionsByName(oldDsc, 'PcdsDynamicEx')
sects = oldDsc.GetSectionByName('Components')
for oldSect in sects:
newSect = newDsc.AddNewSection(oldSect.GetName())
for oldComObj in oldSect.GetObjects():
module = self.GetModuleObject(oldComObj.GetFilename(), oldSect.GetArch())
if module == None: continue
newComObj = dsc.DSCComponentObject(newSect)
newComObj.SetFilename(oldComObj.GetFilename())
# add all library instance for override section
libdict = module.GetLibraries()
for libclass in libdict.keys():
if libdict[libclass] != None:
newComObj.AddOverideLib(libclass, libdict[libclass].GetRelativeFilename().replace('\\', '/'))
# add all pcds for override section
pcddict = module.GetPcds()
for pcd in pcddict.values():
buildPcd = pcd.GetBuildObj()
buildType = buildPcd.GetPcdType()
buildValue = None
if buildType.lower() == 'pcdsdynamichii' or \
buildType.lower() == 'pcdsdynamicvpd' or \
buildType.lower() == 'pcdsdynamicdefault':
buildType = 'PcdsDynamic'
if buildType != 'PcdsDynamic':
buildValue = buildPcd.GetPcdValue()
newComObj.AddOveridePcd(buildPcd.GetPcdName(),
buildType,
buildValue)
newSect.AddObject(newComObj)
return newDsc
class Module(SurfaceObject):
def __init__(self, parent, workspace):
SurfaceObject.__init__(self, parent, workspace)
self._arch = 'common'
self._parent = parent
self._overidePcds = {}
self._overideLibs = {}
self._libs = {}
self._pcds = {}
self._ppis = []
self._protocols = []
self._depexs = []
self._guids = []
self._packages = []
def Destroy(self):
for lib in self._libs.values():
if lib != None:
lib.Destroy()
self._libs.clear()
for pcd in self._pcds.values():
pcd.Destroy()
self._pcds.clear()
for ppi in self._ppis:
ppi.DeRef(self)
del self._ppis[:]
for protocol in self._protocols:
if protocol != None:
protocol.DeRef(self)
del self._protocols[:]
for guid in self._guids:
if guid != None:
guid.DeRef(self)
del self._guids[:]
del self._packages[:]
del self._depexs[:]
SurfaceObject.Destroy(self)
def GetFileObjectClass(self):
return inf.INFFile
def GetLibraries(self):
return self._libs
def Load(self, filename, arch='common', overidePcds=None, overideLibs=None):
if not SurfaceObject.Load(self, filename):
return False
self._arch = arch
if overidePcds != None:
self._overideLibs = overideLibs
if overideLibs != None:
self._overidePcds = overidePcds
self._SearchLibraries()
self._SearchPackage()
self._SearchSurfaceItems()
return True
def GetArch(self):
return self._arch
def GetModuleName(self):
return self.GetFileObj().GetDefine("BASE_NAME")
def GetModuleType(self):
return self.GetFileObj().GetDefine("MODULE_TYPE")
def GetPlatform(self):
return self.GetParent()
def GetModuleObj(self):
return self
def GetPcds(self):
pcds = self._pcds.copy()
for lib in self._libs.values():
if lib == None: continue
for name in lib._pcds.keys():
pcds[name] = lib._pcds[name]
return pcds
def GetPpis(self):
ppis = []
ppis += self._ppis
for lib in self._libs.values():
if lib == None: continue
ppis += lib._ppis
return ppis
def GetProtocols(self):
pros = []
pros = self._protocols
for lib in self._libs.values():
if lib == None: continue
pros += lib._protocols
return pros
def GetGuids(self):
guids = []
guids += self._guids
for lib in self._libs.values():
if lib == None: continue
guids += lib._guids
return guids
def GetDepexs(self):
deps = []
deps += self._depexs
for lib in self._libs.values():
if lib == None: continue
deps += lib._depexs
return deps
def IsLibrary(self):
return self.GetFileObj().GetDefine("LIBRARY_CLASS") != None
def GetLibraryInstance(self, classname, arch, type):
if classname not in self._libs.keys():
# find in overide lib firstly
if classname in self._overideLibs.keys():
self._libs[classname] = Library(self, self.GetWorkspace())
self._libs[classname].Load(self._overideLibs[classname])
return self._libs[classname]
parent = self.GetParent()
if issubclass(parent.__class__, Platform):
path = parent.GetLibraryPath(classname, arch, type)
if path == None:
ErrorMsg('Fail to get library instance for %s' % classname, self.GetFilename())
return None
self._libs[classname] = Library(self, self.GetWorkspace())
if not self._libs[classname].Load(path, self.GetArch()):
self._libs[classname] = None
else:
self._libs[classname] = parent.GetLibraryInstance(classname, arch, type)
return self._libs[classname]
def GetSourceObjs(self):
return self.GetFileObj().GetSectionObjectsByName('source')
def _SearchLibraries(self):
objs = self.GetFileObj().GetSectionObjectsByName('libraryclasses')
arch = self.GetArch()
type = self.GetModuleType()
for obj in objs:
if obj.GetArch().lower() != 'common' and \
obj.GetArch().lower() not in self.GetPlatform().GetSupportArchs():
continue
classname = obj.GetClass()
instance = self.GetLibraryInstance(classname, arch, type)
if not self.IsLibrary() and instance != None:
instance._isInherit = False
if classname not in self._libs.keys():
self._libs[classname] = instance
def _SearchSurfaceItems(self):
# get surface item from self's inf
pcds = []
ppis = []
pros = []
deps = []
guids = []
if self.GetFileObj() != None:
pcds = self.FilterObjsByArch(self.GetFileObj().GetSectionObjectsByName('pcd'),
self.GetArch())
for pcd in pcds:
if pcd.GetPcdName() not in self._pcds.keys():
pcdItem = PcdItem(pcd.GetPcdName(), self, pcd)
self._pcds[pcd.GetPcdName()] = ModulePcd(self,
pcd.GetPcdName(),
pcd,
pcdItem)
ppis += self.FilterObjsByArch(self.GetFileObj().GetSectionObjectsByName('ppis'),
self.GetArch())
for ppi in ppis:
item = PpiItem(ppi.GetName(), self, ppi)
if item not in self._ppis:
self._ppis.append(item)
pros += self.FilterObjsByArch(self.GetFileObj().GetSectionObjectsByName('protocols'),
self.GetArch())
for pro in pros:
item = ProtocolItem(pro.GetName(), self, pro)
if item not in self._protocols:
self._protocols.append(item)
deps += self.FilterObjsByArch(self.GetFileObj().GetSectionObjectsByName('depex'),
self.GetArch())
for dep in deps:
item = DepexItem(self, dep)
self._depexs.append(item)
guids += self.FilterObjsByArch(self.GetFileObj().GetSectionObjectsByName('guids'),
self.GetArch())
for guid in guids:
item = GuidItem(guid.GetName(), self, guid)
if item not in self._guids:
self._guids.append(item)
def _SearchPackage(self):
objs = self.GetFileObj().GetSectionObjectsByName('packages')
for obj in objs:
package = self.GetPlatform().GetPackage(obj.GetPath())
if package != None:
self._packages.append(package)
def GetPackages(self):
return self._packages
def GetPcdObjects(self):
if self.GetFileObj() == None:
return []
return self.GetFileObj().GetSectionObjectsByName('pcd')
def GetLibraryClassHeaderFilePath(self):
lcname = self.GetFileObj().GetProduceLibraryClass()
if lcname == None: return None
pkgs = self.GetPackages()
for package in pkgs:
path = package.GetLibraryClassHeaderPathByName(lcname)
if path != None:
return os.path.realpath(os.path.join(package.GetFileObj().GetPackageRootPath(), path))
return None
def Reload(self, force=False, callback=None):
if callback != None:
callback(self, "Starting reload...")
ret = SurfaceObject.Reload(self, force)
if not ret: return False
if not force and not self.IsModified():
return True
for lib in self._libs.values():
if lib != None:
lib.Destroy()
self._libs.clear()
for pcd in self._pcds.values():
pcd.Destroy()
self._pcds.clear()
for ppi in self._ppis:
ppi.DeRef(self)
del self._ppis[:]
for protocol in self._protocols:
protocol.DeRef(self)
del self._protocols[:]
for guid in self._guids:
guid.DeRef(self)
del self._guids[:]
del self._packages[:]
del self._depexs[:]
if callback != None:
callback(self, "Searching libraries...")
self._SearchLibraries()
if callback != None:
callback(self, "Searching packages...")
self._SearchPackage()
if callback != None:
callback(self, "Searching surface items...")
self._SearchSurfaceItems()
self.Modify(False)
return True
def Modify(self, modify=True, modifiedObj=None):
if modify:
#LogMsg("%s is modified, modified object is %s" % (self.GetFilename(), modifiedObj))
if issubclass(modifiedObj.__class__, ini.BaseINIFile) and self._isModify:
return
self._isModify = modify
self.GetParent().Modify(modify, self)
else:
if self.GetFileObj().IsModified():
return
self._isModify = modify
self.GetParent().Modify(modify, self)
class Library(Module):
def __init__(self, parent, workspace):
Module.__init__(self, parent, workspace)
self._isInherit = True
def IsInherit(self):
return self._isInherit
def GetModuleType(self):
return self.GetParent().GetModuleType()
def GetPlatform(self):
return self.GetParent().GetParent()
def GetModuleObj(self):
return self.GetParent()
def GetArch(self):
return self.GetParent().GetArch()
def Destroy(self):
self._libs.clear()
self._pcds.clear()
SurfaceObject.Destroy(self)
class Package(SurfaceObject):
def __init__(self, parent, workspace):
SurfaceObject.__init__(self, parent, workspace)
self._pcds = {}
self._guids = {}
self._protocols = {}
self._ppis = {}
def GetPcds(self):
return self._pcds
def GetPpis(self):
return self._ppis.values()
def GetProtocols(self):
return self._protocols.values()
def GetGuids(self):
return self._guids.values()
def Destroy(self):
for pcd in self._pcds.values():
if pcd != None:
pcd.Destroy()
for guid in self._guids.values():
if guid != None:
guid.Destroy()
for protocol in self._protocols.values():
if protocol != None:
protocol.Destroy()
for ppi in self._ppis.values():
if ppi != None:
ppi.Destroy()
self._pcds.clear()
self._guids.clear()
self._protocols.clear()
self._ppis.clear()
self._pcds.clear()
SurfaceObject.Destroy(self)
def Load(self, relativePath):
ret = SurfaceObject.Load(self, relativePath)
if not ret: return False
pcds = self.GetFileObj().GetSectionObjectsByName('pcds')
for pcd in pcds:
if pcd.GetPcdName() in self._pcds.keys():
if self._pcds[pcd.GetPcdName()] != None:
self._pcds[pcd.GetPcdName()].AddDecObj(pcd)
else:
self._pcds[pcd.GetPcdName()] = PcdItem(pcd.GetPcdName(), self, pcd)
guids = self.GetFileObj().GetSectionObjectsByName('guids')
for guid in guids:
if guid.GetName() not in self._guids.keys():
self._guids[guid.GetName()] = GuidItem(guid.GetName(), self, guid)
else:
WarnMsg("Duplicate definition for %s" % guid.GetName())
ppis = self.GetFileObj().GetSectionObjectsByName('ppis')
for ppi in ppis:
if ppi.GetName() not in self._ppis.keys():
self._ppis[ppi.GetName()] = PpiItem(ppi.GetName(), self, ppi)
else:
WarnMsg("Duplicate definition for %s" % ppi.GetName())
protocols = self.GetFileObj().GetSectionObjectsByName('protocols')
for protocol in protocols:
if protocol.GetName() not in self._protocols.keys():
self._protocols[protocol.GetName()] = ProtocolItem(protocol.GetName(), self, protocol)
else:
WarnMsg("Duplicate definition for %s" % protocol.GetName())
return True
def GetFileObjectClass(self):
return dec.DECFile
def GetName(self):
return self.GetFileObj().GetDefine("PACKAGE_NAME")
def GetPcdDefineObjs(self, name=None):
arr = []
objs = self.GetFileObj().GetSectionObjectsByName('pcds')
if name == None: return objs
for obj in objs:
if obj.GetPcdName().lower() == name.lower():
arr.append(obj)
return arr
def GetLibraryClassObjs(self):
return self.GetFileObj().GetSectionObjectsByName('libraryclasses')
def Modify(self, modify=True, modifiedObj=None):
if modify:
self._isModify = modify
self.GetParent().Modify(modify, self)
else:
if self.GetFileObj().IsModified():
return
self._isModify = modify
self.GetParent().Modify(modify, self)
def GetLibraryClassHeaderPathByName(self, clsname):
objs = self.GetLibraryClassObjs()
for obj in objs:
if obj.GetClassName() == clsname:
return obj.GetHeaderFile()
return None
class DepexItem(object):
def __init__(self, parent, infObj):
self._parent = parent
self._infObj = infObj
def GetDepexString(self):
return str(self._infObj)
def GetInfObject(self):
return self._infObj
class ModulePcd(object):
_type_mapping = {'FeaturePcd': 'PcdsFeatureFlag',
'FixedPcd': 'PcdsFixedAtBuild',
'PatchPcd': 'PcdsPatchableInModule'}
def __init__(self, parent, name, infObj, pcdItem):
assert issubclass(parent.__class__, Module), "Module's PCD's parent must be module!"
assert pcdItem != None, 'Pcd %s does not in some package!' % name
self._name = name
self._parent = parent
self._pcdItem = pcdItem
self._infObj = infObj
def GetName(self):
return self._name
def GetParent(self):
return self._name
def GetArch(self):
return self._parent.GetArch()
def Destroy(self):
self._pcdItem.DeRef(self._parent)
self._infObj = None
def GetBuildObj(self):
platformInfos = self._parent.GetPlatform().GetPcdBuildObjs(self._name, self.GetArch())
modulePcdType = self._infObj.GetPcdType()
# if platform do not gives pcd's value, get default value from package
if len(platformInfos) == 0:
if modulePcdType.lower() == 'pcd':
return self._pcdItem.GetDecObject()
else:
for obj in self._pcdItem.GetDecObjects():
if modulePcdType not in self._type_mapping.keys():
ErrorMsg("Invalid PCD type %s" % modulePcdType)
return None
if self._type_mapping[modulePcdType] == obj.GetPcdType():
return obj
ErrorMsg ('Module PCD type %s does not in valied range [%s] in package!' % \
(modulePcdType))
else:
if modulePcdType.lower() == 'pcd':
if len(platformInfos) > 1:
WarnMsg("Find more than one value for PCD %s in platform %s" % \
(self._name, self._parent.GetPlatform().GetFilename()))
return platformInfos[0]
else:
for obj in platformInfos:
if modulePcdType not in self._type_mapping.keys():
ErrorMsg("Invalid PCD type %s" % modulePcdType)
return None
if self._type_mapping[modulePcdType] == obj.GetPcdType():
return obj
ErrorMsg('Can not find value for pcd %s in pcd type %s' % \
(self._name, modulePcdType))
return None
class SurfaceItem(object):
_objs = {}
def __new__(cls, *args, **kwargs):
"""Maintain only a single instance of this object
@return: instance of this class
"""
name = args[0]
parent = args[1]
fileObj = args[2]
if issubclass(parent.__class__, Package):
if name in cls._objs.keys():
ErrorMsg("%s item is duplicated defined in packages: %s and %s" %
(name, parent.GetFilename(), cls._objs[name].GetParent().GetFilename()))
return None
obj = object.__new__(cls, *args, **kwargs)
cls._objs[name] = obj
return obj
elif issubclass(parent.__class__, Module):
if name not in cls._objs.keys():
ErrorMsg("%s item does not defined in any package! It is used by module %s" % \
(name, parent.GetFilename()))
return None
return cls._objs[name]
return None
def __init__(self, name, parent, fileObj):
if issubclass(parent.__class__, Package):
self._name = name
self._parent = parent
self._decObj = [fileObj]
self._refMods = {}
else:
self.RefModule(parent, fileObj)
@classmethod
def GetObjectDict(cls):
return cls._objs
def GetParent(self):
return self._parent
def GetReference(self):
return self._refMods
def RefModule(self, mObj, infObj):
if mObj in self._refMods.keys():
return
self._refMods[mObj] = infObj
def DeRef(self, mObj):
if mObj not in self._refMods.keys():
WarnMsg("%s is not referenced by module %s" % (self._name, mObj.GetFilename()))
return
del self._refMods[mObj]
def Destroy(self):
self._refMods.clear()
cls = self.__class__
del cls._objs[self._name]
def GetName(self):
return self._name
def GetDecObject(self):
return self._decObj[0]
def GetDecObjects(self):
return self._decObj
class PcdItem(SurfaceItem):
def AddDecObj(self, fileObj):
for decObj in self._decObj:
if decObj.GetFilename() != fileObj.GetFilename():
ErrorMsg("Pcd %s defined in more than one packages : %s and %s" % \
(self._name, decObj.GetFilename(), fileObj.GetFilename()))
return
if decObj.GetPcdType() == fileObj.GetPcdType() and \
decObj.GetArch().lower() == fileObj.GetArch():
ErrorMsg("Pcd %s is duplicated defined in pcd type %s in package %s" % \
(self._name, decObj.GetPcdType(), decObj.GetFilename()))
return
self._decObj.append(fileObj)
def GetValidPcdType(self):
types = []
for obj in self._decObj:
if obj.GetPcdType() not in types:
types += obj.GetPcdType()
return types
class GuidItem(SurfaceItem):
pass
class PpiItem(SurfaceItem):
pass
class ProtocolItem(SurfaceItem):
pass

View File

@ -0,0 +1,319 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
import plugins.EdkPlugins.basemodel.ini as ini
import re, os
from plugins.EdkPlugins.basemodel.message import *
class DECFile(ini.BaseINIFile):
def GetSectionInstance(self, parent, name, isCombined=False):
return DECSection(parent, name, isCombined)
def GetComponents(self):
return self.GetSectionByName('Components')
def GetPackageRootPath(self):
return os.path.dirname(self.GetFilename()).strip()
def GetBaseName(self):
return self.GetDefine("PACKAGE_NAME").strip()
def GetVersion(self):
return self.GetDefine("PACKAGE_VERSION").strip()
def GetSectionObjectsByName(self, name, arch=None):
arr = []
sects = self.GetSectionByName(name)
for sect in sects:
# skip unmatched archtecture content
if not sect.IsArchMatch(arch):
continue
for obj in sect.GetObjects():
arr.append(obj)
return arr
class DECSection(ini.BaseINISection):
def GetSectionINIObject(self, parent):
type = self.GetType()
if type.lower().find('defines') != -1:
return DECDefineSectionObject(self)
if type.lower().find('includes') != -1:
return DECIncludeObject(self)
if type.lower().find('pcd') != -1:
return DECPcdObject(self)
if type.lower() == 'libraryclasses':
return DECLibraryClassObject(self)
if type.lower() == 'guids':
return DECGuidObject(self)
if type.lower() == 'ppis':
return DECPpiObject(self)
if type.lower() == 'protocols':
return DECProtocolObject(self)
return DECSectionObject(self)
def GetType(self):
arr = self._name.split('.')
return arr[0].strip()
def GetArch(self):
arr = self._name.split('.')
if len(arr) == 1:
return 'common'
return arr[1]
def IsArchMatch(self, arch):
if arch == None or self.GetArch() == 'common':
return True
if self.GetArch().lower() != arch.lower():
return False
return True
class DECSectionObject(ini.BaseINISectionObject):
def GetArch(self):
return self.GetParent().GetArch()
class DECDefineSectionObject(DECSectionObject):
def __init__(self, parent):
DECSectionObject.__init__(self, parent)
self._key = None
self._value = None
def Parse(self):
assert (self._start == self._end), 'The object in define section must be in single line'
line = self.GetLineByOffset(self._start).strip()
line = line.split('#')[0]
arr = line.split('=')
if len(arr) != 2:
ErrorMsg('Invalid define section object',
self.GetFilename(),
self.GetParent().GetName()
)
return False
self._key = arr[0].strip()
self._value = arr[1].strip()
return True
def GetKey(self):
return self._key
def GetValue(self):
return self._value
class DECGuidObject(DECSectionObject):
_objs = {}
def __init__(self, parent):
DECSectionObject.__init__(self, parent)
self._name = None
def Parse(self):
line = self.GetLineByOffset(self._start).strip().split('#')[0]
self._name = line.split('=')[0].strip()
self._guid = line.split('=')[1].strip()
objdict = DECGuidObject._objs
if self._name not in objdict.keys():
objdict[self._name] = [self]
else:
objdict[self._name].append(self)
return True
def GetName(self):
return self._name
def GetGuid(self):
return self._guid
def Destroy(self):
objdict = DECGuidObject._objs
objdict[self._name].remove(self)
if len(objdict[self._name]) == 0:
del objdict[self._name]
@staticmethod
def GetObjectDict():
return DECGuidObject._objs
class DECPpiObject(DECSectionObject):
_objs = {}
def __init__(self, parent):
DECSectionObject.__init__(self, parent)
self._name = None
def Parse(self):
line = self.GetLineByOffset(self._start).strip().split('#')[0]
self._name = line.split('=')[0].strip()
self._guid = line.split('=')[1].strip()
objdict = DECPpiObject._objs
if self._name not in objdict.keys():
objdict[self._name] = [self]
else:
objdict[self._name].append(self)
return True
def GetName(self):
return self._name
def GetGuid(self):
return self._guid
def Destroy(self):
objdict = DECPpiObject._objs
objdict[self._name].remove(self)
if len(objdict[self._name]) == 0:
del objdict[self._name]
@staticmethod
def GetObjectDict():
return DECPpiObject._objs
class DECProtocolObject(DECSectionObject):
_objs = {}
def __init__(self, parent):
DECSectionObject.__init__(self, parent)
self._name = None
def Parse(self):
line = self.GetLineByOffset(self._start).strip().split('#')[0]
self._name = line.split('=')[0].strip()
self._guid = line.split('=')[1].strip()
objdict = DECProtocolObject._objs
if self._name not in objdict.keys():
objdict[self._name] = [self]
else:
objdict[self._name].append(self)
return True
def GetName(self):
return self._name
def GetGuid(self):
return self._guid
def Destroy(self):
objdict = DECProtocolObject._objs
objdict[self._name].remove(self)
if len(objdict[self._name]) == 0:
del objdict[self._name]
@staticmethod
def GetObjectDict():
return DECProtocolObject._objs
class DECLibraryClassObject(DECSectionObject):
_objs = {}
def __init__(self, parent):
DECSectionObject.__init__(self, parent)
self.mClassName = None
self.mHeaderFile = None
def Parse(self):
line = self.GetLineByOffset(self._start).strip().split('#')[0]
self.mClassName, self.mHeaderFile = line.split('|')
objdict = DECLibraryClassObject._objs
if self.mClassName not in objdict.keys():
objdict[self.mClassName] = [self]
else:
objdict[self.mClassName].append(self)
return True
def GetClassName(self):
return self.mClassName
def GetName(self):
return self.mClassName
def GetHeaderFile(self):
return self.mHeaderFile
def Destroy(self):
objdict = DECLibraryClassObject._objs
objdict[self.mClassName].remove(self)
if len(objdict[self.mClassName]) == 0:
del objdict[self.mClassName]
@staticmethod
def GetObjectDict():
return DECLibraryClassObject._objs
class DECIncludeObject(DECSectionObject):
def __init__(self, parent):
DECSectionObject.__init__(self, parent)
def GetPath(self):
return self.GetLineByOffset(self._start).split('#')[0].strip()
class DECPcdObject(DECSectionObject):
_objs = {}
def __init__(self, parent):
DECSectionObject.__init__(self, parent)
self.mPcdName = None
self.mPcdDefaultValue = None
self.mPcdDataType = None
self.mPcdToken = None
def Parse(self):
line = self.GetLineByOffset(self._start).strip().split('#')[0]
(self.mPcdName, self.mPcdDefaultValue, self.mPcdDataType, self.mPcdToken) = line.split('|')
objdict = DECPcdObject._objs
if self.mPcdName not in objdict.keys():
objdict[self.mPcdName] = [self]
else:
objdict[self.mPcdName].append(self)
return True
def Destroy(self):
objdict = DECPcdObject._objs
objdict[self.mPcdName].remove(self)
if len(objdict[self.mPcdName]) == 0:
del objdict[self.mPcdName]
def GetPcdType(self):
return self.GetParent().GetType()
def GetPcdName(self):
return self.mPcdName
def GetPcdValue(self):
return self.mPcdDefaultValue
def GetPcdDataType(self):
return self.mPcdDataType
def GetPcdToken(self):
return self.mPcdToken
def GetName(self):
return self.GetPcdName().split('.')[1]
@staticmethod
def GetObjectDict():
return DECPcdObject._objs

View File

@ -0,0 +1,201 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
import plugins.EdkPlugins.basemodel.ini as ini
import re, os
from plugins.EdkPlugins.basemodel.message import *
class DSCFile(ini.BaseINIFile):
def GetSectionInstance(self, parent, name, isCombined=False):
return DSCSection(parent, name, isCombined)
def GetComponents(self):
return self.GetSectionObjectsByName('Components')
class DSCSection(ini.BaseINISection):
def GetSectionINIObject(self, parent):
type = self.GetType()
if type.lower() == 'components':
return DSCComponentObject(self)
if type.lower() == 'libraryclasses':
return DSCLibraryClassObject(self)
if type.lower() == 'defines':
return ini.BaseINISectionObject(self)
if type.lower() == 'pcdsfeatureflag' or \
type.lower() == 'pcdsfixedatbuild' or \
type.lower() == 'pcdspatchableinmodule' or\
type.lower() == 'pcdsdynamicdefault' or \
type.lower() == 'pcdsdynamicex' or \
type.lower() == 'pcdsdynamichii' or \
type.lower() == 'pcdsdynamicvpd':
return DSCPcdObject(self)
return DSCSectionObject(self)
def GetType(self):
arr = self._name.split('.')
return arr[0].strip()
def GetArch(self):
arr = self._name.split('.')
if len(arr) == 1:
return 'common'
return arr[1]
def GetModuleType(self):
arr = self._name.split('.')
if len(arr) < 3:
return 'common'
return arr[2]
class DSCSectionObject(ini.BaseINISectionObject):
def GetArch(self):
return self.GetParent().GetArch()
class DSCPcdObject(DSCSectionObject):
def __init__(self, parent):
ini.BaseINISectionObject.__init__(self, parent)
self._name = None
def Parse(self):
line = self.GetLineByOffset(self._start).strip().split('#')[0]
self._name = line.split('|')[0]
self._value = line.split('|')[1]
return True
def GetPcdName(self):
return self._name
def GetPcdType(self):
return self.GetParent().GetType()
def GetPcdValue(self):
return self._value
class DSCLibraryClassObject(DSCSectionObject):
def __init__(self, parent):
ini.BaseINISectionObject.__init__(self, parent)
def GetClass(self):
line = self.GetLineByOffset(self._start)
return line.split('#')[0].split('|')[0].strip()
def GetInstance(self):
line = self.GetLineByOffset(self._start)
return line.split('#')[0].split('|')[1].strip()
def GetArch(self):
return self.GetParent().GetArch()
def GetModuleType(self):
return self.GetParent().GetModuleType()
class DSCComponentObject(DSCSectionObject):
def __init__(self, parent):
ini.BaseINISectionObject.__init__(self, parent)
self._OveridePcds = {}
self._OverideLibraries = {}
self._Filename = ''
def __del__(self):
self._OverideLibraries.clear()
self._OverideLibraries.clear()
ini.BaseINISectionObject.__del__(self)
def AddOverideLib(self, libclass, libinstPath):
if libclass not in self._OverideLibraries.keys():
self._OverideLibraries[libclass] = libinstPath
def AddOveridePcd(self, name, type, value=None):
if type not in self._OveridePcds.keys():
self._OveridePcds[type] = []
self._OveridePcds[type].append((name, value))
def GetOverideLibs(self):
return self._OverideLibraries
def GetArch(self):
return self.GetParent().GetArch()
def GetOveridePcds(self):
return self._OveridePcds
def GetFilename(self):
return self.GetLineByOffset(self._start).split('#')[0].split('{')[0].strip()
def SetFilename(self, fName):
self._Filename = fName
def Parse(self):
if (self._start < self._end):
#
# The first line is inf path and could be ignored
# The end line is '}' and could be ignored
#
curr = self._start + 1
end = self._end - 1
OverideName = ''
while (curr <= end):
line = self.GetLineByOffset(curr).strip()
if len(line) > 0 and line[0] != '#':
line = line.split('#')[0].strip()
if line[0] == '<':
OverideName = line[1:len(line)-1]
elif OverideName.lower() == 'libraryclasses':
arr = line.split('|')
self._OverideLibraries[arr[0].strip()] = arr[1].strip()
elif OverideName.lower() == 'pcds':
ErrorMsg('EDES does not support PCD overide',
self.GetFileName(),
self.GetParent().GetLinenumberByOffset(curr))
curr = curr + 1
return True
def GenerateLines(self):
lines = []
hasLib = False
hasPcd = False
if len(self._OverideLibraries) != 0:
hasLib = True
if len(self._OveridePcds) != 0:
hasPcd = True
if hasLib or hasPcd:
lines.append((' %s {\n' % self._Filename))
else:
lines.append((' %s \n' % self._Filename))
return lines
if hasLib:
lines.append(' <LibraryClasses>\n')
for libKey in self._OverideLibraries.keys():
lines.append(' %s|%s\n' % (libKey, self._OverideLibraries[libKey]))
if hasPcd:
for key in self._OveridePcds.keys():
lines.append(' <%s>\n' % key)
for name, value in self._OveridePcds[key]:
if value != None:
lines.append(' %s|%s\n' % (name, value))
else:
lines.append(' %s\n' % name)
if hasLib or hasPcd:
lines.append(' }\n')
return lines

View File

@ -0,0 +1,341 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
import plugins.EdkPlugins.basemodel.ini as ini
import re, os
from plugins.EdkPlugins.basemodel.message import *
class INFFile(ini.BaseINIFile):
_libobjs = {}
def GetSectionInstance(self, parent, name, isCombined=False):
return INFSection(parent, name, isCombined)
def GetProduceLibraryClass(self):
obj = self.GetDefine("LIBRARY_CLASS")
if obj == None: return None
return obj.split('|')[0].strip()
def GetSectionObjectsByName(self, name, arch=None):
arr = []
sects = self.GetSectionByName(name)
for sect in sects:
# skip unmatched archtecture content
if not sect.IsArchMatch(arch):
continue
for obj in sect.GetObjects():
arr.append(obj)
return arr
def GetSourceObjects(self, arch=None, tool=None):
arr = []
sects = self.GetSectionByName('sources')
for sect in sects:
# skip unmatched archtecture content
if not sect.IsArchMatch(arch):
continue
for obj in sect.GetObjects():
if not obj.IsMatchFamily(tool):
continue
arr.append(obj)
return arr
def Parse(self):
if not ini.BaseINIFile.Parse(self):
return False
classname = self.GetProduceLibraryClass()
if classname != None:
libobjdict = INFFile._libobjs
if libobjdict.has_key(classname):
if self not in libobjdict[classname]:
libobjdict[classname].append(self)
else:
libobjdict[classname] = [self]
return True
def GetBaseName(self):
return self.GetDefine("BASE_NAME").strip()
def GetModuleRootPath(self):
return os.path.dirname(self.GetFilename())
def Clear(self):
classname = self.GetProduceLibraryClass()
if classname != None:
libobjdict = INFFile._libobjs
libobjdict[classname].remove(self)
if len(libobjdict[classname]) == 0:
del libobjdict[classname]
ini.BaseINIFile.Clear(self)
class INFSection(ini.BaseINISection):
def GetSectionINIObject(self, parent):
type = self.GetType()
if type.lower() == 'libraryclasses':
return INFLibraryClassObject(self)
if type.lower() == 'sources':
return INFSourceObject(self)
if type.lower().find('pcd') != -1:
return INFPcdObject(self)
if type.lower() == 'packages':
return INFDependentPackageObject(self)
if type.lower() in ['guids', 'protocols', 'ppis']:
return INFGuidObject(self)
if type.lower() == 'defines':
return INFDefineSectionObject(self)
return INFSectionObject(self)
def GetType(self):
arr = self._name.split('.')
return arr[0].strip()
def GetArch(self):
arr = self._name.split('.')
if len(arr) == 1:
return 'common'
return arr[1]
def IsArchMatch(self, arch):
if arch == None or self.GetArch() == 'common':
return True
if self.GetArch().lower() != arch.lower():
return False
return True
class INFSectionObject(ini.BaseINISectionObject):
def GetArch(self):
return self.GetParent().GetArch()
class INFDefineSectionObject(INFSectionObject):
def __init__(self, parent):
INFSectionObject.__init__(self, parent)
self._key = None
self._value = None
def Parse(self):
assert (self._start == self._end), 'The object in define section must be in single line'
line = self.GetLineByOffset(self._start).strip()
line = line.split('#')[0]
arr = line.split('=')
if len(arr) != 2:
ErrorMsg('Invalid define section object',
self.GetFilename(),
self._start
)
return False
self._key = arr[0].strip()
self._value = arr[1].strip()
return True
def GetKey(self):
return self._key
def GetValue(self):
return self._value
class INFLibraryClassObject(INFSectionObject):
_objs = {}
def __init__(self, parent):
INFSectionObject.__init__(self, parent)
self._classname = None
def GetClass(self):
return self._classname
def Parse(self):
self._classname = self.GetLineByOffset(self._start).split('#')[0].strip()
objdict = INFLibraryClassObject._objs
if objdict.has_key(self._classname):
objdict[self._classname].append(self)
else:
objdict[self._classname] = [self]
return True
def Destroy(self):
objdict = INFLibraryClassObject._objs
objdict[self._classname].remove(self)
if len(objdict[self._classname]) == 0:
del objdict[self._classname]
def GetName(self):
return self._classname
@staticmethod
def GetObjectDict():
return INFLibraryClassObject._objs
class INFDependentPackageObject(INFSectionObject):
def GetPath(self):
return self.GetLineByOffset(self._start).split('#')[0].strip()
class INFSourceObject(INFSectionObject):
_objs = {}
def __init__(self, parent):
INFSectionObject.__init__(self, parent)
self.mSourcename = None
self.mToolCode = None
self.mFamily = None
self.mTagName = None
self.mFeaturePcd = None
self.mFilename = None
def GetSourcePath(self):
return self.mSourcename
def GetSourceFullPath(self):
path = os.path.dirname(self.GetFilename())
path = os.path.join(path, self.GetSourcePath())
return os.path.normpath(path)
def GetToolCode(self):
return self.mToolCode
def GetFamily(self):
return self.mFamily
def GetTagName(self):
return self.mTagName
def GetFeaturePcd(self):
return self.mFeaturePcd
def Parse(self):
line = self.GetLineByOffset(self._start).strip().split('#')[0]
arr = line.split('|')
self.mSourcename = arr[0].strip()
if len(arr) >= 2:
self.mFamily = arr[1].strip()
if len(arr) >= 3:
self.mTagName = arr[2].strip()
if len(arr) >= 4:
self.mToolCode = arr[3].strip()
if len(arr) >= 5:
self.mFeaturePcd = arr[4].strip()
self.mFilename = os.path.basename(self.GetSourceFullPath())
objdict = INFSourceObject._objs
if not objdict.has_key(self.mFilename):
objdict[self.mFilename] = [self]
else:
objdict[self.mFilename].append(self)
return True
def GetName(self):
return self.mFilename
def Destroy(self):
objdict = INFSourceObject._objs
objdict[self.mFilename].remove(self)
if len(objdict[self.mFilename]) == 0:
del objdict[self.mFilename]
def IsMatchFamily(self, family):
if family == None:
return True
if self.mFamily != None:
if family.strip().lower() == self.mFamily.lower():
return True
else:
return False
else:
fname = self.GetSourcePath()
if fname.endswith('.S') and family.lower() != 'gcc':
return False
if fname.endswith('.s') and (self.GetArch().lower() != 'ipf' and self.GetArch().lower() != 'common'):
return False
if fname.lower().endswith('.asm') and (family.lower() != 'msft' and family.lower() != 'intel'):
return False
return True
@staticmethod
def GetObjectDict():
return INFSourceObject._objs
class INFPcdObject(INFSectionObject):
_objs = {}
def __init__(self, parent):
INFSectionObject.__init__(self, parent)
self.mPcdType = None
self.mDefaultValue = None
self.mPcdName = None
@staticmethod
def GetObjectDict():
return INFPcdObject._objs
def Parse(self):
line = self.GetLineByOffset(self._start).strip().split('#')[0]
arr = line.split('|')
self.mPcdName = arr[0].strip()
if len(arr) >= 2:
self.mDefaultValue = arr[1].strip()
objdict = INFPcdObject._objs
if objdict.has_key(self.GetName()):
if self not in objdict[self.GetName()]:
objdict[self.GetName()].append(self)
else:
objdict[self.GetName()] = [self]
return True
def GetPcdName(self):
return self.mPcdName
def GetPcdType(self):
return self.GetParent().GetType()
def GetName(self):
return self.mPcdName.split('.')[1]
def Destroy(self):
objdict = INFPcdObject._objs
objdict[self.GetName()].remove(self)
if len(objdict[self.GetName()]) == 0:
del objdict[self.GetName()]
class INFGuidObject(INFSectionObject):
def __init__(self, parent):
INFSectionObject.__init__(self, parent)
self._name = None
def Parse(self):
line = self.GetLineByOffset(self._start).strip().split('#')[0].split("|")[0]
self._name = line.strip()
return True
def GetName(self):
return self._name

View File

@ -0,0 +1,12 @@
## @file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#