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