From: Yonghong Zhu Date: Tue, 10 May 2016 09:58:26 +0000 (+0800) Subject: BaseTools: support private package definition X-Git-Tag: edk2-stable201903~7022 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=c28d2e1047816164ffec552e4a3375122cbcc6b6 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 --- diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py index 0664101008..8da441f6b9 100644 --- a/BaseTools/Source/Python/AutoGen/AutoGen.py +++ b/BaseTools/Source/Python/AutoGen/AutoGen.py @@ -2174,7 +2174,7 @@ class PlatformAutoGen(AutoGen): for SkuId in PcdInModule.SkuInfoList: Sku = PcdInModule.SkuInfoList[SkuId] 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: PackageList = "\n\t".join([str(P) for P in self.PackageList]) EdkLogger.error( @@ -3395,7 +3395,11 @@ class ModuleAutoGen(AutoGen): PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir) if PackageDir not in self._IncludePathList: 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: self._IncludePathList.append(str(Inc)) return self._IncludePathList @@ -3462,7 +3466,7 @@ class ModuleAutoGen(AutoGen): for SkuName in Pcd.SkuInfoList: SkuInfo = Pcd.SkuInfoList[SkuName] Name = ConvertStringToByteArray(SkuInfo.VariableName) - Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList) + Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path) if not Value: continue Guid = GuidStructureStringToGuidString(Value) diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py index 777450d818..c99716da7d 100644 --- a/BaseTools/Source/Python/Common/Misc.py +++ b/BaseTools/Source/Python/Common/Misc.py @@ -1,7 +1,7 @@ ## @file # Common routines used by all tools # -# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 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 @@ -794,13 +794,18 @@ def GetRelPath(Path1, Path2): # # @param CName The CName of the GUID # @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 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: - 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 None @@ -808,13 +813,18 @@ def GuidValue(CName, PackageList): # # @param CName The CName of the GUID # @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 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: - 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 None @@ -822,13 +832,18 @@ def ProtocolValue(CName, PackageList): # # @param CName The CName of the GUID # @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 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: - 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 None 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,