]> git.proxmox.com Git - mirror_edk2.git/commitdiff
BaseTools/ECC: Add a new checkpoint
authorHess Chen <hesheng.chen@intel.com>
Tue, 11 Apr 2017 08:17:19 +0000 (16:17 +0800)
committerYonghong Zhu <yonghong.zhu@intel.com>
Thu, 13 Apr 2017 02:55:57 +0000 (10:55 +0800)
Add a new checkpoint to check if the SMM communication parameter has
a correct buffer type.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hess Chen <hesheng.chen@intel.com>
Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com>
BaseTools/Source/Python/Ecc/Check.py
BaseTools/Source/Python/Ecc/Configuration.py
BaseTools/Source/Python/Ecc/EccToolError.py
BaseTools/Source/Python/Ecc/config.ini

index 062120c0e51a8288934ce66ea6348611554de7e2..5864758950ce973ccfb0094a732b24cf7b647adb 100644 (file)
@@ -41,6 +41,134 @@ class Check(object):
         self.DeclAndDataTypeCheck()\r
         self.FunctionLayoutCheck()\r
         self.NamingConventionCheck()\r
+        self.SmmCommParaCheck()\r
+\r
+    def SmmCommParaCheck(self):\r
+        self.SmmCommParaCheckBufferType()\r
+\r
+\r
+    # Check if SMM communication function has correct parameter type\r
+    # 1. Get function calling with instance./->Communicate() interface\r
+    # and make sure the protocol instance is of type EFI_SMM_COMMUNICATION_PROTOCOL.\r
+    # 2. Find the origin of the 2nd parameter of Communicate() interface, if -\r
+    #    a. it is a local buffer on stack\r
+    #       report error.\r
+    #    b. it is a global buffer, check the driver that holds the global buffer is of type DXE_RUNTIME_DRIVER\r
+    #       report success.\r
+    #    c. it is a buffer by AllocatePage/AllocatePool (may be wrapped by nested function calls),\r
+    #       check the EFI_MEMORY_TYPE to be EfiRuntimeServicesCode,EfiRuntimeServicesData,\r
+    #       EfiACPIMemoryNVS or EfiReservedMemoryType\r
+    #       report success.\r
+    #    d. it is a buffer located via EFI_SYSTEM_TABLE.ConfigurationTable (may be wrapped by nested function calls)\r
+    #       report warning to indicate human code review.\r
+    #    e. it is a buffer from other kind of pointers (may need to trace into nested function calls to locate),\r
+    #       repeat checks in a.b.c and d.\r
+    def SmmCommParaCheckBufferType(self):\r
+        if EccGlobalData.gConfig.SmmCommParaCheckBufferType == '1' or EccGlobalData.gConfig.SmmCommParaCheckAll == '1':\r
+            EdkLogger.quiet("Checking SMM communication parameter type ...")\r
+            # Get all EFI_SMM_COMMUNICATION_PROTOCOL interface\r
+            CommApiList = []\r
+            for IdentifierTable in EccGlobalData.gIdentifierTableList:\r
+                SqlCommand = """select ID, Name, BelongsToFile from %s\r
+                                where Modifier = 'EFI_SMM_COMMUNICATION_PROTOCOL*' """ % (IdentifierTable)\r
+                RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
+                if RecordSet:\r
+                    for Record in RecordSet:\r
+                        if Record[1] not in CommApiList:\r
+                            CommApiList.append(Record[1])\r
+            # For each interface, check the second parameter\r
+            for CommApi in CommApiList:\r
+                for IdentifierTable in EccGlobalData.gIdentifierTableList:\r
+                    SqlCommand = """select ID, Name, Value, BelongsToFile, StartLine from %s\r
+                    where Name = '%s->Communicate' and Model = %s""" \\r
+                    % (IdentifierTable, CommApi, MODEL_IDENTIFIER_FUNCTION_CALLING)\r
+                    RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
+                    if RecordSet:\r
+                        # print IdentifierTable\r
+                        for Record in RecordSet:\r
+                            # Get the second parameter for Communicate function\r
+                            SecondPara = Record[2].split(',')[1].strip()\r
+                            SecondParaIndex = None\r
+                            if SecondPara.startswith('&'):\r
+                                SecondPara = SecondPara[1:]\r
+                            if SecondPara.endswith(']'):\r
+                                SecondParaIndex = SecondPara[SecondPara.find('[') + 1:-1]\r
+                                SecondPara = SecondPara[:SecondPara.find('[')]\r
+                            # Get the ID\r
+                            Id = Record[0]\r
+                            # Get the BelongsToFile\r
+                            BelongsToFile = Record[3]\r
+                            # Get the source file path\r
+                            SqlCommand = """select FullPath from File where ID = %s""" % BelongsToFile\r
+                            NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
+                            FullPath = NewRecordSet[0][0]\r
+                            # Get the line no of function calling\r
+                            StartLine = Record[4]\r
+                            # Get the module type\r
+                            SqlCommand = """select Value3 from INF where BelongsToFile = (select ID from File\r
+                                            where Path = (select Path from File where ID = %s) and Model = 1011)\r
+                                            and Value2 = 'MODULE_TYPE'""" % BelongsToFile\r
+                            NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
+                            ModuleType = NewRecordSet[0][0] if NewRecordSet else None\r
+\r
+                            # print BelongsToFile, FullPath, StartLine, ModuleType, SecondPara\r
+\r
+                            Value = FindPara(FullPath, SecondPara, StartLine)\r
+                            # Find the value of the parameter\r
+                            if Value:\r
+                                if 'AllocatePage' in Value \\r
+                                    or 'AllocatePool' in Value \\r
+                                    or 'AllocateRuntimePool' in Value \\r
+                                    or 'AllocateZeroPool' in Value:\r
+                                    pass\r
+                                else:\r
+                                    if '->' in Value:\r
+                                        if not EccGlobalData.gException.IsException(\r
+                                               ERROR_SMM_COMM_PARA_CHECK_BUFFER_TYPE, Value):\r
+                                            EccGlobalData.gDb.TblReport.Insert(ERROR_SMM_COMM_PARA_CHECK_BUFFER_TYPE,\r
+                                                                               OtherMsg="Please review the buffer type"\r
+                                                                               + "is correct or not. If it is correct" +\r
+                                                                               " please add [%s] to exception list"\r
+                                                                               % Value,\r
+                                                                               BelongsToTable=IdentifierTable,\r
+                                                                               BelongsToItem=Id)\r
+                                    else:\r
+                                        if not EccGlobalData.gException.IsException(\r
+                                               ERROR_SMM_COMM_PARA_CHECK_BUFFER_TYPE, Value):\r
+                                            EccGlobalData.gDb.TblReport.Insert(ERROR_SMM_COMM_PARA_CHECK_BUFFER_TYPE,\r
+                                                                               OtherMsg="Please review the buffer type"\r
+                                                                               + "is correct or not. If it is correct" +\r
+                                                                               " please add [%s] to exception list"\r
+                                                                               % Value,\r
+                                                                               BelongsToTable=IdentifierTable,\r
+                                                                               BelongsToItem=Id)\r
+\r
+\r
+                            # Not find the value of the parameter\r
+                            else:\r
+                                SqlCommand = """select ID, Modifier, Name, Value, Model, BelongsToFunction from %s\r
+                                                where Name = '%s' and StartLine < %s order by StartLine DESC""" \\r
+                                                % (IdentifierTable, SecondPara, StartLine)\r
+                                NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
+                                if NewRecordSet:\r
+                                    Value = NewRecordSet[0][1]\r
+                                    if 'AllocatePage' in Value \\r
+                                        or 'AllocatePool' in Value \\r
+                                        or 'AllocateRuntimePool' in Value \\r
+                                        or 'AllocateZeroPool' in Value:\r
+                                        pass\r
+                                    else:\r
+                                        if not EccGlobalData.gException.IsException(\r
+                                            ERROR_SMM_COMM_PARA_CHECK_BUFFER_TYPE, Value):\r
+                                            EccGlobalData.gDb.TblReport.Insert(ERROR_SMM_COMM_PARA_CHECK_BUFFER_TYPE,\r
+                                                                               OtherMsg="Please review the buffer type"\r
+                                                                               + "is correct or not. If it is correct" +\r
+                                                                               " please add [%s] to exception list"\r
+                                                                               % Value,\r
+                                                                               BelongsToTable=IdentifierTable,\r
+                                                                               BelongsToItem=Id)\r
+                                else:\r
+                                    pass\r
 \r
     # Check UNI files\r
     def UniCheck(self):\r
@@ -1261,6 +1389,19 @@ class Check(object):
                     if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE, Record[1]):\r
                         EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE, OtherMsg="The variable name [%s] does not follow the rules" % (Record[1]), BelongsToTable=FileTable, BelongsToItem=Record[0])\r
 \r
+def FindPara(FilePath, Para, CallingLine):\r
+    Lines = open(FilePath).readlines()\r
+    Line = ''\r
+    for Index in range(CallingLine - 1, 0, -1):\r
+        # Find the nearest statement for Para\r
+        Line = Lines[Index].strip()\r
+        if Line.startswith('%s = ' % Para):\r
+            Line = Line.strip()\r
+            return Line\r
+            break\r
+\r
+    return ''\r
+\r
 ##\r
 #\r
 # This acts like the main() function for the script, unless it is 'import'ed into another\r
index 5262b685a52e5f48ec5ebe8df5f2d14361089d3e..b523858e1b1f5149b6ef0702495797053f6e8ec0 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # This file is used to define class Configuration\r
 #\r
-# Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution.  The full text of the license may be found at\r
@@ -256,6 +256,11 @@ class Configuration(object):
         # Check PCD whether defined the prompt, help in the DEC file and localized information in the associated UNI file.\r
         self.UniCheckPCDInfo = 1\r
 \r
+        # Check SMM communication function parameter\r
+        self.SmmCommParaCheckAll = 0\r
+        # Check if the EFI_SMM_COMMUNICATION_PROTOCOL parameter buffer type is Reserved / ACPI NVS or UEFI RT code/data\r
+        self.SmmCommParaCheckBufferType = -1\r
+\r
         #\r
         # The check points in this section are reserved\r
         #\r
index 1eae9d1364e655492b0234e1b6fe21d583da9470..1d51da3ae19bf641950267c2301ed83bacf95e8d 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # Standardized Error Hanlding infrastructures.\r
 #\r
-# Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution.  The full text of the license may be found at\r
@@ -105,6 +105,8 @@ ERROR_META_DATA_FILE_CHECK_LIBRARY_NOT_DEFINED = 10022
 \r
 ERROR_SPELLING_CHECK_ALL = 11000\r
 \r
+ERROR_SMM_COMM_PARA_CHECK_BUFFER_TYPE = 12001\r
+\r
 gEccErrorMessage = {\r
     ERROR_GENERAL_CHECK_ALL : "",\r
     ERROR_GENERAL_CHECK_NO_TAB : "'TAB' character is not allowed in source code, please replace each 'TAB' with two spaces",\r
@@ -198,5 +200,7 @@ gEccErrorMessage = {
     ERROR_META_DATA_FILE_CHECK_FORMAT_PCD : "Wrong Pcd Format used in Module file",\r
     ERROR_META_DATA_FILE_CHECK_LIBRARY_NOT_DEFINED : "Not defined LibraryClass used in the Module file.",\r
     ERROR_SPELLING_CHECK_ALL : "",\r
+\r
+    ERROR_SMM_COMM_PARA_CHECK_BUFFER_TYPE : "SMM communication function may use wrong parameter type",\r
     }\r
 \r
index e97c718dcd2b190e030c9ef00b73f2798f4febf2..9a431bf1245d28ae261ad4f1edd45367ab92f2d0 100644 (file)
@@ -261,6 +261,13 @@ UniCheckPCDInfo = 1
 # Uncheck whether UNI file is in UTF-16 format\r
 GeneralCheckUni = -1\r
 \r
+#\r
+# SMM Communicate Function Parameter Checking\r
+#\r
+SmmCommParaCheckAll = 0\r
+# Check if the EFI_SMM_COMMUNICATION_PROTOCOL parameter buffer type is Reserved / ACPI NVS or UEFI RT code/data\r
+SmmCommParaCheckBufferType = 1\r
+\r
 #\r
 # The check points in this section are reserved\r
 #\r