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
47 # to avoid re-collection collected.
48 self
.__PackageGuidInitialized
= False
49 # The internal flag to indicate whether module Guids info has been
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
64 # @retval True The Guid value is successfully added to map table.
65 # @retval False The Guid is an empty string or the map table
66 # already contains a same Guid.
68 def __AddGuidToFilePath(self
, Guid
, Version
, FilePath
):
70 EdkLogger
.info("Cannot find Guid in file %s" % FilePath
)
72 #Add the Guid value to map table to ensure case insensitive comparison.
73 OldFilePath
= self
.__GuidToFilePath
.setdefault(Guid
.lower(), FilePath
)
74 if OldFilePath
== FilePath
:
75 EdkLogger
.verbose("File %s has new Guid '%s'" % (FilePath
, Guid
))
78 EdkLogger
.info("File %s has duplicate Guid with & %s" % (FilePath
, OldFilePath
))
82 ## Gets file information from a module description file.
84 # Extracts Module Name, File Guid and Version number from INF, MSA and NMSA
85 # file. It supports to exact such information from text based INF file or
86 # XML based (N)MSA file.
88 # @param self The object pointer.
89 # @param FileName The input module file name.
91 # @retval True This module file represents a new module discovered
92 # in current workspace.
93 # @retval False This module file is not regarded as a valid module.
94 # The File Guid cannot be extracted or the another
95 # file with the same Guid already exists
97 def __GetModuleFileInfo(self
, FileName
):
98 if fnmatch
.fnmatch(FileName
, "*.inf"):
99 TagTuple
= ("BASE_NAME", "FILE_GUID", "VERSION_STRING")
100 (Name
, Guid
, Version
) = GetTextFileInfo(FileName
, TagTuple
)
102 XmlTag1
= "ModuleSurfaceArea/MsaHeader/ModuleName"
103 XmlTag2
= "ModuleSurfaceArea/MsaHeader/GuidValue"
104 XmlTag3
= "ModuleSurfaceArea/MsaHeader/Version"
105 TagTuple
= (XmlTag1
, XmlTag2
, XmlTag3
)
106 (Name
, Guid
, Version
) = GetXmlFileInfo(FileName
, TagTuple
)
108 return self
.__AddGuidToFilePath
(Guid
, Version
, FileName
)
111 ## Gets file information from a package description file.
113 # Extracts Package Name, File Guid and Version number from INF, SPD and NSPD
114 # file. It supports to exact such information from text based DEC file or
115 # XML based (N)SPD file. EDK Compatibility Package is hardcoded to be
116 # ignored since no EDKII INF file depends on that package.
118 # @param self The object pointer.
119 # @param FileName The input package file name.
121 # @retval True This package file represents a new package
122 # discovered in current workspace.
123 # @retval False This package is not regarded as a valid package.
124 # The File Guid cannot be extracted or the another
125 # file with the same Guid already exists
127 def __GetPackageFileInfo(self
, FileName
):
128 if fnmatch
.fnmatch(FileName
, "*.dec"):
129 TagTuple
= ("PACKAGE_NAME", "PACKAGE_GUID", "PACKAGE_VERSION")
130 (Name
, Guid
, Version
) = GetTextFileInfo(FileName
, TagTuple
)
132 XmlTag1
= "PackageSurfaceArea/SpdHeader/PackageName"
133 XmlTag2
= "PackageSurfaceArea/SpdHeader/GuidValue"
134 XmlTag3
= "PackageSurfaceArea/SpdHeader/Version"
135 TagTuple
= (XmlTag1
, XmlTag2
, XmlTag3
)
136 (Name
, Guid
, Version
) = GetXmlFileInfo(FileName
, TagTuple
)
138 if Name
== "EdkCompatibilityPkg":
139 # Do not scan EDK compatibitilty package to avoid Guid collision
140 # with those in EDK Glue Library.
141 EdkLogger
.verbose("Bypass EDK Compatibility Pkg")
144 return self
.__AddGuidToFilePath
(Guid
, Version
, FileName
)
146 ## Iterate on all package files listed in framework database file.
148 # Yields all package description files listed in framework database files.
149 # The framework database file describes the packages current workspace
152 # @param self The object pointer.
154 def __FrameworkDatabasePackageFiles(self
):
155 XmlFrameworkDb
= XmlParseFile(self
.WorkspaceFile
)
156 XmlTag
= "FrameworkDatabase/PackageList/Filename"
157 for PackageFile
in XmlElementList(XmlFrameworkDb
, XmlTag
):
158 yield os
.path
.join(self
.WorkspaceDir
, PackageFile
)
161 ## Iterate on all package files in current workspace directory.
163 # Yields all package description files listed in current workspace
164 # directory. This happens when no framework database file exists.
166 # @param self The object pointer.
168 def __TraverseAllPackageFiles(self
):
169 for Path
, Dirs
, Files
in os
.walk(self
.WorkspaceDir
):
170 # Ignore svn version control directory.
175 # Assume priority from high to low: DEC, NSPD, SPD.
176 PackageFiles
= fnmatch
.filter(Files
, "*.dec")
177 if len(PackageFiles
) == 0:
178 PackageFiles
= fnmatch
.filter(Files
, "*.nspd")
179 if len(PackageFiles
) == 0:
180 PackageFiles
= fnmatch
.filter(Files
, "*.spd")
182 for File
in PackageFiles
:
183 # Assume no more package decription file in sub-directory.
185 yield os
.path
.join(Path
, File
)
187 ## Iterate on all module files in current package directory.
189 # Yields all module description files listed in current package
192 # @param self The object pointer.
194 def __TraverseAllModuleFiles(self
):
195 for PackageDir
in self
.__PackageDirList
:
196 for Path
, Dirs
, Files
in os
.walk(PackageDir
):
197 # Ignore svn version control directory.
200 # Assume priority from high to low: INF, NMSA, MSA.
201 ModuleFiles
= fnmatch
.filter(Files
, "*.inf")
202 if len(ModuleFiles
) == 0:
203 ModuleFiles
= fnmatch
.filter(Files
, "*.nmsa")
204 if len(ModuleFiles
) == 0:
205 ModuleFiles
= fnmatch
.filter(Files
, "*.msa")
207 for File
in ModuleFiles
:
208 yield os
.path
.join(Path
, File
)
210 ## Initialize package Guids info mapping table.
212 # Collects all package guids map to package decription file path. This
213 # function is invokes on demand to avoid unnecessary directory scan.
215 # @param self The object pointer.
217 def __InitializePackageGuidInfo(self
):
218 if self
.__PackageGuidInitialized
:
221 EdkLogger
.verbose("Start to collect Package Guids Info.")
223 WorkspaceFile
= os
.path
.join("Conf", "FrameworkDatabase.db")
224 self
.WorkspaceFile
= os
.path
.join(self
.WorkspaceDir
, WorkspaceFile
)
226 # Try to find the frameworkdatabase file to discover package lists
227 if os
.path
.exists(self
.WorkspaceFile
):
228 TraversePackage
= self
.__FrameworkDatabasePackageFiles
229 EdkLogger
.verbose("Package list bases on: %s" % self
.WorkspaceFile
)
231 TraversePackage
= self
.__TraverseAllPackageFiles
232 EdkLogger
.verbose("Package list in: %s" % self
.WorkspaceDir
)
234 for FileName
in TraversePackage():
235 if self
.__GetPackageFileInfo
(FileName
):
236 PackageDir
= os
.path
.dirname(FileName
)
237 EdkLogger
.verbose("Find new package directory %s" % PackageDir
)
238 self
.__PackageDirList
.append(PackageDir
)
240 self
.__PackageGuidInitialized
= True
242 ## Initialize module Guids info mapping table.
244 # Collects all module guids map to module decription file path. This
245 # function is invokes on demand to avoid unnecessary directory scan.
247 # @param self The object pointer.
249 def __InitializeModuleGuidInfo(self
):
250 if self
.__ModuleGuidInitialized
:
252 EdkLogger
.verbose("Start to collect Module Guids Info")
254 self
.__InitializePackageGuidInfo
()
255 for FileName
in self
.__TraverseAllModuleFiles
():
256 if self
.__GetModuleFileInfo
(FileName
):
257 EdkLogger
.verbose("Find new module %s" % FileName
)
259 self
.__ModuleGuidInitialized
= True
261 ## Get Package file path by Package guid and Version.
263 # Translates the Package Guid and Version to a file path relative
264 # to workspace directory. If no package in current workspace match the
265 # input Guid, an empty file path is returned. For now, the version
266 # value is simply ignored.
268 # @param self The object pointer.
269 # @param Guid The Package Guid value to look for.
270 # @param Version The Package Version value to look for.
272 def ResolvePackageFilePath(self
, Guid
, Version
= ""):
273 self
.__InitializePackageGuidInfo
()
275 EdkLogger
.verbose("Resolve Package Guid '%s'" % Guid
)
276 FileName
= self
.__GuidToFilePath
.get(Guid
.lower(), "")
278 EdkLogger
.info("Cannot resolve Package Guid '%s'" % Guid
)
280 FileName
= self
.WorkspaceRelativePath(FileName
)
281 FileName
= os
.path
.splitext(FileName
)[0] + ".dec"
282 FileName
= FileName
.replace("\\", "/")
285 ## Get Module file path by Package guid and Version.
287 # Translates the Module Guid and Version to a file path relative
288 # to workspace directory. If no module in current workspace match the
289 # input Guid, an empty file path is returned. For now, the version
290 # value is simply ignored.
292 # @param self The object pointer.
293 # @param Guid The Module Guid value to look for.
294 # @param Version The Module Version value to look for.
296 def ResolveModuleFilePath(self
, Guid
, Version
= ""):
297 self
.__InitializeModuleGuidInfo
()
299 EdkLogger
.verbose("Resolve Module Guid '%s'" % Guid
)
300 FileName
= self
.__GuidToFilePath
.get(Guid
.lower(), "")
302 EdkLogger
.info("Cannot resolve Module Guid '%s'" % Guid
)
304 FileName
= self
.WorkspaceRelativePath(FileName
)
305 FileName
= os
.path
.splitext(FileName
)[0] + ".inf"
306 FileName
= FileName
.replace("\\", "/")
309 # A global class object of EdkIIWorkspaceGuidsInfo for external reference.
310 gEdkIIWorkspaceGuidsInfo
= EdkIIWorkspaceGuidsInfo()
312 # This acts like the main() function for the script, unless it is 'import'ed
313 # into another script.
314 if __name__
== '__main__':
315 # Test the translation of package Guid.
316 MdePkgGuid
= "1E73767F-8F52-4603-AEB4-F29B510B6766"
317 OldMdePkgGuid
= "5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"
318 print gEdkIIWorkspaceGuidsInfo
.ResolveModuleFilePath(MdePkgGuid
)
319 print gEdkIIWorkspaceGuidsInfo
.ResolveModuleFilePath(OldMdePkgGuid
)
321 # Test the translation of module Guid.
322 UefiLibGuid
= "3a004ba5-efe0-4a61-9f1a-267a46ae5ba9"
323 UefiDriverModelLibGuid
= "52af22ae-9901-4484-8cdc-622dd5838b09"
324 print gEdkIIWorkspaceGuidsInfo
.ResolveModuleFilePath(UefiLibGuid
)
325 print gEdkIIWorkspaceGuidsInfo
.ResolveModuleFilePath(UefiDriverModelLibGuid
)