From c28d2e1047816164ffec552e4a3375122cbcc6b6 Mon Sep 17 00:00:00 2001 From: Yonghong Zhu Date: Tue, 10 May 2016 17:58:26 +0800 Subject: 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 Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Yonghong Zhu Reviewed-by: Liming Gao --- .../Source/Python/Workspace/MetaFileParser.py | 12 +++++ BaseTools/Source/Python/Workspace/MetaFileTable.py | 4 +- .../Source/Python/Workspace/WorkspaceDatabase.py | 59 +++++++++++++++++----- 3 files changed, 61 insertions(+), 14 deletions(-) (limited to 'BaseTools/Source/Python/Workspace') diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py index 209f47c9eb..82d874f8dd 100644 --- a/BaseTools/Source/Python/Workspace/MetaFileParser.py +++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py @@ -1722,6 +1722,7 @@ class DecParser(MetaFileParser): self._SectionName = '' self._SectionType = [] ArchList = set() + PrivateList = set() 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): if Item == '': @@ -1757,8 +1758,14 @@ class DecParser(MetaFileParser): # S2 may be Platform or ModuleType if len(ItemList) > 2: 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: S2 = 'COMMON' + PrivateList.add(S2) if [S1, S2, self.DataType[self._SectionName]] not in self._Scope: 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", 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 @ParseMacro def _GuidParser(self): diff --git a/BaseTools/Source/Python/Workspace/MetaFileTable.py b/BaseTools/Source/Python/Workspace/MetaFileTable.py index 449e56efcc..ab1807046e 100644 --- a/BaseTools/Source/Python/Workspace/MetaFileTable.py +++ b/BaseTools/Source/Python/Workspace/MetaFileTable.py @@ -1,7 +1,7 @@ ## @file # This file is used to create/update/query/erase a meta file table # -# Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.
# 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 @@ -218,7 +218,7 @@ class PackageTable(MetaFileTable): # def Query(self, Model, Arch=None): 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': ConditionString += " AND (Scope1='%s' OR Scope1='COMMON')" % Arch diff --git a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py index 7cd0004688..5168e838a8 100644 --- a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py +++ b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py @@ -1328,6 +1328,10 @@ class DecBuildData(PackageBuildClassObject): self._LibraryClasses = None self._Pcds = None self.__Macros = None + self._PrivateProtocols = None + self._PrivatePpis = None + self._PrivateGuids = None + self._PrivateIncludes = None ## Get current effective macros def _GetMacros(self): @@ -1402,21 +1406,30 @@ class DecBuildData(PackageBuildClassObject): # protocol defition for given ARCH # ProtocolDict = tdict(True) + PrivateProtocolDict = tdict(True) NameList = [] + PrivateNameList = [] # find out all protocol definitions for specific and 'common' 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: NameList.append(Name) ProtocolDict[Arch, Name] = Guid # use sdict to keep the order self._Protocols = sdict() + self._PrivateProtocols = sdict() for Name in NameList: # # limit the ARCH to self._Arch, if no self._Arch found, tdict # will automatically turn to 'common' ARCH for trying # self._Protocols[Name] = ProtocolDict[self._Arch, Name] + for Name in PrivateNameList: + self._PrivateProtocols[Name] = PrivateProtocolDict[self._Arch, Name] return self._Protocols ## Retrieve PPI definitions (name/value pairs) @@ -1427,21 +1440,30 @@ class DecBuildData(PackageBuildClassObject): # PPI defition for given ARCH # PpiDict = tdict(True) + PrivatePpiDict = tdict(True) NameList = [] + PrivateNameList = [] # find out all PPI definitions for specific arch and 'common' 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: NameList.append(Name) PpiDict[Arch, Name] = Guid # use sdict to keep the order self._Ppis = sdict() + self._PrivatePpis = sdict() for Name in NameList: # # limit the ARCH to self._Arch, if no self._Arch found, tdict # will automatically turn to 'common' ARCH for trying # self._Ppis[Name] = PpiDict[self._Arch, Name] + for Name in PrivateNameList: + self._PrivatePpis[Name] = PrivatePpiDict[self._Arch, Name] return self._Ppis ## Retrieve GUID definitions (name/value pairs) @@ -1452,27 +1474,37 @@ class DecBuildData(PackageBuildClassObject): # GUID defition for given ARCH # GuidDict = tdict(True) + PrivateGuidDict = tdict(True) NameList = [] + PrivateNameList = [] # find out all protocol definitions for specific and 'common' 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: NameList.append(Name) GuidDict[Arch, Name] = Guid # use sdict to keep the order self._Guids = sdict() + self._PrivateGuids = sdict() for Name in NameList: # # limit the ARCH to self._Arch, if no self._Arch found, tdict # will automatically turn to 'common' ARCH for trying # self._Guids[Name] = GuidDict[self._Arch, Name] + for Name in PrivateNameList: + self._PrivateGuids[Name] = PrivateGuidDict[self._Arch, Name] return self._Guids ## Retrieve public include paths declared in this package def _GetInclude(self): if self._Includes == None: self._Includes = [] + self._PrivateIncludes = [] RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch] Macros = self._Macros Macros["EDK_SOURCE"] = GlobalData.gEcpSource @@ -1487,6 +1519,9 @@ class DecBuildData(PackageBuildClassObject): # avoid duplicate include path if File not in self._Includes: self._Includes.append(File) + if Record[4] == 'PRIVATE': + if File not in self._PrivateIncludes: + self._PrivateIncludes.append(File) return self._Includes ## Retrieve library class declarations (not used in build at present) @@ -1500,7 +1535,7 @@ class DecBuildData(PackageBuildClassObject): LibraryClassSet = set() RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch] 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) # check the file validation ErrorCode, ErrorInfo = File.Validate() @@ -1536,7 +1571,7 @@ class DecBuildData(PackageBuildClassObject): PcdSet = set() # find out all PCDs of the 'type' 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 PcdSet.add((PcdCName, TokenSpaceGuid)) @@ -2275,7 +2310,7 @@ class InfBuildData(ModuleBuildClassObject): RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform] for Record in RecordList: CName = Record[0] - Value = ProtocolValue(CName, self.Packages) + Value = ProtocolValue(CName, self.Packages, self.MetaFile.Path) if Value == None: PackageList = "\n\t".join([str(P) for P in self.Packages]) EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, @@ -2300,7 +2335,7 @@ class InfBuildData(ModuleBuildClassObject): RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform] for Record in RecordList: CName = Record[0] - Value = PpiValue(CName, self.Packages) + Value = PpiValue(CName, self.Packages, self.MetaFile.Path) if Value == None: PackageList = "\n\t".join([str(P) for P in self.Packages]) EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, @@ -2325,7 +2360,7 @@ class InfBuildData(ModuleBuildClassObject): RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform] for Record in RecordList: CName = Record[0] - Value = GuidValue(CName, self.Packages) + Value = GuidValue(CName, self.Packages, self.MetaFile.Path) if Value == None: PackageList = "\n\t".join([str(P) for P in self.Packages]) EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, @@ -2494,11 +2529,11 @@ class InfBuildData(ModuleBuildClassObject): DepexList.append(Module.Guid) else: # get the GUID value now - Value = ProtocolValue(Token, self.Packages) + Value = ProtocolValue(Token, self.Packages, self.MetaFile.Path) if Value == None: - Value = PpiValue(Token, self.Packages) + Value = PpiValue(Token, self.Packages, self.MetaFile.Path) if Value == None: - Value = GuidValue(Token, self.Packages) + Value = GuidValue(Token, self.Packages, self.MetaFile.Path) if Value == None: PackageList = "\n\t".join([str(P) for P in self.Packages]) EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, @@ -2541,7 +2576,7 @@ class InfBuildData(ModuleBuildClassObject): PcdList.append((PcdCName, TokenSpaceGuid)) # get the guid value if TokenSpaceGuid not in self.Guids: - Value = GuidValue(TokenSpaceGuid, self.Packages) + Value = GuidValue(TokenSpaceGuid, self.Packages, self.MetaFile.Path) if Value == None: PackageList = "\n\t".join([str(P) for P in self.Packages]) EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, -- cgit v1.2.3