mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-20 15:48:18 +01:00
929 lines
31 KiB
Python
929 lines
31 KiB
Python
|
## @file
|
||
|
#
|
||
|
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
|
||
|
#
|
||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
|
||
|
from plugins.EdkPlugins.basemodel import ini
|
||
|
from plugins.EdkPlugins.edk2.model import dsc
|
||
|
from plugins.EdkPlugins.edk2.model import inf
|
||
|
from plugins.EdkPlugins.edk2.model import 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)
|
||
|
if "None" not in cls._objs:
|
||
|
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 key in self._objs, "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 is not 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 relativePath not in cls._objs:
|
||
|
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() is 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 is not 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 is not 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 is not 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 is 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] is not 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 is not 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 is not None:
|
||
|
protocol.DeRef(self)
|
||
|
del self._protocols[:]
|
||
|
|
||
|
for guid in self._guids:
|
||
|
if guid is not 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 is not None:
|
||
|
self._overideLibs = overideLibs
|
||
|
if overideLibs is not 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 is 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 is None: continue
|
||
|
ppis += lib._ppis
|
||
|
return ppis
|
||
|
|
||
|
def GetProtocols(self):
|
||
|
pros = []
|
||
|
pros = self._protocols
|
||
|
for lib in self._libs.values():
|
||
|
if lib is None: continue
|
||
|
pros += lib._protocols
|
||
|
return pros
|
||
|
|
||
|
def GetGuids(self):
|
||
|
guids = []
|
||
|
guids += self._guids
|
||
|
for lib in self._libs.values():
|
||
|
if lib is None: continue
|
||
|
guids += lib._guids
|
||
|
return guids
|
||
|
|
||
|
def GetDepexs(self):
|
||
|
deps = []
|
||
|
deps += self._depexs
|
||
|
for lib in self._libs.values():
|
||
|
if lib is None: continue
|
||
|
deps += lib._depexs
|
||
|
return deps
|
||
|
|
||
|
def IsLibrary(self):
|
||
|
return self.GetFileObj().GetDefine("LIBRARY_CLASS") is not 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 is 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 is not 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() is not 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 is not None:
|
||
|
self._packages.append(package)
|
||
|
|
||
|
def GetPackages(self):
|
||
|
return self._packages
|
||
|
|
||
|
def GetPcdObjects(self):
|
||
|
if self.GetFileObj() is None:
|
||
|
return []
|
||
|
|
||
|
return self.GetFileObj().GetSectionObjectsByName('pcd')
|
||
|
|
||
|
def GetLibraryClassHeaderFilePath(self):
|
||
|
lcname = self.GetFileObj().GetProduceLibraryClass()
|
||
|
if lcname is None: return None
|
||
|
|
||
|
pkgs = self.GetPackages()
|
||
|
for package in pkgs:
|
||
|
path = package.GetLibraryClassHeaderPathByName(lcname)
|
||
|
if path is not None:
|
||
|
return os.path.realpath(os.path.join(package.GetFileObj().GetPackageRootPath(), path))
|
||
|
return None
|
||
|
|
||
|
def Reload(self, force=False, callback=None):
|
||
|
if callback is not 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 is not 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 is not None:
|
||
|
callback(self, "Searching libraries...")
|
||
|
self._SearchLibraries()
|
||
|
if callback is not None:
|
||
|
callback(self, "Searching packages...")
|
||
|
self._SearchPackage()
|
||
|
if callback is not 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 list(self._ppis.values())
|
||
|
|
||
|
def GetProtocols(self):
|
||
|
return list(self._protocols.values())
|
||
|
|
||
|
def GetGuids(self):
|
||
|
return list(self._guids.values())
|
||
|
|
||
|
def Destroy(self):
|
||
|
for pcd in self._pcds.values():
|
||
|
if pcd is not None:
|
||
|
pcd.Destroy()
|
||
|
for guid in self._guids.values():
|
||
|
if guid is not None:
|
||
|
guid.Destroy()
|
||
|
for protocol in self._protocols.values():
|
||
|
if protocol is not None:
|
||
|
protocol.Destroy()
|
||
|
for ppi in self._ppis.values():
|
||
|
if ppi is not 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()] is not 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 is 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 is not 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)
|
||
|
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
|