mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-26 16:47:40 +01:00
870 lines
33 KiB
Python
870 lines
33 KiB
Python
|
## @file
|
||
|
# This file is used to define common parsing related functions used in parsing
|
||
|
# Inf/Dsc/Makefile process
|
||
|
#
|
||
|
# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
|
||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
#
|
||
|
|
||
|
##
|
||
|
# Import Modules
|
||
|
#
|
||
|
from __future__ import absolute_import
|
||
|
import Common.LongFilePathOs as os, re
|
||
|
import Common.EdkLogger as EdkLogger
|
||
|
from Common.DataType import *
|
||
|
from CommonDataClass.DataClass import *
|
||
|
from Common.StringUtils import CleanString, GetSplitValueList, ReplaceMacro
|
||
|
from . import EotGlobalData
|
||
|
from Common.StringUtils import GetSplitList
|
||
|
from Common.LongFilePathSupport import OpenLongFilePath as open
|
||
|
|
||
|
import subprocess
|
||
|
|
||
|
## DeCompress
|
||
|
#
|
||
|
# Call external decompress tool to decompress the fv section
|
||
|
#
|
||
|
def DeCompress(Method, Input):
|
||
|
# Write the input to a temp file
|
||
|
open('_Temp.bin', 'wb').write(Input)
|
||
|
cmd = ''
|
||
|
if Method == 'Lzma':
|
||
|
cmd = r'LzmaCompress -o _New.bin -d _Temp.bin'
|
||
|
if Method == 'Efi':
|
||
|
cmd = r'TianoCompress -d --uefi -o _New.bin _Temp.bin'
|
||
|
if Method == 'Framework':
|
||
|
cmd = r'TianoCompress -d -o _New.bin _Temp.bin'
|
||
|
|
||
|
# Call tool to create the decompressed output file
|
||
|
Process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||
|
Process.communicate()[0]
|
||
|
|
||
|
# Return the beffer of New.bin
|
||
|
if os.path.exists('_New.bin'):
|
||
|
return open('_New.bin', 'rb').read()
|
||
|
|
||
|
|
||
|
## PreProcess() method
|
||
|
#
|
||
|
# Pre process a file
|
||
|
#
|
||
|
# 1. Remove all comments
|
||
|
# 2. Merge multiple lines code to one line
|
||
|
#
|
||
|
# @param Filename: Name of the file to be parsed
|
||
|
# @param MergeMultipleLines: Switch for if merge multiple lines
|
||
|
# @param LineNo: Default line no
|
||
|
#
|
||
|
# @return Lines: The file contents after removing comments
|
||
|
#
|
||
|
def PreProcess(Filename, MergeMultipleLines = True, LineNo = -1):
|
||
|
Lines = []
|
||
|
Filename = os.path.normpath(Filename)
|
||
|
if not os.path.isfile(Filename):
|
||
|
EdkLogger.error("Eot", EdkLogger.FILE_NOT_FOUND, ExtraData=Filename)
|
||
|
|
||
|
IsFindBlockComment = False
|
||
|
IsFindBlockCode = False
|
||
|
ReservedLine = ''
|
||
|
ReservedLineLength = 0
|
||
|
for Line in open(Filename, 'r'):
|
||
|
Line = Line.strip()
|
||
|
# Remove comment block
|
||
|
if Line.find(TAB_COMMENT_EDK_START) > -1:
|
||
|
ReservedLine = GetSplitList(Line, TAB_COMMENT_EDK_START, 1)[0]
|
||
|
IsFindBlockComment = True
|
||
|
if Line.find(TAB_COMMENT_EDK_END) > -1:
|
||
|
Line = ReservedLine + GetSplitList(Line, TAB_COMMENT_EDK_END, 1)[1]
|
||
|
ReservedLine = ''
|
||
|
IsFindBlockComment = False
|
||
|
if IsFindBlockComment:
|
||
|
Lines.append('')
|
||
|
continue
|
||
|
|
||
|
# Remove comments at tail and remove spaces again
|
||
|
Line = CleanString(Line)
|
||
|
if Line == '':
|
||
|
Lines.append('')
|
||
|
continue
|
||
|
|
||
|
if MergeMultipleLines:
|
||
|
# Add multiple lines to one line
|
||
|
if IsFindBlockCode and Line[-1] != TAB_SLASH:
|
||
|
ReservedLine = (ReservedLine + TAB_SPACE_SPLIT + Line).strip()
|
||
|
Lines.append(ReservedLine)
|
||
|
for Index in (0, ReservedLineLength):
|
||
|
Lines.append('')
|
||
|
ReservedLine = ''
|
||
|
ReservedLineLength = 0
|
||
|
IsFindBlockCode = False
|
||
|
continue
|
||
|
if Line[-1] == TAB_SLASH:
|
||
|
ReservedLine = ReservedLine + TAB_SPACE_SPLIT + Line[0:-1].strip()
|
||
|
ReservedLineLength = ReservedLineLength + 1
|
||
|
IsFindBlockCode = True
|
||
|
continue
|
||
|
|
||
|
Lines.append(Line)
|
||
|
|
||
|
return Lines
|
||
|
|
||
|
## AddToGlobalMacro() method
|
||
|
#
|
||
|
# Add a macro to EotGlobalData.gMACRO
|
||
|
#
|
||
|
# @param Name: Name of the macro
|
||
|
# @param Value: Value of the macro
|
||
|
#
|
||
|
def AddToGlobalMacro(Name, Value):
|
||
|
Value = ReplaceMacro(Value, EotGlobalData.gMACRO, True)
|
||
|
EotGlobalData.gMACRO[Name] = Value
|
||
|
|
||
|
## AddToSelfMacro() method
|
||
|
#
|
||
|
# Parse a line of macro definition and add it to a macro set
|
||
|
#
|
||
|
# @param SelfMacro: The self macro set
|
||
|
# @param Line: The line of a macro definition
|
||
|
#
|
||
|
# @return Name: Name of macro
|
||
|
# @return Value: Value of macro
|
||
|
#
|
||
|
def AddToSelfMacro(SelfMacro, Line):
|
||
|
Name, Value = '', ''
|
||
|
List = GetSplitValueList(Line, TAB_EQUAL_SPLIT, 1)
|
||
|
if len(List) == 2:
|
||
|
Name = List[0]
|
||
|
Value = List[1]
|
||
|
Value = ReplaceMacro(Value, EotGlobalData.gMACRO, True)
|
||
|
Value = ReplaceMacro(Value, SelfMacro, True)
|
||
|
SelfMacro[Name] = Value
|
||
|
|
||
|
return (Name, Value)
|
||
|
|
||
|
## GetIncludeListOfFile() method
|
||
|
#
|
||
|
# Get the include path list for a source file
|
||
|
#
|
||
|
# 1. Find the source file belongs to which INF file
|
||
|
# 2. Find the inf's package
|
||
|
# 3. Return the include path list of the package
|
||
|
#
|
||
|
# @param WorkSpace: WORKSPACE path
|
||
|
# @param Filepath: File path
|
||
|
# @param Db: Eot database
|
||
|
#
|
||
|
# @return IncludeList: A list of include directories
|
||
|
#
|
||
|
def GetIncludeListOfFile(WorkSpace, Filepath, Db):
|
||
|
IncludeList = []
|
||
|
Filepath = os.path.normpath(Filepath)
|
||
|
SqlCommand = """
|
||
|
select Value1 from Inf where Model = %s and BelongsToFile in(
|
||
|
select distinct B.BelongsToFile from File as A left join Inf as B
|
||
|
where A.ID = B.BelongsToFile and B.Model = %s and (A.Path || '%s' || B.Value1) = '%s')""" \
|
||
|
% (MODEL_META_DATA_PACKAGE, MODEL_EFI_SOURCE_FILE, '\\', Filepath)
|
||
|
RecordSet = Db.TblFile.Exec(SqlCommand)
|
||
|
for Record in RecordSet:
|
||
|
DecFullPath = os.path.normpath(os.path.join(WorkSpace, Record[0]))
|
||
|
(DecPath, DecName) = os.path.split(DecFullPath)
|
||
|
SqlCommand = """select Value1 from Dec where BelongsToFile =
|
||
|
(select ID from File where FullPath = '%s') and Model = %s""" \
|
||
|
% (DecFullPath, MODEL_EFI_INCLUDE)
|
||
|
NewRecordSet = Db.TblDec.Exec(SqlCommand)
|
||
|
for NewRecord in NewRecordSet:
|
||
|
IncludePath = os.path.normpath(os.path.join(DecPath, NewRecord[0]))
|
||
|
if IncludePath not in IncludeList:
|
||
|
IncludeList.append(IncludePath)
|
||
|
|
||
|
return IncludeList
|
||
|
|
||
|
## GetTableList() method
|
||
|
#
|
||
|
# Search table file and find all small tables
|
||
|
#
|
||
|
# @param FileModelList: Model code for the file list
|
||
|
# @param Table: Table to insert records
|
||
|
# @param Db: Eot database
|
||
|
#
|
||
|
# @return TableList: A list of tables
|
||
|
#
|
||
|
def GetTableList(FileModelList, Table, Db):
|
||
|
TableList = []
|
||
|
SqlCommand = """select ID, FullPath from File where Model in %s""" % str(FileModelList)
|
||
|
RecordSet = Db.TblFile.Exec(SqlCommand)
|
||
|
for Record in RecordSet:
|
||
|
TableName = Table + str(Record[0])
|
||
|
TableList.append([TableName, Record[1]])
|
||
|
|
||
|
return TableList
|
||
|
|
||
|
## GetAllIncludeDir() method
|
||
|
#
|
||
|
# Find all Include directories
|
||
|
#
|
||
|
# @param Db: Eot database
|
||
|
#
|
||
|
# @return IncludeList: A list of include directories
|
||
|
#
|
||
|
def GetAllIncludeDirs(Db):
|
||
|
IncludeList = []
|
||
|
SqlCommand = """select distinct Value1 from Inf where Model = %s order by Value1""" % MODEL_EFI_INCLUDE
|
||
|
RecordSet = Db.TblInf.Exec(SqlCommand)
|
||
|
|
||
|
for Record in RecordSet:
|
||
|
IncludeList.append(Record[0])
|
||
|
|
||
|
return IncludeList
|
||
|
|
||
|
## GetAllIncludeFiles() method
|
||
|
#
|
||
|
# Find all Include files
|
||
|
#
|
||
|
# @param Db: Eot database
|
||
|
#
|
||
|
# @return IncludeFileList: A list of include files
|
||
|
#
|
||
|
def GetAllIncludeFiles(Db):
|
||
|
IncludeList = GetAllIncludeDirs(Db)
|
||
|
IncludeFileList = []
|
||
|
|
||
|
for Dir in IncludeList:
|
||
|
if os.path.isdir(Dir):
|
||
|
SubDir = os.listdir(Dir)
|
||
|
for Item in SubDir:
|
||
|
if os.path.isfile(Item):
|
||
|
IncludeFileList.append(Item)
|
||
|
|
||
|
return IncludeFileList
|
||
|
|
||
|
## GetAllSourceFiles() method
|
||
|
#
|
||
|
# Find all source files
|
||
|
#
|
||
|
# @param Db: Eot database
|
||
|
#
|
||
|
# @return SourceFileList: A list of source files
|
||
|
#
|
||
|
def GetAllSourceFiles(Db):
|
||
|
SourceFileList = []
|
||
|
SqlCommand = """select distinct Value1 from Inf where Model = %s order by Value1""" % MODEL_EFI_SOURCE_FILE
|
||
|
RecordSet = Db.TblInf.Exec(SqlCommand)
|
||
|
|
||
|
for Record in RecordSet:
|
||
|
SourceFileList.append(Record[0])
|
||
|
|
||
|
return SourceFileList
|
||
|
|
||
|
## GetAllFiles() method
|
||
|
#
|
||
|
# Find all files, both source files and include files
|
||
|
#
|
||
|
# @param Db: Eot database
|
||
|
#
|
||
|
# @return FileList: A list of files
|
||
|
#
|
||
|
def GetAllFiles(Db):
|
||
|
FileList = []
|
||
|
IncludeFileList = GetAllIncludeFiles(Db)
|
||
|
SourceFileList = GetAllSourceFiles(Db)
|
||
|
for Item in IncludeFileList:
|
||
|
if os.path.isfile(Item) and Item not in FileList:
|
||
|
FileList.append(Item)
|
||
|
for Item in SourceFileList:
|
||
|
if os.path.isfile(Item) and Item not in FileList:
|
||
|
FileList.append(Item)
|
||
|
|
||
|
return FileList
|
||
|
|
||
|
## ParseConditionalStatement() method
|
||
|
#
|
||
|
# Parse conditional statement
|
||
|
#
|
||
|
# @param Line: One line to be parsed
|
||
|
# @param Macros: A set of all macro
|
||
|
# @param StatusSet: A set of all status
|
||
|
#
|
||
|
# @retval True: Find keyword of conditional statement
|
||
|
# @retval False: Not find keyword of conditional statement
|
||
|
#
|
||
|
def ParseConditionalStatement(Line, Macros, StatusSet):
|
||
|
NewLine = Line.upper()
|
||
|
if NewLine.find(TAB_IF_EXIST.upper()) > -1:
|
||
|
IfLine = Line[NewLine.find(TAB_IF_EXIST) + len(TAB_IF_EXIST) + 1:].strip()
|
||
|
IfLine = ReplaceMacro(IfLine, EotGlobalData.gMACRO, True)
|
||
|
IfLine = ReplaceMacro(IfLine, Macros, True)
|
||
|
IfLine = IfLine.replace("\"", '')
|
||
|
IfLine = IfLine.replace("(", '')
|
||
|
IfLine = IfLine.replace(")", '')
|
||
|
Status = os.path.exists(os.path.normpath(IfLine))
|
||
|
StatusSet.append([Status])
|
||
|
return True
|
||
|
if NewLine.find(TAB_IF_DEF.upper()) > -1:
|
||
|
IfLine = Line[NewLine.find(TAB_IF_DEF) + len(TAB_IF_DEF) + 1:].strip()
|
||
|
Status = False
|
||
|
if IfLine in Macros or IfLine in EotGlobalData.gMACRO:
|
||
|
Status = True
|
||
|
StatusSet.append([Status])
|
||
|
return True
|
||
|
if NewLine.find(TAB_IF_N_DEF.upper()) > -1:
|
||
|
IfLine = Line[NewLine.find(TAB_IF_N_DEF) + len(TAB_IF_N_DEF) + 1:].strip()
|
||
|
Status = False
|
||
|
if IfLine not in Macros and IfLine not in EotGlobalData.gMACRO:
|
||
|
Status = True
|
||
|
StatusSet.append([Status])
|
||
|
return True
|
||
|
if NewLine.find(TAB_IF.upper()) > -1:
|
||
|
IfLine = Line[NewLine.find(TAB_IF) + len(TAB_IF) + 1:].strip()
|
||
|
Status = ParseConditionalStatementMacros(IfLine, Macros)
|
||
|
StatusSet.append([Status])
|
||
|
return True
|
||
|
if NewLine.find(TAB_ELSE_IF.upper()) > -1:
|
||
|
IfLine = Line[NewLine.find(TAB_ELSE_IF) + len(TAB_ELSE_IF) + 1:].strip()
|
||
|
Status = ParseConditionalStatementMacros(IfLine, Macros)
|
||
|
StatusSet[-1].append(Status)
|
||
|
return True
|
||
|
if NewLine.find(TAB_ELSE.upper()) > -1:
|
||
|
Status = False
|
||
|
for Item in StatusSet[-1]:
|
||
|
Status = Status or Item
|
||
|
StatusSet[-1].append(not Status)
|
||
|
return True
|
||
|
if NewLine.find(TAB_END_IF.upper()) > -1:
|
||
|
StatusSet.pop()
|
||
|
return True
|
||
|
|
||
|
return False
|
||
|
|
||
|
## ParseConditionalStatement() method
|
||
|
#
|
||
|
# Parse conditional statement with Macros
|
||
|
#
|
||
|
# @param Line: One line to be parsed
|
||
|
# @param Macros: A set of macros
|
||
|
#
|
||
|
# @return Line: New line after replacing macros
|
||
|
#
|
||
|
def ParseConditionalStatementMacros(Line, Macros):
|
||
|
if Line.upper().find('DEFINED(') > -1 or Line.upper().find('EXIST') > -1:
|
||
|
return False
|
||
|
Line = ReplaceMacro(Line, EotGlobalData.gMACRO, True)
|
||
|
Line = ReplaceMacro(Line, Macros, True)
|
||
|
Line = Line.replace("&&", "and")
|
||
|
Line = Line.replace("||", "or")
|
||
|
return eval(Line)
|
||
|
|
||
|
## GetConditionalStatementStatus() method
|
||
|
#
|
||
|
# 1. Assume the latest status as True
|
||
|
# 2. Pop the top status of status set, previous status
|
||
|
# 3. Compare the latest one and the previous one and get new status
|
||
|
#
|
||
|
# @param StatusSet: A set of all status
|
||
|
#
|
||
|
# @return Status: The final status
|
||
|
#
|
||
|
def GetConditionalStatementStatus(StatusSet):
|
||
|
Status = True
|
||
|
for Item in StatusSet:
|
||
|
Status = Status and Item[-1]
|
||
|
|
||
|
return Status
|
||
|
|
||
|
## SearchBelongsToFunction() method
|
||
|
#
|
||
|
# Search all functions belong to the file
|
||
|
#
|
||
|
# @param BelongsToFile: File id
|
||
|
# @param StartLine: Start line of search scope
|
||
|
# @param EndLine: End line of search scope
|
||
|
#
|
||
|
# @return: The found function
|
||
|
#
|
||
|
def SearchBelongsToFunction(BelongsToFile, StartLine, EndLine):
|
||
|
SqlCommand = """select ID, Name from Function where BelongsToFile = %s and StartLine <= %s and EndLine >= %s""" %(BelongsToFile, StartLine, EndLine)
|
||
|
RecordSet = EotGlobalData.gDb.TblFunction.Exec(SqlCommand)
|
||
|
if RecordSet != []:
|
||
|
return RecordSet[0][0], RecordSet[0][1]
|
||
|
else:
|
||
|
return -1, ''
|
||
|
|
||
|
## SearchPpiCallFunction() method
|
||
|
#
|
||
|
# Search all used PPI calling function 'PeiServicesReInstallPpi' and 'PeiServicesInstallPpi'
|
||
|
# Store the result to database
|
||
|
#
|
||
|
# @param Identifier: Table id
|
||
|
# @param SourceFileID: Source file id
|
||
|
# @param SourceFileFullPath: Source file full path
|
||
|
# @param ItemMode: Mode of the item
|
||
|
#
|
||
|
def SearchPpiCallFunction(Identifier, SourceFileID, SourceFileFullPath, ItemMode):
|
||
|
ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Ppi', '', '', ''
|
||
|
SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
|
||
|
where (Name like '%%%s%%' and Model = %s)""" \
|
||
|
% (Identifier, 'PeiServicesReInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
|
||
|
BelongsToFunctionID, BelongsToFunction = -1, ''
|
||
|
Db = EotGlobalData.gDb.TblReport
|
||
|
RecordSet = Db.Exec(SqlCommand)
|
||
|
for Record in RecordSet:
|
||
|
Index = 0
|
||
|
BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]
|
||
|
BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)
|
||
|
VariableList = Record[0].split(',')
|
||
|
for Variable in VariableList:
|
||
|
Variable = Variable.strip()
|
||
|
# Get index of the variable
|
||
|
if Variable.find('[') > -1:
|
||
|
Index = int(Variable[Variable.find('[') + 1 : Variable.find(']')])
|
||
|
Variable = Variable[:Variable.find('[')]
|
||
|
# Get variable name
|
||
|
if Variable.startswith('&'):
|
||
|
Variable = Variable[1:]
|
||
|
# Get variable value
|
||
|
SqlCommand = """select Value from %s where (Name like '%%%s%%') and Model = %s""" \
|
||
|
% (Identifier, Variable, MODEL_IDENTIFIER_VARIABLE)
|
||
|
NewRecordSet = Db.Exec(SqlCommand)
|
||
|
if NewRecordSet:
|
||
|
NewRecord = NewRecordSet[0][0]
|
||
|
VariableValueList = NewRecord.split('},')
|
||
|
if len(VariableValueList) > Index:
|
||
|
VariableValue = VariableValueList[Index]
|
||
|
NewVariableValueList = VariableValue.split(',')
|
||
|
if len(NewVariableValueList) > 1:
|
||
|
NewVariableValue = NewVariableValueList[1].strip()
|
||
|
if NewVariableValue.startswith('&'):
|
||
|
Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, NewVariableValue[1:], GuidMacro, GuidValue, BelongsToFunction, 0)
|
||
|
continue
|
||
|
else:
|
||
|
EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, NewParameter))
|
||
|
|
||
|
ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Ppi', '', '', ''
|
||
|
SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
|
||
|
where (Value like '%%%s%%' and Model = %s)""" \
|
||
|
% (Identifier, 'PeiServicesInstallPpi', MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION)
|
||
|
BelongsToFunctionID, BelongsToFunction = -1, ''
|
||
|
Db = EotGlobalData.gDb.TblReport
|
||
|
RecordSet = Db.Exec(SqlCommand)
|
||
|
|
||
|
SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
|
||
|
where (Name like '%%%s%%' and Model = %s)""" \
|
||
|
% (Identifier, 'PeiServicesInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
|
||
|
Db = EotGlobalData.gDb.TblReport
|
||
|
RecordSet2 = Db.Exec(SqlCommand)
|
||
|
|
||
|
for Record in RecordSet + RecordSet2:
|
||
|
if Record == []:
|
||
|
continue
|
||
|
Index = 0
|
||
|
BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]
|
||
|
BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)
|
||
|
Variable = Record[0].replace('PeiServicesInstallPpi', '').replace('(', '').replace(')', '').replace('&', '').strip()
|
||
|
Variable = Variable[Variable.find(',') + 1:].strip()
|
||
|
# Get index of the variable
|
||
|
if Variable.find('[') > -1:
|
||
|
Index = int(Variable[Variable.find('[') + 1 : Variable.find(']')])
|
||
|
Variable = Variable[:Variable.find('[')]
|
||
|
# Get variable name
|
||
|
if Variable.startswith('&'):
|
||
|
Variable = Variable[1:]
|
||
|
# Get variable value
|
||
|
SqlCommand = """select Value from %s where (Name like '%%%s%%') and Model = %s""" \
|
||
|
% (Identifier, Variable, MODEL_IDENTIFIER_VARIABLE)
|
||
|
NewRecordSet = Db.Exec(SqlCommand)
|
||
|
if NewRecordSet:
|
||
|
NewRecord = NewRecordSet[0][0]
|
||
|
VariableValueList = NewRecord.split('},')
|
||
|
for VariableValue in VariableValueList[Index:]:
|
||
|
NewVariableValueList = VariableValue.split(',')
|
||
|
if len(NewVariableValueList) > 1:
|
||
|
NewVariableValue = NewVariableValueList[1].strip()
|
||
|
if NewVariableValue.startswith('&'):
|
||
|
Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, NewVariableValue[1:], GuidMacro, GuidValue, BelongsToFunction, 0)
|
||
|
continue
|
||
|
else:
|
||
|
EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, NewParameter))
|
||
|
|
||
|
## SearchPpis() method
|
||
|
#
|
||
|
# Search all used PPI calling function
|
||
|
# Store the result to database
|
||
|
#
|
||
|
# @param SqlCommand: SQL command statement
|
||
|
# @param Table: Table id
|
||
|
# @param SourceFileID: Source file id
|
||
|
# @param SourceFileFullPath: Source file full path
|
||
|
# @param ItemMode: Mode of the item
|
||
|
# @param PpiMode: Mode of PPI
|
||
|
#
|
||
|
def SearchPpi(SqlCommand, Table, SourceFileID, SourceFileFullPath, ItemMode, PpiMode = 1):
|
||
|
ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Ppi', '', '', ''
|
||
|
BelongsToFunctionID, BelongsToFunction = -1, ''
|
||
|
Db = EotGlobalData.gDb.TblReport
|
||
|
RecordSet = Db.Exec(SqlCommand)
|
||
|
for Record in RecordSet:
|
||
|
Parameter = GetPpiParameter(Record[0], PpiMode)
|
||
|
BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]
|
||
|
# Get BelongsToFunction
|
||
|
BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)
|
||
|
|
||
|
# Default is Not Found
|
||
|
IsFound = False
|
||
|
|
||
|
# For Consumed Ppi
|
||
|
if ItemMode == 'Consumed':
|
||
|
if Parameter.startswith('g'):
|
||
|
Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, Parameter, GuidMacro, GuidValue, BelongsToFunction, 0)
|
||
|
else:
|
||
|
EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))
|
||
|
continue
|
||
|
|
||
|
# Direct Parameter.Guid
|
||
|
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)
|
||
|
NewRecordSet = Db.Exec(SqlCommand)
|
||
|
for NewRecord in NewRecordSet:
|
||
|
GuidName = GetParameterName(NewRecord[0])
|
||
|
Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
|
||
|
IsFound = True
|
||
|
|
||
|
# Defined Parameter
|
||
|
if not IsFound:
|
||
|
Key = Parameter
|
||
|
if Key.rfind(' ') > -1:
|
||
|
Key = Key[Key.rfind(' ') : ].strip().replace('&', '')
|
||
|
Value = FindKeyValue(EotGlobalData.gDb.TblFile, Table, Key)
|
||
|
List = GetSplitValueList(Value.replace('\n', ''), TAB_COMMA_SPLIT)
|
||
|
if len(List) > 1:
|
||
|
GuidName = GetParameterName(List[1])
|
||
|
Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
|
||
|
IsFound = True
|
||
|
|
||
|
# A list Parameter
|
||
|
if not IsFound:
|
||
|
Start = Parameter.find('[')
|
||
|
End = Parameter.find(']')
|
||
|
if Start > -1 and End > -1 and Start < End:
|
||
|
try:
|
||
|
Index = int(Parameter[Start + 1 : End])
|
||
|
Parameter = Parameter[0 : Start]
|
||
|
SqlCommand = """select Value from %s where Name = '%s' and Model = %s""" % (Table, Parameter, MODEL_IDENTIFIER_VARIABLE)
|
||
|
NewRecordSet = Db.Exec(SqlCommand)
|
||
|
for NewRecord in NewRecordSet:
|
||
|
NewParameter = GetSplitValueList(NewRecord[0], '}')[Index]
|
||
|
GuidName = GetPpiParameter(NewParameter[NewParameter.find('{') : ])
|
||
|
Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
|
||
|
IsFound = True
|
||
|
except Exception:
|
||
|
pass
|
||
|
|
||
|
# A External Parameter
|
||
|
if not IsFound:
|
||
|
SqlCommand = """select File.ID from Inf, File
|
||
|
where BelongsToFile = (select BelongsToFile from Inf where Value1 = '%s')
|
||
|
and Inf.Model = %s and Inf.Value1 = File.FullPath and File.Model = %s""" % (SourceFileFullPath, MODEL_EFI_SOURCE_FILE, MODEL_FILE_C)
|
||
|
NewRecordSet = Db.Exec(SqlCommand)
|
||
|
for NewRecord in NewRecordSet:
|
||
|
Table = 'Identifier' + str(NewRecord[0])
|
||
|
SqlCommand = """select Value from %s where Name = '%s' and Modifier = 'EFI_PEI_PPI_DESCRIPTOR' and Model = %s""" % (Table, Parameter, MODEL_IDENTIFIER_VARIABLE)
|
||
|
PpiSet = Db.Exec(SqlCommand)
|
||
|
if PpiSet != []:
|
||
|
GuidName = GetPpiParameter(PpiSet[0][0])
|
||
|
if GuidName != '':
|
||
|
Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
|
||
|
IsFound = True
|
||
|
break
|
||
|
|
||
|
if not IsFound:
|
||
|
EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))
|
||
|
|
||
|
## SearchProtocols() method
|
||
|
#
|
||
|
# Search all used PROTOCOL calling function
|
||
|
# Store the result to database
|
||
|
#
|
||
|
# @param SqlCommand: SQL command statement
|
||
|
# @param Table: Table id
|
||
|
# @param SourceFileID: Source file id
|
||
|
# @param SourceFileFullPath: Source file full path
|
||
|
# @param ItemMode: Mode of the item
|
||
|
# @param ProtocolMode: Mode of PROTOCOL
|
||
|
#
|
||
|
def SearchProtocols(SqlCommand, Table, SourceFileID, SourceFileFullPath, ItemMode, ProtocolMode):
|
||
|
ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Protocol', '', '', ''
|
||
|
BelongsToFunctionID, BelongsToFunction = -1, ''
|
||
|
Db = EotGlobalData.gDb.TblReport
|
||
|
RecordSet = Db.Exec(SqlCommand)
|
||
|
for Record in RecordSet:
|
||
|
Parameter = ''
|
||
|
BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]
|
||
|
# Get BelongsToFunction
|
||
|
BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)
|
||
|
|
||
|
# Default is Not Found
|
||
|
IsFound = False
|
||
|
|
||
|
if ProtocolMode == 0 or ProtocolMode == 1:
|
||
|
Parameter = GetProtocolParameter(Record[0], ProtocolMode)
|
||
|
if Parameter.startswith('g') or Parameter.endswith('Guid') or Parameter == 'ShellEnvProtocol' or Parameter == 'ShellInterfaceProtocol':
|
||
|
GuidName = GetParameterName(Parameter)
|
||
|
Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
|
||
|
IsFound = True
|
||
|
|
||
|
if ProtocolMode == 2:
|
||
|
Protocols = GetSplitValueList(Record[0], TAB_COMMA_SPLIT)
|
||
|
for Protocol in Protocols:
|
||
|
if Protocol.startswith('&') and Protocol.endswith('Guid'):
|
||
|
GuidName = GetParameterName(Protocol)
|
||
|
Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
|
||
|
IsFound = True
|
||
|
else:
|
||
|
NewValue = FindKeyValue(EotGlobalData.gDb.TblFile, Table, Protocol)
|
||
|
if Protocol != NewValue and NewValue.endswith('Guid'):
|
||
|
GuidName = GetParameterName(NewValue)
|
||
|
Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
|
||
|
IsFound = True
|
||
|
|
||
|
if not IsFound:
|
||
|
if BelongsToFunction in EotGlobalData.gProducedProtocolLibrary or BelongsToFunction in EotGlobalData.gConsumedProtocolLibrary:
|
||
|
EotGlobalData.gOP_UN_MATCHED_IN_LIBRARY_CALLING.write('%s, %s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter, BelongsToFunction))
|
||
|
else:
|
||
|
EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))
|
||
|
|
||
|
## SearchFunctionCalling() method
|
||
|
#
|
||
|
# Search all used PPI/PROTOCOL calling function by library
|
||
|
# Store the result to database
|
||
|
#
|
||
|
# @param SqlCommand: SQL command statement
|
||
|
# @param Table: Table id
|
||
|
# @param SourceFileID: Source file id
|
||
|
# @param SourceFileFullPath: Source file full path
|
||
|
# @param ItemType: Type of the item, PPI or PROTOCOL
|
||
|
# @param ItemMode: Mode of item
|
||
|
#
|
||
|
def SearchFunctionCalling(Table, SourceFileID, SourceFileFullPath, ItemType, ItemMode):
|
||
|
LibraryList = {}
|
||
|
Db = EotGlobalData.gDb.TblReport
|
||
|
Parameters, ItemName, GuidName, GuidMacro, GuidValue, BelongsToFunction = [], '', '', '', '', ''
|
||
|
if ItemType == 'Protocol' and ItemMode == 'Produced':
|
||
|
LibraryList = EotGlobalData.gProducedProtocolLibrary
|
||
|
elif ItemType == 'Protocol' and ItemMode == 'Consumed':
|
||
|
LibraryList = EotGlobalData.gConsumedProtocolLibrary
|
||
|
elif ItemType == 'Protocol' and ItemMode == 'Callback':
|
||
|
LibraryList = EotGlobalData.gCallbackProtocolLibrary
|
||
|
elif ItemType == 'Ppi' and ItemMode == 'Produced':
|
||
|
LibraryList = EotGlobalData.gProducedPpiLibrary
|
||
|
elif ItemType == 'Ppi' and ItemMode == 'Consumed':
|
||
|
LibraryList = EotGlobalData.gConsumedPpiLibrary
|
||
|
|
||
|
for Library in LibraryList:
|
||
|
Index = LibraryList[Library]
|
||
|
SqlCommand = """select Value, StartLine from %s
|
||
|
where Name like '%%%s%%' and Model = %s""" \
|
||
|
% (Table, Library, MODEL_IDENTIFIER_FUNCTION_CALLING)
|
||
|
RecordSet = Db.Exec(SqlCommand)
|
||
|
for Record in RecordSet:
|
||
|
IsFound = False
|
||
|
if Index == -1:
|
||
|
ParameterList = GetSplitValueList(Record[0], TAB_COMMA_SPLIT)
|
||
|
for Parameter in ParameterList:
|
||
|
Parameters.append(GetParameterName(Parameter))
|
||
|
else:
|
||
|
Parameters = [GetProtocolParameter(Record[0], Index)]
|
||
|
StartLine = Record[1]
|
||
|
for Parameter in Parameters:
|
||
|
if Parameter.startswith('g') or Parameter.endswith('Guid') or Parameter == 'ShellEnvProtocol' or Parameter == 'ShellInterfaceProtocol':
|
||
|
GuidName = GetParameterName(Parameter)
|
||
|
Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
|
||
|
IsFound = True
|
||
|
|
||
|
if not IsFound:
|
||
|
EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))
|
||
|
|
||
|
## FindProtocols() method
|
||
|
#
|
||
|
# Find defined protocols
|
||
|
#
|
||
|
# @param SqlCommand: SQL command statement
|
||
|
# @param Table: Table id
|
||
|
# @param SourceFileID: Source file id
|
||
|
# @param SourceFileFullPath: Source file full path
|
||
|
# @param ItemName: String of protocol definition
|
||
|
# @param ItemType: Type of the item, PPI or PROTOCOL
|
||
|
# @param ItemMode: Mode of item
|
||
|
#
|
||
|
#def FindProtocols(Db, SqlCommand, Table, SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue):
|
||
|
# BelongsToFunction = ''
|
||
|
# RecordSet = Db.Exec(SqlCommand)
|
||
|
# for Record in RecordSet:
|
||
|
# IsFound = True
|
||
|
# Parameter = GetProtocolParameter(Record[0])
|
||
|
|
||
|
## GetProtocolParameter() method
|
||
|
#
|
||
|
# Parse string of protocol and find parameters
|
||
|
#
|
||
|
# @param Parameter: Parameter to be parsed
|
||
|
# @param Index: The index of the parameter
|
||
|
#
|
||
|
# @return: call common GetParameter
|
||
|
#
|
||
|
def GetProtocolParameter(Parameter, Index = 1):
|
||
|
return GetParameter(Parameter, Index)
|
||
|
|
||
|
## GetPpiParameter() method
|
||
|
#
|
||
|
# Parse string of ppi and find parameters
|
||
|
#
|
||
|
# @param Parameter: Parameter to be parsed
|
||
|
# @param Index: The index of the parameter
|
||
|
#
|
||
|
# @return: call common GetParameter
|
||
|
#
|
||
|
def GetPpiParameter(Parameter, Index = 1):
|
||
|
return GetParameter(Parameter, Index)
|
||
|
|
||
|
## GetParameter() method
|
||
|
#
|
||
|
# Get a parameter by index
|
||
|
#
|
||
|
# @param Parameter: Parameter to be parsed
|
||
|
# @param Index: The index of the parameter
|
||
|
#
|
||
|
# @return Parameter: The found parameter
|
||
|
#
|
||
|
def GetParameter(Parameter, Index = 1):
|
||
|
ParameterList = GetSplitValueList(Parameter, TAB_COMMA_SPLIT)
|
||
|
if len(ParameterList) > Index:
|
||
|
Parameter = GetParameterName(ParameterList[Index])
|
||
|
|
||
|
return Parameter
|
||
|
|
||
|
return ''
|
||
|
|
||
|
## GetParameterName() method
|
||
|
#
|
||
|
# Get a parameter name
|
||
|
#
|
||
|
# @param Parameter: Parameter to be parsed
|
||
|
#
|
||
|
# @return: The name of parameter
|
||
|
#
|
||
|
def GetParameterName(Parameter):
|
||
|
if isinstance(Parameter, type('')) and Parameter.startswith('&'):
|
||
|
return Parameter[1:].replace('{', '').replace('}', '').replace('\r', '').replace('\n', '').strip()
|
||
|
else:
|
||
|
return Parameter.strip()
|
||
|
|
||
|
## FindKeyValue() method
|
||
|
#
|
||
|
# Find key value of a variable
|
||
|
#
|
||
|
# @param Db: Database to be searched
|
||
|
# @param Table: Table to be searched
|
||
|
# @param Key: The keyword
|
||
|
#
|
||
|
# @return Value: The value of the keyword
|
||
|
#
|
||
|
def FindKeyValue(Db, Table, Key):
|
||
|
SqlCommand = """select Value from %s where Name = '%s' and (Model = %s or Model = %s)""" % (Table, Key, MODEL_IDENTIFIER_VARIABLE, MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION)
|
||
|
RecordSet = Db.Exec(SqlCommand)
|
||
|
Value = ''
|
||
|
for Record in RecordSet:
|
||
|
if Record[0] != 'NULL':
|
||
|
Value = FindKeyValue(Db, Table, GetParameterName(Record[0]))
|
||
|
|
||
|
if Value != '':
|
||
|
return Value
|
||
|
else:
|
||
|
return Key
|
||
|
|
||
|
## ParseMapFile() method
|
||
|
#
|
||
|
# Parse map files to get a dict of 'ModuleName' : {FunName : FunAddress}
|
||
|
#
|
||
|
# @param Files: A list of map files
|
||
|
#
|
||
|
# @return AllMaps: An object of all map files
|
||
|
#
|
||
|
def ParseMapFile(Files):
|
||
|
AllMaps = {}
|
||
|
CurrentModule = ''
|
||
|
CurrentMaps = {}
|
||
|
for File in Files:
|
||
|
Content = open(File, 'r').readlines()
|
||
|
for Line in Content:
|
||
|
Line = CleanString(Line)
|
||
|
# skip empty line
|
||
|
if Line == '':
|
||
|
continue
|
||
|
|
||
|
if Line.find('(') > -1 and Line.find(')') > -1:
|
||
|
if CurrentModule != '' and CurrentMaps != {}:
|
||
|
AllMaps[CurrentModule] = CurrentMaps
|
||
|
CurrentModule = Line[:Line.find('(')]
|
||
|
CurrentMaps = {}
|
||
|
continue
|
||
|
else:
|
||
|
Name = ''
|
||
|
Address = ''
|
||
|
List = Line.split()
|
||
|
Address = List[0]
|
||
|
if List[1] == 'F' or List[1] == 'FS':
|
||
|
Name = List[2]
|
||
|
else:
|
||
|
Name = List[1]
|
||
|
CurrentMaps[Name] = Address
|
||
|
continue
|
||
|
|
||
|
return AllMaps
|
||
|
|
||
|
## ConvertGuid
|
||
|
#
|
||
|
# Convert a GUID to a GUID with all upper letters
|
||
|
#
|
||
|
# @param guid: The GUID to be converted
|
||
|
#
|
||
|
# @param newGuid: The GUID with all upper letters.
|
||
|
#
|
||
|
def ConvertGuid(guid):
|
||
|
numList = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
|
||
|
newGuid = ''
|
||
|
if guid.startswith('g'):
|
||
|
guid = guid[1:]
|
||
|
for i in guid:
|
||
|
if i.upper() == i and i not in numList:
|
||
|
newGuid = newGuid + ('_' + i)
|
||
|
else:
|
||
|
newGuid = newGuid + i.upper()
|
||
|
if newGuid.startswith('_'):
|
||
|
newGuid = newGuid[1:]
|
||
|
if newGuid.endswith('_'):
|
||
|
newGuid = newGuid[:-1]
|
||
|
|
||
|
return newGuid
|
||
|
|
||
|
## ConvertGuid2() method
|
||
|
#
|
||
|
# Convert a GUID to a GUID with new string instead of old string
|
||
|
#
|
||
|
# @param guid: The GUID to be converted
|
||
|
# @param old: Old string to be replaced
|
||
|
# @param new: New string to replace the old one
|
||
|
#
|
||
|
# @param newGuid: The GUID after replacement
|
||
|
#
|
||
|
def ConvertGuid2(guid, old, new):
|
||
|
newGuid = ConvertGuid(guid)
|
||
|
newGuid = newGuid.replace(old, new)
|
||
|
|
||
|
return newGuid
|
||
|
|
||
|
##
|
||
|
#
|
||
|
# This acts like the main() function for the script, unless it is 'import'ed into another
|
||
|
# script.
|
||
|
#
|
||
|
if __name__ == '__main__':
|
||
|
pass
|