BaseTools: support private package definition

EDKII build spec and DEC spec updated to support private package
definition.
If GUID, Protocol or PPI is listed in a DEC file, where the  Private
modifier is used in the section tag ([Guids.common.Private] for example),
only modules within the package are permitted to use the GUID, Protocol
or PPI. If a module or library instance outside of the package attempts
to use the item, the build must fail with an appropriate error message.

Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
Yonghong Zhu
2016-05-10 17:58:26 +08:00
parent bba734ab4c
commit c28d2e1047
5 changed files with 90 additions and 24 deletions

View File

@ -2174,7 +2174,7 @@ class PlatformAutoGen(AutoGen):
for SkuId in PcdInModule.SkuInfoList: for SkuId in PcdInModule.SkuInfoList:
Sku = PcdInModule.SkuInfoList[SkuId] Sku = PcdInModule.SkuInfoList[SkuId]
if Sku.VariableGuid == '': continue if Sku.VariableGuid == '': continue
Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList) Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)
if Sku.VariableGuidValue == None: if Sku.VariableGuidValue == None:
PackageList = "\n\t".join([str(P) for P in self.PackageList]) PackageList = "\n\t".join([str(P) for P in self.PackageList])
EdkLogger.error( EdkLogger.error(
@ -3395,7 +3395,11 @@ class ModuleAutoGen(AutoGen):
PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir) PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)
if PackageDir not in self._IncludePathList: if PackageDir not in self._IncludePathList:
self._IncludePathList.append(PackageDir) self._IncludePathList.append(PackageDir)
for Inc in Package.Includes: IncludesList = Package.Includes
if Package._PrivateIncludes:
if not self.MetaFile.Path.startswith(PackageDir):
IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))
for Inc in IncludesList:
if Inc not in self._IncludePathList: if Inc not in self._IncludePathList:
self._IncludePathList.append(str(Inc)) self._IncludePathList.append(str(Inc))
return self._IncludePathList return self._IncludePathList
@ -3462,7 +3466,7 @@ class ModuleAutoGen(AutoGen):
for SkuName in Pcd.SkuInfoList: for SkuName in Pcd.SkuInfoList:
SkuInfo = Pcd.SkuInfoList[SkuName] SkuInfo = Pcd.SkuInfoList[SkuName]
Name = ConvertStringToByteArray(SkuInfo.VariableName) Name = ConvertStringToByteArray(SkuInfo.VariableName)
Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList) Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)
if not Value: if not Value:
continue continue
Guid = GuidStructureStringToGuidString(Value) Guid = GuidStructureStringToGuidString(Value)

View File

@ -1,7 +1,7 @@
## @file ## @file
# Common routines used by all tools # Common routines used by all tools
# #
# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials # This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License # 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 # which accompanies this distribution. The full text of the license may be found at
@ -794,13 +794,18 @@ def GetRelPath(Path1, Path2):
# #
# @param CName The CName of the GUID # @param CName The CName of the GUID
# @param PackageList List of packages looking-up in # @param PackageList List of packages looking-up in
# @param Inffile The driver file
# #
# @retval GuidValue if the CName is found in any given package # @retval GuidValue if the CName is found in any given package
# @retval None if the CName is not found in all given packages # @retval None if the CName is not found in all given packages
# #
def GuidValue(CName, PackageList): def GuidValue(CName, PackageList, Inffile = None):
for P in PackageList: for P in PackageList:
if CName in P.Guids: GuidKeys = P.Guids.keys()
if Inffile and P._PrivateGuids:
if not Inffile.startswith(P.MetaFile.Dir):
GuidKeys = (dict.fromkeys(x for x in P.Guids if x not in P._PrivateGuids)).keys()
if CName in GuidKeys:
return P.Guids[CName] return P.Guids[CName]
return None return None
@ -808,13 +813,18 @@ def GuidValue(CName, PackageList):
# #
# @param CName The CName of the GUID # @param CName The CName of the GUID
# @param PackageList List of packages looking-up in # @param PackageList List of packages looking-up in
# @param Inffile The driver file
# #
# @retval GuidValue if the CName is found in any given package # @retval GuidValue if the CName is found in any given package
# @retval None if the CName is not found in all given packages # @retval None if the CName is not found in all given packages
# #
def ProtocolValue(CName, PackageList): def ProtocolValue(CName, PackageList, Inffile = None):
for P in PackageList: for P in PackageList:
if CName in P.Protocols: ProtocolKeys = P.Protocols.keys()
if Inffile and P._PrivateProtocols:
if not Inffile.startswith(P.MetaFile.Dir):
ProtocolKeys = (dict.fromkeys(x for x in P.Protocols if x not in P._PrivateProtocols)).keys()
if CName in ProtocolKeys:
return P.Protocols[CName] return P.Protocols[CName]
return None return None
@ -822,13 +832,18 @@ def ProtocolValue(CName, PackageList):
# #
# @param CName The CName of the GUID # @param CName The CName of the GUID
# @param PackageList List of packages looking-up in # @param PackageList List of packages looking-up in
# @param Inffile The driver file
# #
# @retval GuidValue if the CName is found in any given package # @retval GuidValue if the CName is found in any given package
# @retval None if the CName is not found in all given packages # @retval None if the CName is not found in all given packages
# #
def PpiValue(CName, PackageList): def PpiValue(CName, PackageList, Inffile = None):
for P in PackageList: for P in PackageList:
if CName in P.Ppis: PpiKeys = P.Ppis.keys()
if Inffile and P._PrivatePpis:
if not Inffile.startswith(P.MetaFile.Dir):
PpiKeys = (dict.fromkeys(x for x in P.Ppis if x not in P._PrivatePpis)).keys()
if CName in PpiKeys:
return P.Ppis[CName] return P.Ppis[CName]
return None return None

View File

@ -1722,6 +1722,7 @@ class DecParser(MetaFileParser):
self._SectionName = '' self._SectionName = ''
self._SectionType = [] self._SectionType = []
ArchList = set() ArchList = set()
PrivateList = set()
Line = self._CurrentLine.replace("%s%s" % (TAB_COMMA_SPLIT, TAB_SPACE_SPLIT), TAB_COMMA_SPLIT) Line = self._CurrentLine.replace("%s%s" % (TAB_COMMA_SPLIT, TAB_SPACE_SPLIT), TAB_COMMA_SPLIT)
for Item in Line[1:-1].split(TAB_COMMA_SPLIT): for Item in Line[1:-1].split(TAB_COMMA_SPLIT):
if Item == '': if Item == '':
@ -1757,8 +1758,14 @@ class DecParser(MetaFileParser):
# S2 may be Platform or ModuleType # S2 may be Platform or ModuleType
if len(ItemList) > 2: if len(ItemList) > 2:
S2 = ItemList[2].upper() S2 = ItemList[2].upper()
# only Includes, GUIDs, PPIs, Protocols section have Private tag
if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:
if S2 != 'PRIVATE':
EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',
File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
else: else:
S2 = 'COMMON' S2 = 'COMMON'
PrivateList.add(S2)
if [S1, S2, self.DataType[self._SectionName]] not in self._Scope: if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
self._Scope.append([S1, S2, self.DataType[self._SectionName]]) self._Scope.append([S1, S2, self.DataType[self._SectionName]])
@ -1767,6 +1774,11 @@ class DecParser(MetaFileParser):
EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs", EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine) File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
# It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute
if 'COMMON' in PrivateList and len(PrivateList) > 1:
EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",
File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
## [guids], [ppis] and [protocols] section parser ## [guids], [ppis] and [protocols] section parser
@ParseMacro @ParseMacro
def _GuidParser(self): def _GuidParser(self):

View File

@ -1,7 +1,7 @@
## @file ## @file
# This file is used to create/update/query/erase a meta file table # This file is used to create/update/query/erase a meta file table
# #
# Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials # This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License # 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 # which accompanies this distribution. The full text of the license may be found at
@ -218,7 +218,7 @@ class PackageTable(MetaFileTable):
# #
def Query(self, Model, Arch=None): def Query(self, Model, Arch=None):
ConditionString = "Model=%s AND Enabled>=0" % Model ConditionString = "Model=%s AND Enabled>=0" % Model
ValueString = "Value1,Value2,Value3,Scope1,ID,StartLine" ValueString = "Value1,Value2,Value3,Scope1,Scope2,ID,StartLine"
if Arch != None and Arch != 'COMMON': if Arch != None and Arch != 'COMMON':
ConditionString += " AND (Scope1='%s' OR Scope1='COMMON')" % Arch ConditionString += " AND (Scope1='%s' OR Scope1='COMMON')" % Arch

View File

@ -1328,6 +1328,10 @@ class DecBuildData(PackageBuildClassObject):
self._LibraryClasses = None self._LibraryClasses = None
self._Pcds = None self._Pcds = None
self.__Macros = None self.__Macros = None
self._PrivateProtocols = None
self._PrivatePpis = None
self._PrivateGuids = None
self._PrivateIncludes = None
## Get current effective macros ## Get current effective macros
def _GetMacros(self): def _GetMacros(self):
@ -1402,21 +1406,30 @@ class DecBuildData(PackageBuildClassObject):
# protocol defition for given ARCH # protocol defition for given ARCH
# #
ProtocolDict = tdict(True) ProtocolDict = tdict(True)
PrivateProtocolDict = tdict(True)
NameList = [] NameList = []
PrivateNameList = []
# find out all protocol definitions for specific and 'common' arch # find out all protocol definitions for specific and 'common' arch
RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch] RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch]
for Name, Guid, Dummy, Arch, ID, LineNo in RecordList: for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
if PrivateFlag == 'PRIVATE':
if Name not in PrivateNameList:
PrivateNameList.append(Name)
PrivateProtocolDict[Arch, Name] = Guid
if Name not in NameList: if Name not in NameList:
NameList.append(Name) NameList.append(Name)
ProtocolDict[Arch, Name] = Guid ProtocolDict[Arch, Name] = Guid
# use sdict to keep the order # use sdict to keep the order
self._Protocols = sdict() self._Protocols = sdict()
self._PrivateProtocols = sdict()
for Name in NameList: for Name in NameList:
# #
# limit the ARCH to self._Arch, if no self._Arch found, tdict # limit the ARCH to self._Arch, if no self._Arch found, tdict
# will automatically turn to 'common' ARCH for trying # will automatically turn to 'common' ARCH for trying
# #
self._Protocols[Name] = ProtocolDict[self._Arch, Name] self._Protocols[Name] = ProtocolDict[self._Arch, Name]
for Name in PrivateNameList:
self._PrivateProtocols[Name] = PrivateProtocolDict[self._Arch, Name]
return self._Protocols return self._Protocols
## Retrieve PPI definitions (name/value pairs) ## Retrieve PPI definitions (name/value pairs)
@ -1427,21 +1440,30 @@ class DecBuildData(PackageBuildClassObject):
# PPI defition for given ARCH # PPI defition for given ARCH
# #
PpiDict = tdict(True) PpiDict = tdict(True)
PrivatePpiDict = tdict(True)
NameList = [] NameList = []
PrivateNameList = []
# find out all PPI definitions for specific arch and 'common' arch # find out all PPI definitions for specific arch and 'common' arch
RecordList = self._RawData[MODEL_EFI_PPI, self._Arch] RecordList = self._RawData[MODEL_EFI_PPI, self._Arch]
for Name, Guid, Dummy, Arch, ID, LineNo in RecordList: for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
if PrivateFlag == 'PRIVATE':
if Name not in PrivateNameList:
PrivateNameList.append(Name)
PrivatePpiDict[Arch, Name] = Guid
if Name not in NameList: if Name not in NameList:
NameList.append(Name) NameList.append(Name)
PpiDict[Arch, Name] = Guid PpiDict[Arch, Name] = Guid
# use sdict to keep the order # use sdict to keep the order
self._Ppis = sdict() self._Ppis = sdict()
self._PrivatePpis = sdict()
for Name in NameList: for Name in NameList:
# #
# limit the ARCH to self._Arch, if no self._Arch found, tdict # limit the ARCH to self._Arch, if no self._Arch found, tdict
# will automatically turn to 'common' ARCH for trying # will automatically turn to 'common' ARCH for trying
# #
self._Ppis[Name] = PpiDict[self._Arch, Name] self._Ppis[Name] = PpiDict[self._Arch, Name]
for Name in PrivateNameList:
self._PrivatePpis[Name] = PrivatePpiDict[self._Arch, Name]
return self._Ppis return self._Ppis
## Retrieve GUID definitions (name/value pairs) ## Retrieve GUID definitions (name/value pairs)
@ -1452,27 +1474,37 @@ class DecBuildData(PackageBuildClassObject):
# GUID defition for given ARCH # GUID defition for given ARCH
# #
GuidDict = tdict(True) GuidDict = tdict(True)
PrivateGuidDict = tdict(True)
NameList = [] NameList = []
PrivateNameList = []
# find out all protocol definitions for specific and 'common' arch # find out all protocol definitions for specific and 'common' arch
RecordList = self._RawData[MODEL_EFI_GUID, self._Arch] RecordList = self._RawData[MODEL_EFI_GUID, self._Arch]
for Name, Guid, Dummy, Arch, ID, LineNo in RecordList: for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
if PrivateFlag == 'PRIVATE':
if Name not in PrivateNameList:
PrivateNameList.append(Name)
PrivateGuidDict[Arch, Name] = Guid
if Name not in NameList: if Name not in NameList:
NameList.append(Name) NameList.append(Name)
GuidDict[Arch, Name] = Guid GuidDict[Arch, Name] = Guid
# use sdict to keep the order # use sdict to keep the order
self._Guids = sdict() self._Guids = sdict()
self._PrivateGuids = sdict()
for Name in NameList: for Name in NameList:
# #
# limit the ARCH to self._Arch, if no self._Arch found, tdict # limit the ARCH to self._Arch, if no self._Arch found, tdict
# will automatically turn to 'common' ARCH for trying # will automatically turn to 'common' ARCH for trying
# #
self._Guids[Name] = GuidDict[self._Arch, Name] self._Guids[Name] = GuidDict[self._Arch, Name]
for Name in PrivateNameList:
self._PrivateGuids[Name] = PrivateGuidDict[self._Arch, Name]
return self._Guids return self._Guids
## Retrieve public include paths declared in this package ## Retrieve public include paths declared in this package
def _GetInclude(self): def _GetInclude(self):
if self._Includes == None: if self._Includes == None:
self._Includes = [] self._Includes = []
self._PrivateIncludes = []
RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch] RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch]
Macros = self._Macros Macros = self._Macros
Macros["EDK_SOURCE"] = GlobalData.gEcpSource Macros["EDK_SOURCE"] = GlobalData.gEcpSource
@ -1487,6 +1519,9 @@ class DecBuildData(PackageBuildClassObject):
# avoid duplicate include path # avoid duplicate include path
if File not in self._Includes: if File not in self._Includes:
self._Includes.append(File) self._Includes.append(File)
if Record[4] == 'PRIVATE':
if File not in self._PrivateIncludes:
self._PrivateIncludes.append(File)
return self._Includes return self._Includes
## Retrieve library class declarations (not used in build at present) ## Retrieve library class declarations (not used in build at present)
@ -1500,7 +1535,7 @@ class DecBuildData(PackageBuildClassObject):
LibraryClassSet = set() LibraryClassSet = set()
RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch] RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]
Macros = self._Macros Macros = self._Macros
for LibraryClass, File, Dummy, Arch, ID, LineNo in RecordList: for LibraryClass, File, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
File = PathClass(NormPath(File, Macros), self._PackageDir, Arch=self._Arch) File = PathClass(NormPath(File, Macros), self._PackageDir, Arch=self._Arch)
# check the file validation # check the file validation
ErrorCode, ErrorInfo = File.Validate() ErrorCode, ErrorInfo = File.Validate()
@ -1536,7 +1571,7 @@ class DecBuildData(PackageBuildClassObject):
PcdSet = set() PcdSet = set()
# find out all PCDs of the 'type' # find out all PCDs of the 'type'
RecordList = self._RawData[Type, self._Arch] RecordList = self._RawData[Type, self._Arch]
for TokenSpaceGuid, PcdCName, Setting, Arch, Dummy1, Dummy2 in RecordList: for TokenSpaceGuid, PcdCName, Setting, Arch, PrivateFlag, Dummy1, Dummy2 in RecordList:
PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting
PcdSet.add((PcdCName, TokenSpaceGuid)) PcdSet.add((PcdCName, TokenSpaceGuid))
@ -2275,7 +2310,7 @@ class InfBuildData(ModuleBuildClassObject):
RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform] RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]
for Record in RecordList: for Record in RecordList:
CName = Record[0] CName = Record[0]
Value = ProtocolValue(CName, self.Packages) Value = ProtocolValue(CName, self.Packages, self.MetaFile.Path)
if Value == None: if Value == None:
PackageList = "\n\t".join([str(P) for P in self.Packages]) PackageList = "\n\t".join([str(P) for P in self.Packages])
EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
@ -2300,7 +2335,7 @@ class InfBuildData(ModuleBuildClassObject):
RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform] RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]
for Record in RecordList: for Record in RecordList:
CName = Record[0] CName = Record[0]
Value = PpiValue(CName, self.Packages) Value = PpiValue(CName, self.Packages, self.MetaFile.Path)
if Value == None: if Value == None:
PackageList = "\n\t".join([str(P) for P in self.Packages]) PackageList = "\n\t".join([str(P) for P in self.Packages])
EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
@ -2325,7 +2360,7 @@ class InfBuildData(ModuleBuildClassObject):
RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform] RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]
for Record in RecordList: for Record in RecordList:
CName = Record[0] CName = Record[0]
Value = GuidValue(CName, self.Packages) Value = GuidValue(CName, self.Packages, self.MetaFile.Path)
if Value == None: if Value == None:
PackageList = "\n\t".join([str(P) for P in self.Packages]) PackageList = "\n\t".join([str(P) for P in self.Packages])
EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
@ -2494,11 +2529,11 @@ class InfBuildData(ModuleBuildClassObject):
DepexList.append(Module.Guid) DepexList.append(Module.Guid)
else: else:
# get the GUID value now # get the GUID value now
Value = ProtocolValue(Token, self.Packages) Value = ProtocolValue(Token, self.Packages, self.MetaFile.Path)
if Value == None: if Value == None:
Value = PpiValue(Token, self.Packages) Value = PpiValue(Token, self.Packages, self.MetaFile.Path)
if Value == None: if Value == None:
Value = GuidValue(Token, self.Packages) Value = GuidValue(Token, self.Packages, self.MetaFile.Path)
if Value == None: if Value == None:
PackageList = "\n\t".join([str(P) for P in self.Packages]) PackageList = "\n\t".join([str(P) for P in self.Packages])
EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
@ -2541,7 +2576,7 @@ class InfBuildData(ModuleBuildClassObject):
PcdList.append((PcdCName, TokenSpaceGuid)) PcdList.append((PcdCName, TokenSpaceGuid))
# get the guid value # get the guid value
if TokenSpaceGuid not in self.Guids: if TokenSpaceGuid not in self.Guids:
Value = GuidValue(TokenSpaceGuid, self.Packages) Value = GuidValue(TokenSpaceGuid, self.Packages, self.MetaFile.Path)
if Value == None: if Value == None:
PackageList = "\n\t".join([str(P) for P in self.Packages]) PackageList = "\n\t".join([str(P) for P in self.Packages])
EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,