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