Fix a bug to identify all installed PPIs
[mirror/efi/basetools/.git] / Source / Python / Eot / Parser.py
1 ## @file\r
2 # This file is used to define common parsing related functions used in parsing\r
3 # Inf/Dsc/Makefile process\r
4 #\r
5 # Copyright (c) 2008 - 2010, Intel Corporation\r
6 # All rights reserved. This program and the accompanying materials\r
7 # are licensed and made available under the terms and conditions of the BSD License\r
8 # which accompanies this distribution.  The full text of the license may be found at\r
9 # http://opensource.org/licenses/bsd-license.php\r
10 #\r
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 #\r
14 \r
15 ##\r
16 # Import Modules\r
17 #\r
18 import os, re\r
19 import Common.EdkLogger as EdkLogger\r
20 from Common.DataType import *\r
21 from CommonDataClass.DataClass import *\r
22 from Common.String import CleanString, GetSplitValueList, ReplaceMacro\r
23 import EotGlobalData\r
24 from Common.Misc import sdict\r
25 \r
26 ## PreProcess() method\r
27 #\r
28 #  Pre process a file\r
29 #\r
30 #  1. Remove all comments\r
31 #  2. Merge multiple lines code to one line\r
32 #\r
33 #  @param  Filename: Name of the file to be parsed\r
34 #  @param  MergeMultipleLines: Switch for if merge multiple lines\r
35 #  @param  LineNo: Default line no\r
36 #\r
37 #  @return Lines: The file contents after remvoing comments\r
38 #\r
39 def PreProcess(Filename, MergeMultipleLines = True, LineNo = -1):\r
40     Lines = []\r
41     Filename = os.path.normpath(Filename)\r
42     if not os.path.isfile(Filename):\r
43         EdkLogger.error("Eot", EdkLogger.FILE_NOT_FOUND, ExtraData=Filename)\r
44 \r
45     IsFindBlockComment = False\r
46     IsFindBlockCode = False\r
47     ReservedLine = ''\r
48     ReservedLineLength = 0\r
49     for Line in open(Filename, 'r'):\r
50         Line = Line.strip()\r
51         # Remove comment block\r
52         if Line.find(TAB_COMMENT_R8_START) > -1:\r
53             ReservedLine = GetSplitValueList(Line, TAB_COMMENT_R8_START, 1)[0]\r
54             IsFindBlockComment = True\r
55         if Line.find(TAB_COMMENT_R8_END) > -1:\r
56             Line = ReservedLine + GetSplitValueList(Line, TAB_COMMENT_R8_END, 1)[1]\r
57             ReservedLine = ''\r
58             IsFindBlockComment = False\r
59         if IsFindBlockComment:\r
60             Lines.append('')\r
61             continue\r
62 \r
63         # Remove comments at tail and remove spaces again\r
64         Line = CleanString(Line)\r
65         if Line == '':\r
66             Lines.append('')\r
67             continue\r
68 \r
69         if MergeMultipleLines:\r
70             # Add multiple lines to one line\r
71             if IsFindBlockCode and Line[-1] != TAB_SLASH:\r
72                 ReservedLine = (ReservedLine + TAB_SPACE_SPLIT + Line).strip()\r
73                 Lines.append(ReservedLine)\r
74                 for Index in (0, ReservedLineLength):\r
75                     Lines.append('')\r
76                 ReservedLine = ''\r
77                 ReservedLineLength = 0\r
78                 IsFindBlockCode = False\r
79                 continue\r
80             if Line[-1] == TAB_SLASH:\r
81                 ReservedLine = ReservedLine +  TAB_SPACE_SPLIT + Line[0:-1].strip()\r
82                 ReservedLineLength = ReservedLineLength + 1\r
83                 IsFindBlockCode = True\r
84                 continue\r
85 \r
86         Lines.append(Line)\r
87 \r
88     return Lines\r
89 \r
90 ## AddToGlobalMacro() method\r
91 #\r
92 #  Add a macro to EotGlobalData.gMACRO\r
93 #\r
94 #  @param  Name: Name of the macro\r
95 #  @param  Value: Value of the macro\r
96 #\r
97 def AddToGlobalMacro(Name, Value):\r
98     Value = ReplaceMacro(Value, EotGlobalData.gMACRO, True)\r
99     EotGlobalData.gMACRO[Name] = Value\r
100 \r
101 ## AddToSelfMacro() method\r
102 #\r
103 #  Parse a line of macro definition and add it to a macro set\r
104 #\r
105 #  @param  SelfMacro: The self macro set\r
106 #  @param  Line: The line of a macro definition\r
107 #\r
108 #  @return Name: Name of macro\r
109 #  @return Value: Value of macro\r
110 #\r
111 def AddToSelfMacro(SelfMacro, Line):\r
112     Name, Value = '', ''\r
113     List = GetSplitValueList(Line, TAB_EQUAL_SPLIT, 1)\r
114     if len(List) == 2:\r
115         Name = List[0]\r
116         Value = List[1]\r
117         Value = ReplaceMacro(Value, EotGlobalData.gMACRO, True)\r
118         Value = ReplaceMacro(Value, SelfMacro, True)\r
119         SelfMacro[Name] = Value\r
120 \r
121     return (Name, Value)\r
122 \r
123 ## GetIncludeListOfFile() method\r
124 #\r
125 #  Get the include path list for a source file\r
126 #\r
127 #  1. Find the source file belongs to which INF file\r
128 #  2. Find the inf's package\r
129 #  3. Return the include path list of the package\r
130 #\r
131 #  @param  WorkSpace: WORKSPACE path\r
132 #  @param  Filepath: File path\r
133 #  @param  Db: Eot database\r
134 #\r
135 #  @return IncludeList: A list of include directories\r
136 #\r
137 def GetIncludeListOfFile(WorkSpace, Filepath, Db):\r
138     IncludeList = []\r
139     Filepath = os.path.normpath(Filepath)\r
140     SqlCommand = """\r
141                 select Value1 from Inf where Model = %s and BelongsToFile in(\r
142                     select distinct B.BelongsToFile from File as A left join Inf as B\r
143                         where A.ID = B.BelongsToFile and B.Model = %s and (A.Path || '%s' || B.Value1) = '%s')""" \\r
144                 % (MODEL_META_DATA_PACKAGE, MODEL_EFI_SOURCE_FILE, '\\', Filepath)\r
145     RecordSet = Db.TblFile.Exec(SqlCommand)\r
146     for Record in RecordSet:\r
147         DecFullPath = os.path.normpath(os.path.join(WorkSpace, Record[0]))\r
148         (DecPath, DecName) = os.path.split(DecFullPath)\r
149         SqlCommand = """select Value1 from Dec where BelongsToFile =\r
150                            (select ID from File where FullPath = '%s') and Model = %s""" \\r
151                     % (DecFullPath, MODEL_EFI_INCLUDE)\r
152         NewRecordSet = Db.TblDec.Exec(SqlCommand)\r
153         for NewRecord in NewRecordSet:\r
154             IncludePath = os.path.normpath(os.path.join(DecPath, NewRecord[0]))\r
155             if IncludePath not in IncludeList:\r
156                 IncludeList.append(IncludePath)\r
157 \r
158     return IncludeList\r
159 \r
160 ## GetTableList() method\r
161 #\r
162 #  Search table file and find all small tables\r
163 #\r
164 #  @param  FileModelList: Model code for the file list\r
165 #  @param  Table: Table to insert records\r
166 #  @param  Db: Eot database\r
167 #\r
168 #  @return TableList: A list of tables\r
169 #\r
170 def GetTableList(FileModelList, Table, Db):\r
171     TableList = []\r
172     SqlCommand = """select ID, FullPath from File where Model in %s""" % str(FileModelList)\r
173     RecordSet = Db.TblFile.Exec(SqlCommand)\r
174     for Record in RecordSet:\r
175         TableName = Table + str(Record[0])\r
176         TableList.append([TableName, Record[1]])\r
177 \r
178     return TableList\r
179 \r
180 ## GetAllIncludeDir() method\r
181 #\r
182 #  Find all Include directories\r
183 #\r
184 #  @param  Db: Eot database\r
185 #\r
186 #  @return IncludeList: A list of include directories\r
187 #\r
188 def GetAllIncludeDirs(Db):\r
189     IncludeList = []\r
190     SqlCommand = """select distinct Value1 from Inf where Model = %s order by Value1""" % MODEL_EFI_INCLUDE\r
191     RecordSet = Db.TblInf.Exec(SqlCommand)\r
192 \r
193     for Record in RecordSet:\r
194         IncludeList.append(Record[0])\r
195 \r
196     return IncludeList\r
197 \r
198 ## GetAllIncludeFiles() method\r
199 #\r
200 #  Find all Include files\r
201 #\r
202 #  @param  Db: Eot database\r
203 #\r
204 #  @return IncludeFileList: A list of include files\r
205 #\r
206 def GetAllIncludeFiles(Db):\r
207     IncludeList = GetAllIncludeDirs(Db)\r
208     IncludeFileList = []\r
209 \r
210     for Dir in IncludeList:\r
211         if os.path.isdir(Dir):\r
212             SubDir = os.listdir(Dir)\r
213             for Item in SubDir:\r
214                 if os.path.isfile(Item):\r
215                     IncludeFileList.append(Item)\r
216 \r
217     return IncludeFileList\r
218 \r
219 ## GetAllSourceFiles() method\r
220 #\r
221 #  Find all source files\r
222 #\r
223 #  @param  Db: Eot database\r
224 #\r
225 #  @return SourceFileList: A list of source files\r
226 #\r
227 def GetAllSourceFiles(Db):\r
228     SourceFileList = []\r
229     SqlCommand = """select distinct Value1 from Inf where Model = %s order by Value1""" % MODEL_EFI_SOURCE_FILE\r
230     RecordSet = Db.TblInf.Exec(SqlCommand)\r
231 \r
232     for Record in RecordSet:\r
233         SourceFileList.append(Record[0])\r
234 \r
235     return SourceFileList\r
236 \r
237 ## GetAllFiles() method\r
238 #\r
239 #  Find all files, both source files and include files\r
240 #\r
241 #  @param  Db: Eot database\r
242 #\r
243 #  @return FileList: A list of files\r
244 #\r
245 def GetAllFiles(Db):\r
246     FileList = []\r
247     IncludeFileList = GetAllIncludeFiles(Db)\r
248     SourceFileList = GetAllSourceFiles(Db)\r
249     for Item in IncludeFileList:\r
250         if os.path.isfile(Item) and Item not in FileList:\r
251             FileList.append(Item)\r
252     for Item in SourceFileList:\r
253         if os.path.isfile(Item) and Item not in FileList:\r
254             FileList.append(Item)\r
255 \r
256     return FileList\r
257 \r
258 ## ParseConditionalStatement() method\r
259 #\r
260 #  Parse conditional statement\r
261 #\r
262 #  @param Line: One line to be parsed\r
263 #  @param Macros: A set of all macro\r
264 #  @param StatusSet: A set of all status\r
265 #\r
266 #  @retval True: Find keyword of conditional statement\r
267 #  @retval False: Not find keyword of conditional statement\r
268 #\r
269 def ParseConditionalStatement(Line, Macros, StatusSet):\r
270     NewLine = Line.upper()\r
271     if NewLine.find(TAB_IF_EXIST.upper()) > -1:\r
272         IfLine = Line[NewLine.find(TAB_IF_EXIST) + len(TAB_IF_EXIST) + 1:].strip()\r
273         IfLine = ReplaceMacro(IfLine, EotGlobalData.gMACRO, True)\r
274         IfLine = ReplaceMacro(IfLine, Macros, True)\r
275         IfLine = IfLine.replace("\"", '')\r
276         IfLine = IfLine.replace("(", '')\r
277         IfLine = IfLine.replace(")", '')\r
278         Status = os.path.exists(os.path.normpath(IfLine))\r
279         StatusSet.append([Status])\r
280         return True\r
281     if NewLine.find(TAB_IF_DEF.upper()) > -1:\r
282         IfLine = Line[NewLine.find(TAB_IF_DEF) + len(TAB_IF_DEF) + 1:].strip()\r
283         Status = False\r
284         if IfLine in Macros or IfLine in EotGlobalData.gMACRO:\r
285             Status = True\r
286         StatusSet.append([Status])\r
287         return True\r
288     if NewLine.find(TAB_IF_N_DEF.upper()) > -1:\r
289         IfLine = Line[NewLine.find(TAB_IF_N_DEF) + len(TAB_IF_N_DEF) + 1:].strip()\r
290         Status = False\r
291         if IfLine not in Macros and IfLine not in EotGlobalData.gMACRO:\r
292             Status = True\r
293         StatusSet.append([Status])\r
294         return True\r
295     if NewLine.find(TAB_IF.upper()) > -1:\r
296         IfLine = Line[NewLine.find(TAB_IF) + len(TAB_IF) + 1:].strip()\r
297         Status = ParseConditionalStatementMacros(IfLine, Macros)\r
298         StatusSet.append([Status])\r
299         return True\r
300     if NewLine.find(TAB_ELSE_IF.upper()) > -1:\r
301         IfLine = Line[NewLine.find(TAB_ELSE_IF) + len(TAB_ELSE_IF) + 1:].strip()\r
302         Status = ParseConditionalStatementMacros(IfLine, Macros)\r
303         StatusSet[-1].append(Status)\r
304         return True\r
305     if NewLine.find(TAB_ELSE.upper()) > -1:\r
306         Status = False\r
307         for Item in StatusSet[-1]:\r
308             Status = Status or Item\r
309         StatusSet[-1].append(not Status)\r
310         return True\r
311     if NewLine.find(TAB_END_IF.upper()) > -1:\r
312         StatusSet.pop()\r
313         return True\r
314 \r
315     return False\r
316 \r
317 ## ParseConditionalStatement() method\r
318 #\r
319 #  Parse conditional statement with Macros\r
320 #\r
321 #  @param Line: One line to be parsed\r
322 #  @param Macros: A set of macros\r
323 #\r
324 #  @return Line: New line after replacing macros\r
325 #\r
326 def ParseConditionalStatementMacros(Line, Macros):\r
327     if Line.upper().find('DEFINED(') > -1 or Line.upper().find('EXIST') > -1:\r
328         return False\r
329     Line = ReplaceMacro(Line, EotGlobalData.gMACRO, True)\r
330     Line = ReplaceMacro(Line, Macros, True)\r
331     Line = Line.replace("&&", "and")\r
332     Line = Line.replace("||", "or")\r
333     return eval(Line)\r
334 \r
335 ## GetConditionalStatementStatus() method\r
336 #\r
337 #  1. Assume the latest status as True\r
338 #  2. Pop the top status of status set, previous status\r
339 #  3. Compare the latest one and the previous one and get new status\r
340 #\r
341 #  @param StatusSet: A set of all status\r
342 #\r
343 #  @return Status: The final status\r
344 #\r
345 def GetConditionalStatementStatus(StatusSet):\r
346     Status = True\r
347     for Item in StatusSet:\r
348         Status = Status and Item[-1]\r
349 \r
350     return Status\r
351 \r
352 ## SearchBelongsToFunction() method\r
353 #\r
354 #  Search all functions belong to the file\r
355 #\r
356 #  @param BelongsToFile: File id\r
357 #  @param StartLine: Start line of search scope\r
358 #  @param EndLine: End line of search scope\r
359 #\r
360 #  @return: The found function\r
361 #\r
362 def SearchBelongsToFunction(BelongsToFile, StartLine, EndLine):\r
363     SqlCommand = """select ID, Name from Function where BelongsToFile = %s and StartLine <= %s and EndLine >= %s""" %(BelongsToFile, StartLine, EndLine)\r
364     RecordSet = EotGlobalData.gDb.TblFunction.Exec(SqlCommand)\r
365     if RecordSet != []:\r
366         return RecordSet[0][0], RecordSet[0][1]\r
367     else:\r
368         return -1, ''\r
369 \r
370 ## SearchPpiCallFunction() method\r
371 #\r
372 #  Search all used PPI calling function 'PeiServicesReInstallPpi' and 'PeiServicesInstallPpi'\r
373 #  Store the result to database\r
374 #\r
375 #  @param Identifier: Table id\r
376 #  @param SourceFileID: Source file id\r
377 #  @param SourceFileFullPath: Source file full path\r
378 #  @param ItemMode: Mode of the item\r
379 #\r
380 def SearchPpiCallFunction(Identifier, SourceFileID, SourceFileFullPath, ItemMode):\r
381     ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Ppi', '', '', ''\r
382     SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s\r
383                     where (Name like '%%%s%%' and Model = %s)""" \\r
384                     % (Identifier, 'PeiServicesReInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)\r
385     BelongsToFunctionID, BelongsToFunction = -1, ''\r
386     Db = EotGlobalData.gDb.TblReport\r
387     RecordSet = Db.Exec(SqlCommand)\r
388     for Record in RecordSet:\r
389         Index = 0\r
390         BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]\r
391         BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)\r
392         VariableList = Record[0].split(',')\r
393         for Variable in VariableList:\r
394             Variable = Variable.strip()\r
395             # Get index of the variable\r
396             if Variable.find('[') > -1:\r
397                 Index = int(Variable[Variable.find('[') + 1 : Variable.find(']')])\r
398                 Variable = Variable[:Variable.find('[')]\r
399             # Get variable name\r
400             if Variable.startswith('&'):\r
401                 Variable = Variable[1:]\r
402             # Get variable value\r
403             SqlCommand = """select Value from %s where (Name like '%%%s%%') and Model = %s""" \\r
404                          % (Identifier, Variable, MODEL_IDENTIFIER_VARIABLE)\r
405             NewRecordSet = Db.Exec(SqlCommand)\r
406             if NewRecordSet:\r
407                 NewRecord = NewRecordSet[0][0]\r
408                 VariableValueList = NewRecord.split('},')\r
409                 if len(VariableValueList) > Index:\r
410                     VariableValue = VariableValueList[Index]\r
411                     NewVariableValueList = VariableValue.split(',')\r
412                     if len(NewVariableValueList) > 1:\r
413                         NewVariableValue = NewVariableValueList[1].strip()\r
414                         if NewVariableValue.startswith('&'):\r
415                             Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, NewVariableValue[1:], GuidMacro, GuidValue, BelongsToFunction, 0)\r
416                             continue\r
417                         else:\r
418                             EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, NewParameter))\r
419 \r
420     ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Ppi', '', '', ''\r
421     SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s\r
422                     where (Value like '%%%s%%' and Model = %s)""" \\r
423                     % (Identifier, 'PeiServicesInstallPpi', MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION)\r
424     BelongsToFunctionID, BelongsToFunction = -1, ''\r
425     Db = EotGlobalData.gDb.TblReport\r
426     RecordSet = Db.Exec(SqlCommand)\r
427 \r
428     SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s\r
429                     where (Name like '%%%s%%' and Model = %s)""" \\r
430                     % (Identifier, 'PeiServicesInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)\r
431     Db = EotGlobalData.gDb.TblReport\r
432     RecordSet2 = Db.Exec(SqlCommand)\r
433 \r
434     for Record in RecordSet + RecordSet2:\r
435         if Record == []:\r
436             continue\r
437         Index = 0\r
438         BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]\r
439         BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)\r
440         Variable = Record[0].replace('PeiServicesInstallPpi', '').replace('(', '').replace(')', '').replace('&', '').strip()\r
441         Variable = Variable[Variable.find(',') + 1:].strip()\r
442         # Get index of the variable\r
443         if Variable.find('[') > -1:\r
444             Index = int(Variable[Variable.find('[') + 1 : Variable.find(']')])\r
445             Variable = Variable[:Variable.find('[')]\r
446         # Get variable name\r
447         if Variable.startswith('&'):\r
448             Variable = Variable[1:]\r
449         # Get variable value\r
450         SqlCommand = """select Value from %s where (Name like '%%%s%%') and Model = %s""" \\r
451                      % (Identifier, Variable, MODEL_IDENTIFIER_VARIABLE)\r
452         NewRecordSet = Db.Exec(SqlCommand)\r
453         if NewRecordSet:\r
454             NewRecord = NewRecordSet[0][0]\r
455             VariableValueList = NewRecord.split('},')\r
456             for VariableValue in VariableValueList[Index:]:\r
457                 NewVariableValueList = VariableValue.split(',')\r
458                 if len(NewVariableValueList) > 1:\r
459                     NewVariableValue = NewVariableValueList[1].strip()\r
460                     if NewVariableValue.startswith('&'):\r
461                         Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, NewVariableValue[1:], GuidMacro, GuidValue, BelongsToFunction, 0)\r
462                         continue\r
463                     else:\r
464                         EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, NewParameter))\r
465 \r
466 ## SearchPpis() method\r
467 #\r
468 #  Search all used PPI calling function\r
469 #  Store the result to database\r
470 #\r
471 #  @param SqlCommand: SQL command statement\r
472 #  @param Table: Table id\r
473 #  @param SourceFileID: Source file id\r
474 #  @param SourceFileFullPath: Source file full path\r
475 #  @param ItemMode: Mode of the item\r
476 #  @param PpiMode: Mode of PPI\r
477 #\r
478 def SearchPpi(SqlCommand, Table, SourceFileID, SourceFileFullPath, ItemMode, PpiMode = 1):\r
479     ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Ppi', '', '', ''\r
480     BelongsToFunctionID, BelongsToFunction = -1, ''\r
481     Db = EotGlobalData.gDb.TblReport\r
482     RecordSet = Db.Exec(SqlCommand)\r
483     for Record in RecordSet:\r
484         Parameter = GetPpiParameter(Record[0], PpiMode)\r
485         BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]\r
486         # Get BelongsToFunction\r
487         BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)\r
488 \r
489         # Default is Not Found\r
490         IsFound = False\r
491 \r
492         # For Consumed Ppi\r
493         if ItemMode == 'Consumed':\r
494             if Parameter.startswith('g'):\r
495                 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, Parameter, GuidMacro, GuidValue, BelongsToFunction, 0)\r
496             else:\r
497                 EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))\r
498             continue\r
499 \r
500         # Direct Parameter.Guid\r
501         SqlCommand = """select Value from %s where (Name like '%%%s.Guid%%' or Name like '%%%s->Guid%%') and Model = %s""" % (Table, Parameter, Parameter, MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION)\r
502         NewRecordSet = Db.Exec(SqlCommand)\r
503         for NewRecord in NewRecordSet:\r
504             GuidName = GetParameterName(NewRecord[0])\r
505             Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)\r
506             IsFound = True\r
507 \r
508         # Defined Parameter\r
509         if not IsFound:\r
510             Key = Parameter\r
511             if Key.rfind(' ') > -1:\r
512                 Key = Key[Key.rfind(' ') : ].strip().replace('&', '')\r
513             Value = FindKeyValue(EotGlobalData.gDb.TblFile, Table, Key)\r
514             List = GetSplitValueList(Value.replace('\n', ''), TAB_COMMA_SPLIT)\r
515             if len(List) > 1:\r
516                 GuidName = GetParameterName(List[1])\r
517                 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)\r
518                 IsFound = True\r
519 \r
520         # A list Parameter\r
521         if not IsFound:\r
522             Start = Parameter.find('[')\r
523             End = Parameter.find(']')\r
524             if Start > -1 and End > -1 and Start < End:\r
525                 try:\r
526                     Index = int(Parameter[Start + 1 : End])\r
527                     Parameter = Parameter[0 : Start]\r
528                     SqlCommand = """select Value from %s where Name = '%s' and Model = %s""" % (Table, Parameter, MODEL_IDENTIFIER_VARIABLE)\r
529                     NewRecordSet = Db.Exec(SqlCommand)\r
530                     for NewRecord in NewRecordSet:\r
531                         NewParameter = GetSplitValueList(NewRecord[0], '}')[Index]\r
532                         GuidName = GetPpiParameter(NewParameter[NewParameter.find('{') : ])\r
533                         Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)\r
534                         IsFound = True\r
535                 except Exception:\r
536                     pass\r
537 \r
538         # A External Parameter\r
539         if not IsFound:\r
540             SqlCommand = """select File.ID from Inf, File\r
541                             where BelongsToFile = (select BelongsToFile from Inf where Value1 = '%s')\r
542                             and Inf.Model = %s and Inf.Value1 = File.FullPath and File.Model = %s""" % (SourceFileFullPath, MODEL_EFI_SOURCE_FILE, MODEL_FILE_C)\r
543             NewRecordSet = Db.Exec(SqlCommand)\r
544             for NewRecord in NewRecordSet:\r
545                 Table = 'Identifier' + str(NewRecord[0])\r
546                 SqlCommand = """select Value from %s where Name = '%s' and Modifier = 'EFI_PEI_PPI_DESCRIPTOR' and Model = %s""" % (Table, Parameter, MODEL_IDENTIFIER_VARIABLE)\r
547                 PpiSet = Db.Exec(SqlCommand)\r
548                 if PpiSet != []:\r
549                     GuidName = GetPpiParameter(PpiSet[0][0])\r
550                     if GuidName != '':\r
551                         Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)\r
552                         IsFound = True\r
553                         break\r
554 \r
555         if not IsFound:\r
556             EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))\r
557 \r
558 ## SearchProtocols() method\r
559 #\r
560 #  Search all used PROTOCOL calling function\r
561 #  Store the result to database\r
562 #\r
563 #  @param SqlCommand: SQL command statement\r
564 #  @param Table: Table id\r
565 #  @param SourceFileID: Source file id\r
566 #  @param SourceFileFullPath: Source file full path\r
567 #  @param ItemMode: Mode of the item\r
568 #  @param ProtocolMode: Mode of PROTOCOL\r
569 #\r
570 def SearchProtocols(SqlCommand, Table, SourceFileID, SourceFileFullPath, ItemMode, ProtocolMode):\r
571     ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Protocol', '', '', ''\r
572     BelongsToFunctionID, BelongsToFunction = -1, ''\r
573     Db = EotGlobalData.gDb.TblReport\r
574     RecordSet = Db.Exec(SqlCommand)\r
575     for Record in RecordSet:\r
576         Parameter = ''\r
577         BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]\r
578         # Get BelongsToFunction\r
579         BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)\r
580 \r
581         # Default is Not Found\r
582         IsFound = False\r
583 \r
584         if ProtocolMode == 0 or ProtocolMode == 1:\r
585             Parameter = GetProtocolParameter(Record[0], ProtocolMode)\r
586             if Parameter.startswith('g') or Parameter.endswith('Guid') or Parameter == 'ShellEnvProtocol' or Parameter == 'ShellInterfaceProtocol':\r
587                 GuidName = GetParameterName(Parameter)\r
588                 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)\r
589                 IsFound = True\r
590 \r
591         if ProtocolMode == 2:\r
592             Protocols = GetSplitValueList(Record[0], TAB_COMMA_SPLIT)\r
593             for Protocol in Protocols:\r
594                 if Protocol.startswith('&') and Protocol.endswith('Guid'):\r
595                     GuidName = GetParameterName(Protocol)\r
596                     Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)\r
597                     IsFound = True\r
598                 else:\r
599                     NewValue = FindKeyValue(EotGlobalData.gDb.TblFile, Table, Protocol)\r
600                     if Protocol != NewValue and NewValue.endswith('Guid'):\r
601                         GuidName = GetParameterName(NewValue)\r
602                         Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)\r
603                         IsFound = True\r
604 \r
605         if not IsFound:\r
606             if BelongsToFunction in EotGlobalData.gProducedProtocolLibrary or BelongsToFunction in EotGlobalData.gConsumedProtocolLibrary:\r
607                 EotGlobalData.gOP_UN_MATCHED_IN_LIBRARY_CALLING.write('%s, %s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter, BelongsToFunction))\r
608             else:\r
609                 EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))\r
610 \r
611 ## SearchFunctionCalling() method\r
612 #\r
613 #  Search all used PPI/PROTOCOL calling function by library\r
614 #  Store the result to database\r
615 #\r
616 #  @param SqlCommand: SQL command statement\r
617 #  @param Table: Table id\r
618 #  @param SourceFileID: Source file id\r
619 #  @param SourceFileFullPath: Source file full path\r
620 #  @param ItemType: Type of the item, PPI or PROTOCOL\r
621 #  @param ItemMode: Mode of item\r
622 #\r
623 def SearchFunctionCalling(Table, SourceFileID, SourceFileFullPath, ItemType, ItemMode):\r
624     LibraryList = sdict()\r
625     Db = EotGlobalData.gDb.TblReport\r
626     Parameters, ItemName, GuidName, GuidMacro, GuidValue, BelongsToFunction = [], '', '', '', '', ''\r
627     if ItemType == 'Protocol' and ItemMode == 'Produced':\r
628         LibraryList = EotGlobalData.gProducedProtocolLibrary\r
629     elif ItemType == 'Protocol' and ItemMode == 'Consumed':\r
630         LibraryList = EotGlobalData.gConsumedProtocolLibrary\r
631     elif ItemType == 'Protocol' and ItemMode == 'Callback':\r
632         LibraryList = EotGlobalData.gCallbackProtocolLibrary\r
633     elif ItemType == 'Ppi' and ItemMode == 'Produced':\r
634         LibraryList = EotGlobalData.gProducedPpiLibrary\r
635     elif ItemType == 'Ppi' and ItemMode == 'Consumed':\r
636         LibraryList = EotGlobalData.gConsumedPpiLibrary\r
637 \r
638     for Library in LibraryList:\r
639         Index = LibraryList[Library]\r
640         SqlCommand = """select Value, StartLine from %s\r
641                         where Name like '%%%s%%' and Model = %s""" \\r
642                         % (Table, Library, MODEL_IDENTIFIER_FUNCTION_CALLING)\r
643         RecordSet = Db.Exec(SqlCommand)\r
644         for Record in RecordSet:\r
645             IsFound = False\r
646             if Index == -1:\r
647                 ParameterList = GetSplitValueList(Record[0], TAB_COMMA_SPLIT)\r
648                 for Parameter in ParameterList:\r
649                     Parameters.append(GetParameterName(Parameter))\r
650             else:\r
651                 Parameters = [GetProtocolParameter(Record[0], Index)]\r
652             StartLine = Record[1]\r
653             for Parameter in Parameters:\r
654                 if Parameter.startswith('g') or Parameter.endswith('Guid') or Parameter == 'ShellEnvProtocol' or Parameter == 'ShellInterfaceProtocol':\r
655                     GuidName = GetParameterName(Parameter)\r
656                     Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)\r
657                     IsFound = True\r
658 \r
659             if not IsFound:\r
660                 EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))\r
661 \r
662 ## FindProtocols() method\r
663 #\r
664 #  Find defined protocols\r
665 #\r
666 #  @param SqlCommand: SQL command statement\r
667 #  @param Table: Table id\r
668 #  @param SourceFileID: Source file id\r
669 #  @param SourceFileFullPath: Source file full path\r
670 #  @param ItemName: String of protocol definition\r
671 #  @param ItemType: Type of the item, PPI or PROTOCOL\r
672 #  @param ItemMode: Mode of item\r
673 #\r
674 #def FindProtocols(Db, SqlCommand, Table, SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue):\r
675 #    BelongsToFunction = ''\r
676 #    RecordSet = Db.Exec(SqlCommand)\r
677 #    for Record in RecordSet:\r
678 #        IsFound = True\r
679 #        Parameter = GetProtocolParameter(Record[0])\r
680 \r
681 ## GetProtocolParameter() method\r
682 #\r
683 # Parse string of protocol and find parameters\r
684 #\r
685 #  @param Parameter: Parameter to be parsed\r
686 #  @param Index: The index of the parameter\r
687 #\r
688 #  @return: call common GetParameter\r
689 #\r
690 def GetProtocolParameter(Parameter, Index = 1):\r
691     return GetParameter(Parameter, Index)\r
692 \r
693 ## GetPpiParameter() method\r
694 #\r
695 # Parse string of ppi and find parameters\r
696 #\r
697 #  @param Parameter: Parameter to be parsed\r
698 #  @param Index: The index of the parameter\r
699 #\r
700 #  @return: call common GetParameter\r
701 #\r
702 def GetPpiParameter(Parameter, Index = 1):\r
703     return GetParameter(Parameter, Index)\r
704 \r
705 ## GetParameter() method\r
706 #\r
707 # Get a parameter by index\r
708 #\r
709 #  @param Parameter: Parameter to be parsed\r
710 #  @param Index: The index of the parameter\r
711 #\r
712 #  @return Parameter: The found parameter\r
713 #\r
714 def GetParameter(Parameter, Index = 1):\r
715     ParameterList = GetSplitValueList(Parameter, TAB_COMMA_SPLIT)\r
716     if len(ParameterList) > Index:\r
717         Parameter = GetParameterName(ParameterList[Index])\r
718 \r
719         return Parameter\r
720 \r
721     return ''\r
722 \r
723 ## GetParameterName() method\r
724 #\r
725 # Get a parameter name\r
726 #\r
727 #  @param Parameter: Parameter to be parsed\r
728 #\r
729 #  @return: The name of parameter\r
730 #\r
731 def GetParameterName(Parameter):\r
732     if type(Parameter) == type('') and Parameter.startswith('&'):\r
733         return Parameter[1:].replace('{', '').replace('}', '').replace('\r', '').replace('\n', '').strip()\r
734     else:\r
735         return Parameter.strip()\r
736 \r
737 ## FindKeyValue() method\r
738 #\r
739 # Find key value of a variable\r
740 #\r
741 #  @param Db: Database to be searched\r
742 #  @param Table: Table to be searched\r
743 #  @param Key: The keyword\r
744 #\r
745 #  @return Value: The value of the the keyword\r
746 #\r
747 def FindKeyValue(Db, Table, Key):\r
748     SqlCommand = """select Value from %s where Name = '%s' and (Model = %s or Model = %s)""" % (Table, Key, MODEL_IDENTIFIER_VARIABLE, MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION)\r
749     RecordSet = Db.Exec(SqlCommand)\r
750     Value = ''\r
751     for Record in RecordSet:\r
752         if Record[0] != 'NULL':\r
753             Value = FindKeyValue(Db, Table, GetParameterName(Record[0]))\r
754 \r
755     if Value != '':\r
756         return Value\r
757     else:\r
758         return Key\r
759 \r
760 ## ParseMapFile() method\r
761 #\r
762 #  Parse map files to get a dict of 'ModuleName' : {FunName : FunAddress}\r
763 #\r
764 #  @param Files: A list of map files\r
765 #\r
766 #  @return AllMaps: An object of all map files\r
767 #\r
768 def ParseMapFile(Files):\r
769     AllMaps = {}\r
770     CurrentModule = ''\r
771     CurrentMaps = {}\r
772     for File in Files:\r
773         Content = open(File, 'r').readlines()\r
774         for Line in Content:\r
775             Line = CleanString(Line)\r
776             # skip empty line\r
777             if Line == '':\r
778                 continue\r
779 \r
780             if Line.find('(') > -1 and Line.find(')') > -1:\r
781                 if CurrentModule != '' and CurrentMaps != {}:\r
782                     AllMaps[CurrentModule] = CurrentMaps\r
783                 CurrentModule = Line[:Line.find('(')]\r
784                 CurrentMaps = {}\r
785                 continue\r
786             else:\r
787                 Name = ''\r
788                 Address = ''\r
789                 List = Line.split()\r
790                 Address = List[0]\r
791                 if List[1] == 'F' or List[1] == 'FS':\r
792                     Name = List[2]\r
793                 else:\r
794                     Name = List[1]\r
795                 CurrentMaps[Name] = Address\r
796                 continue\r
797 \r
798     return AllMaps\r
799 \r
800 ## ConvertGuid\r
801 #\r
802 #  Convert a GUID to a GUID with all upper letters\r
803 #\r
804 #  @param guid:  The GUID to be converted\r
805 #\r
806 #  @param newGuid: The GUID with all upper letters.\r
807 #\r
808 def ConvertGuid(guid):\r
809     numList = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']\r
810     newGuid = ''\r
811     if guid.startswith('g'):\r
812         guid = guid[1:]\r
813     for i in guid:\r
814         if i.upper() == i and i not in numList:\r
815             newGuid = newGuid + ('_' + i)\r
816         else:\r
817             newGuid = newGuid + i.upper()\r
818     if newGuid.startswith('_'):\r
819         newGuid = newGuid[1:]\r
820     if newGuid.endswith('_'):\r
821         newGuid = newGuid[:-1]\r
822 \r
823     return newGuid\r
824 \r
825 ## ConvertGuid2() method\r
826 #\r
827 #  Convert a GUID to a GUID with new string instead of old string\r
828 #\r
829 #  @param guid: The GUID to be converted\r
830 #  @param old: Old string to be replaced\r
831 #  @param new: New string to replace the old one\r
832 #\r
833 #  @param newGuid: The GUID after replacement\r
834 #\r
835 def ConvertGuid2(guid, old, new):\r
836     newGuid = ConvertGuid(guid)\r
837     newGuid = newGuid.replace(old, new)\r
838 \r
839     return newGuid\r
840 \r
841 ##\r
842 #\r
843 # This acts like the main() function for the script, unless it is 'import'ed into another\r
844 # script.\r
845 #\r
846 if __name__ == '__main__':\r
847     pass\r