Reviewed-by: Liming Gao <liming....@intel.com> -----Original Message----- From: Zhu, Yonghong Sent: Tuesday, May 10, 2016 6:17 PM To: edk2-devel@lists.01.org Cc: Gao, Liming <liming....@intel.com> Subject: [Patch] 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....@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Yonghong Zhu <yonghong....@intel.com> --- BaseTools/Source/Python/AutoGen/AutoGen.py | 10 ++-- BaseTools/Source/Python/Common/Misc.py | 29 ++++++++--- .../Source/Python/Workspace/MetaFileParser.py | 12 +++++ BaseTools/Source/Python/Workspace/MetaFileTable.py | 4 +- .../Source/Python/Workspace/WorkspaceDatabase.py | 59 +++++++++++++++++----- 5 files changed, 90 insertions(+), 24 deletions(-) diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py index ae0f8a6..2f2bed0 100644 --- a/BaseTools/Source/Python/AutoGen/AutoGen.py +++ b/BaseTools/Source/Python/AutoGen/AutoGen.py @@ -2172,11 +2172,11 @@ class PlatformAutoGen(AutoGen): self._OverridePcd(PcdInModule, PcdInPlatform, Module) # resolve the VariableGuid value 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( 'build', RESOURCE_NOT_AVAILABLE, @@ -3392,11 +3392,15 @@ class ModuleAutoGen(AutoGen): for Package in self.Module.Packages: 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 def _GetIncludePathLength(self): @@ -3459,11 +3463,11 @@ class ModuleAutoGen(AutoGen): if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII: continue 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) if (Name, Guid) in NameGuids and Pcd not in HiiExPcds: HiiExPcds.append(Pcd) diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py index 777450d..c99716d 100644 --- a/BaseTools/Source/Python/Common/Misc.py +++ b/BaseTools/Source/Python/Common/Misc.py @@ -1,9 +1,9 @@ ## @file # 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 # 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 # @@ -792,45 +792,60 @@ def GetRelPath(Path1, Path2): ## Get GUID value from given packages # # @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 ## Get Protocol value from given packages # # @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 ## Get PPI value from given packages # # @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 ## A string template class # diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py index 209f47c..82d874f 100644 --- a/BaseTools/Source/Python/Workspace/MetaFileParser.py +++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py @@ -1720,10 +1720,11 @@ class DecParser(MetaFileParser): def _SectionHeaderParser(self): self._Scope = [] 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 == '': EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "section name can NOT be empty or incorrectly use separator comma", @@ -1755,20 +1756,31 @@ class DecParser(MetaFileParser): S1 = 'COMMON' ArchList.add(S1) # 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]]) # 'COMMON' must not be used with specific ARCHs at the same section if 'COMMON' in ArchList and len(ArchList) > 1: 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): TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1) if len(TokenList) < 2: diff --git a/BaseTools/Source/Python/Workspace/MetaFileTable.py b/BaseTools/Source/Python/Workspace/MetaFileTable.py index 449e56e..ab18070 100644 --- a/BaseTools/Source/Python/Workspace/MetaFileTable.py +++ b/BaseTools/Source/Python/Workspace/MetaFileTable.py @@ -1,9 +1,9 @@ ## @file # 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 # 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 # @@ -216,11 +216,11 @@ class PackageTable(MetaFileTable): # # @retval: A recordSet of all found records # 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 SqlCommand = "SELECT %s FROM %s WHERE %s" % (ValueString, self.Table, ConditionString) diff --git a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py index 7cd0004..5168e83 100644 --- a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py +++ b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py @@ -1326,10 +1326,14 @@ class DecBuildData(PackageBuildClassObject): self._Guids = None self._Includes = None 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): if self.__Macros == None: self.__Macros = {} @@ -1400,81 +1404,109 @@ class DecBuildData(PackageBuildClassObject): # # tdict is a special kind of dict, used for selecting correct # 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) def _GetPpi(self): if self._Ppis == None: # # tdict is a special kind of dict, used for selecting correct # 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) def _GetGuid(self): if self._Guids == None: # # tdict is a special kind of dict, used for selecting correct # 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 for Record in RecordList: File = PathClass(NormPath(Record[0], Macros), self._PackageDir, Arch=self._Arch) @@ -1485,10 +1517,13 @@ class DecBuildData(PackageBuildClassObject): EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) # 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) def _GetLibraryClass(self): if self._LibraryClasses == None: @@ -1498,11 +1533,11 @@ class DecBuildData(PackageBuildClassObject): # LibraryClassDict = tdict(True) 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() if ErrorCode != 0: EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) @@ -1534,11 +1569,11 @@ class DecBuildData(PackageBuildClassObject): PcdDict = tdict(True, 3) # for summarizing PCD 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)) for PcdCName, TokenSpaceGuid in PcdSet: # @@ -2273,11 +2308,11 @@ class InfBuildData(ModuleBuildClassObject): self._Protocols = sdict() self._ProtocolComments = sdict() 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, "Value of Protocol [%s] is not found under [Protocols] section in" % CName, ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) @@ -2298,11 +2333,11 @@ class InfBuildData(ModuleBuildClassObject): self._Ppis = sdict() self._PpiComments = sdict() 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, "Value of PPI [%s] is not found under [Ppis] section in " % CName, ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) @@ -2323,11 +2358,11 @@ class InfBuildData(ModuleBuildClassObject): self._Guids = sdict() self._GuidComments = sdict() 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, "Value of Guid [%s] is not found under [Guids] section in" % CName, ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) @@ -2492,15 +2527,15 @@ class InfBuildData(ModuleBuildClassObject): EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform", ExtraData=Token, File=self.MetaFile, Line=Record[-1]) 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, "Value of [%s] is not found in" % Token, ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) @@ -2539,11 +2574,11 @@ class InfBuildData(ModuleBuildClassObject): for TokenSpaceGuid, PcdCName, Setting, Arch, Platform, Id, LineNo in RecordList: PcdDict[Arch, Platform, PcdCName, TokenSpaceGuid] = (Setting, LineNo) 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, "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid, ExtraData=PackageList, File=self.MetaFile, Line=LineNo) -- 2.6.1.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel