2 # Collects the Guid Information in current workspace.
4 # Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 from Common
.EdkIIWorkspace
import EdkIIWorkspace
20 from Common
.MigrationUtilities
import *
22 ## A class for EdkII work space to resolve Guids
24 # This class inherits from EdkIIWorkspace and collects the Guids information
25 # in current workspace. The Guids information is important to translate the
26 # package Guids and recommended library instances Guids to relative file path
27 # (to workspace directory) in MSA files.
29 class EdkIIWorkspaceGuidsInfo(EdkIIWorkspace
):
31 ## The classconstructor
33 # The constructor initialize workspace directory. It does not collect
34 # pakage and module Guids info at initialization; instead, it collects them
37 # @param self The object pointer
40 # Initialize parent class.
41 EdkIIWorkspace
.__init
__(self
)
42 # The internal map from Guid to FilePath.
43 self
.__GuidToFilePath
= {}
44 # The internal package directory list.
45 self
.__PackageDirList
= []
46 # The internal flag to indicate whether package Guids info has been initialized
47 # to avoid re-collection collected.
48 self
.__PackageGuidInitialized
= False
49 # The internal flag to indicate whether module Guids info has been initialized
50 # to avoid re-collection collected.
51 self
.__ModuleGuidInitialized
= False
53 ## Add Guid, Version and FilePath to Guids database
55 # Add Guid, Version and FilePath to Guids database. It constructs a map
56 # table from Guid, Version to FilePath internally. If also detects possible
57 # Guid collision. For now, the version information is simply ignored and
58 # Guid value itself acts as master key.
60 # @param self The object pointer
61 # @param Guid The Guid Value
62 # @param Version The version information
63 # @param FilePath The Guid related file path
65 # @retval True The Guid value is successfully added to map table
66 # @retval False The Guid is an empty string or the map table
67 # already contains a same Guid
69 def __AddGuidToFilePath(self
, Guid
, Version
, FilePath
):
71 EdkLogger
.info("Cannot find Guid in file %s" % FilePath
)
73 #Add the Guid value to map table to ensure case insensitive comparison.
74 OldFilePath
= self
.__GuidToFilePath
.setdefault(Guid
.lower(), FilePath
)
75 if OldFilePath
== FilePath
:
76 EdkLogger
.verbose("File %s has new Guid '%s'" % (FilePath
, Guid
))
79 EdkLogger
.info("File %s has duplicate Guid with & %s" % (FilePath
, OldFilePath
))
83 ## Gets file information from a module description file
85 # Extracts Module Name, File Guid and Version number from INF, MSA and NMSA
86 # file. It supports to exact such information from text based INF file or
87 # XML based (N)MSA file.
89 # @param self The object pointer
90 # @param FileName The input module file name
92 # @retval True This module file represents a new module discovered
93 # in current workspace
94 # @retval False This module file is not regarded as a valid module
95 # The File Guid cannot be extracted or the another
96 # file with the same Guid already exists
98 def __GetModuleFileInfo(self
, FileName
):
99 if fnmatch
.fnmatch(FileName
, "*.inf"):
100 TagTuple
= ("BASE_NAME", "FILE_GUID", "VERSION_STRING")
101 (Name
, Guid
, Version
) = GetTextFileInfo(FileName
, TagTuple
)
103 XmlTag1
= "ModuleSurfaceArea/MsaHeader/ModuleName"
104 XmlTag2
= "ModuleSurfaceArea/MsaHeader/GuidValue"
105 XmlTag3
= "ModuleSurfaceArea/MsaHeader/Version"
106 TagTuple
= (XmlTag1
, XmlTag2
, XmlTag3
)
107 (Name
, Guid
, Version
) = GetXmlFileInfo(FileName
, TagTuple
)
109 return self
.__AddGuidToFilePath
(Guid
, Version
, FileName
)
112 ## Gets file information from a package description file
114 # Extracts Package Name, File Guid and Version number from INF, SPD and NSPD
115 # file. It supports to exact such information from text based DEC file or
116 # XML based (N)SPD file. EDK Compatibility Package is hardcoded to be
117 # ignored since no EDKII INF file depends on that package.
119 # @param self The object pointer
120 # @param FileName The input package file name
122 # @retval True This package file represents a new package
123 # discovered in current workspace
124 # @retval False This package is not regarded as a valid package
125 # The File Guid cannot be extracted or the another
126 # file with the same Guid already exists
128 def __GetPackageFileInfo(self
, FileName
):
129 if fnmatch
.fnmatch(FileName
, "*.dec"):
130 TagTuple
= ("PACKAGE_NAME", "PACKAGE_GUID", "PACKAGE_VERSION")
131 (Name
, Guid
, Version
) = GetTextFileInfo(FileName
, TagTuple
)
133 XmlTag1
= "PackageSurfaceArea/SpdHeader/PackageName"
134 XmlTag2
= "PackageSurfaceArea/SpdHeader/GuidValue"
135 XmlTag3
= "PackageSurfaceArea/SpdHeader/Version"
136 TagTuple
= (XmlTag1
, XmlTag2
, XmlTag3
)
137 (Name
, Guid
, Version
) = GetXmlFileInfo(FileName
, TagTuple
)
139 if Name
== "EdkCompatibilityPkg":
140 # Do not scan EDK compatibitilty package to avoid Guid collision
141 # with those in EDK Glue Library.
142 EdkLogger
.verbose("Bypass EDK Compatibility Pkg")
145 return self
.__AddGuidToFilePath
(Guid
, Version
, FileName
)
147 ## Iterate on all package files listed in framework database file
149 # Yields all package description files listed in framework database files.
150 # The framework database file describes the packages current workspace
153 # @param self The object pointer
155 def __FrameworkDatabasePackageFiles(self
):
156 XmlFrameworkDb
= XmlParseFile(self
.WorkspaceFile
)
157 XmlTag
= "FrameworkDatabase/PackageList/Filename"
158 for PackageFile
in XmlElementList(XmlFrameworkDb
, XmlTag
):
159 yield os
.path
.join(self
.WorkspaceDir
, PackageFile
)
162 ## Iterate on all package files in current workspace directory
164 # Yields all package description files listed in current workspace
165 # directory. This happens when no framework database file exists.
167 # @param self The object pointer
169 def __TraverseAllPackageFiles(self
):
170 for Path
, Dirs
, Files
in os
.walk(self
.WorkspaceDir
):
171 # Ignore svn version control directory.
176 # Assume priority from high to low: DEC, NSPD, SPD.
177 PackageFiles
= fnmatch
.filter(Files
, "*.dec")
178 if len(PackageFiles
) == 0:
179 PackageFiles
= fnmatch
.filter(Files
, "*.nspd")
180 if len(PackageFiles
) == 0:
181 PackageFiles
= fnmatch
.filter(Files
, "*.spd")
183 for File
in PackageFiles
:
184 # Assume no more package decription file in sub-directory.
186 yield os
.path
.join(Path
, File
)
188 ## Iterate on all module files in current package directory
190 # Yields all module description files listed in current package
193 # @param self The object pointer
195 def __TraverseAllModuleFiles(self
):
196 for PackageDir
in self
.__PackageDirList
:
197 for Path
, Dirs
, Files
in os
.walk(PackageDir
):
198 # Ignore svn version control directory.
201 # Assume priority from high to low: INF, NMSA, MSA.
202 ModuleFiles
= fnmatch
.filter(Files
, "*.inf")
203 if len(ModuleFiles
) == 0:
204 ModuleFiles
= fnmatch
.filter(Files
, "*.nmsa")
205 if len(ModuleFiles
) == 0:
206 ModuleFiles
= fnmatch
.filter(Files
, "*.msa")
208 for File
in ModuleFiles
:
209 yield os
.path
.join(Path
, File
)
211 ## Initialize package Guids info mapping table
213 # Collects all package guids map to package decription file path. This
214 # function is invokes on demand to avoid unnecessary directory scan.
216 # @param self The object pointer
218 def __InitializePackageGuidInfo(self
):
219 if self
.__PackageGuidInitialized
:
222 EdkLogger
.verbose("Start to collect Package Guids Info.")
224 WorkspaceFile
= os
.path
.join("Conf", "FrameworkDatabase.db")
225 self
.WorkspaceFile
= os
.path
.join(self
.WorkspaceDir
, WorkspaceFile
)
227 # Try to find the frameworkdatabase file to discover package lists
228 if os
.path
.exists(self
.WorkspaceFile
):
229 TraversePackage
= self
.__FrameworkDatabasePackageFiles
230 EdkLogger
.verbose("Package list bases on: %s" % self
.WorkspaceFile
)
232 TraversePackage
= self
.__TraverseAllPackageFiles
233 EdkLogger
.verbose("Package list in: %s" % self
.WorkspaceDir
)
235 for FileName
in TraversePackage():
236 if self
.__GetPackageFileInfo
(FileName
):
237 PackageDir
= os
.path
.dirname(FileName
)
238 EdkLogger
.verbose("Find new package directory %s" % PackageDir
)
239 self
.__PackageDirList
.append(PackageDir
)
241 self
.__PackageGuidInitialized
= True
243 ## Initialize module Guids info mapping table
245 # Collects all module guids map to module decription file path. This
246 # function is invokes on demand to avoid unnecessary directory scan.
248 # @param self The object pointer
250 def __InitializeModuleGuidInfo(self
):
251 if self
.__ModuleGuidInitialized
:
253 EdkLogger
.verbose("Start to collect Module Guids Info")
255 self
.__InitializePackageGuidInfo
()
256 for FileName
in self
.__TraverseAllModuleFiles
():
257 if self
.__GetModuleFileInfo
(FileName
):
258 EdkLogger
.verbose("Find new module %s" % FileName
)
260 self
.__ModuleGuidInitialized
= True
262 ## Get Package file path by Package Guid and Version
264 # Translates the Package Guid and Version to a file path relative
265 # to workspace directory. If no package in current workspace match the
266 # input Guid, an empty file path is returned. For now, the version
267 # value is simply ignored.
269 # @param self The object pointer
270 # @param Guid The Package Guid value to look for
271 # @param Version The Package Version value to look for
273 def ResolvePackageFilePath(self
, Guid
, Version
= ""):
274 self
.__InitializePackageGuidInfo
()
276 EdkLogger
.verbose("Resolve Package Guid '%s'" % Guid
)
277 FileName
= self
.__GuidToFilePath
.get(Guid
.lower(), "")
279 EdkLogger
.info("Cannot resolve Package Guid '%s'" % Guid
)
281 FileName
= self
.WorkspaceRelativePath(FileName
)
282 FileName
= os
.path
.splitext(FileName
)[0] + ".dec"
283 FileName
= FileName
.replace("\\", "/")
286 ## Get Module file path by Module Guid and Version
288 # Translates the Module Guid and Version to a file path relative
289 # to workspace directory. If no module in current workspace match the
290 # input Guid, an empty file path is returned. For now, the version
291 # value is simply ignored.
293 # @param self The object pointer
294 # @param Guid The Module Guid value to look for
295 # @param Version The Module Version value to look for
297 def ResolveModuleFilePath(self
, Guid
, Version
= ""):
298 self
.__InitializeModuleGuidInfo
()
300 EdkLogger
.verbose("Resolve Module Guid '%s'" % Guid
)
301 FileName
= self
.__GuidToFilePath
.get(Guid
.lower(), "")
303 EdkLogger
.info("Cannot resolve Module Guid '%s'" % Guid
)
305 FileName
= self
.WorkspaceRelativePath(FileName
)
306 FileName
= os
.path
.splitext(FileName
)[0] + ".inf"
307 FileName
= FileName
.replace("\\", "/")
310 # A global class object of EdkIIWorkspaceGuidsInfo for external reference.
311 gEdkIIWorkspaceGuidsInfo
= EdkIIWorkspaceGuidsInfo()
313 # This acts like the main() function for the script, unless it is 'import'ed
314 # into another script.
315 if __name__
== '__main__':
316 # Test the translation of package Guid.
317 # MdePkgGuid = "1E73767F-8F52-4603-AEB4-F29B510B6766"
318 # OldMdePkgGuid = "5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"
319 # print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(MdePkgGuid)
320 # print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(OldMdePkgGuid)
322 # Test the translation of module Guid.
323 # UefiLibGuid = "3a004ba5-efe0-4a61-9f1a-267a46ae5ba9"
324 # UefiDriverModelLibGuid = "52af22ae-9901-4484-8cdc-622dd5838b09"
325 # print gEdkIIWorkspaceGuidsInfo.ResolvePlatformFilePath(UefiLibGuid)
326 # print gEdkIIWorkspaceGuidsInfo.ResolvePlatformFilePath(UefiDriverModelLibGuid)