[PATCH 2/4] acpi/wmi: Check if the mandatory block query method exists

Armin Wolf W_Armin at gmx.de
Wed Jun 28 20:42:33 UTC 2023


According to the ACPI WMI documentation, WMI data blocks
need to provide a block query method (WQxx). On several
machines (like the Dell Inspiron 3505), some WMI data blocks
do not provide such a method, which for example causes
the linux kernel to log a warning.
Add a matching test to allow for catching this sort of
issue with the fwts. Also update the wmi regression tests.

Signed-off-by: Armin Wolf <W_Armin at gmx.de>
---
 fwts-test/wmi-0001/wmi-0001.log |  26 +++++---
 fwts-test/wmi-0001/wmi-0003.log |  16 +++--
 src/acpi/wmi/wmi.c              | 107 +++++++++++++++++++++++++++++++-
 3 files changed, 137 insertions(+), 12 deletions(-)

diff --git a/fwts-test/wmi-0001/wmi-0001.log b/fwts-test/wmi-0001/wmi-0001.log
index f3436640..0e013a96 100644
--- a/fwts-test/wmi-0001/wmi-0001.log
+++ b/fwts-test/wmi-0001/wmi-0001.log
@@ -5,11 +5,13 @@ wmi             Test 1 of 1: Windows Management Instrumentation test.
 wmi
 wmi             \_SB_.WMI1._WDG (1 of 9)
 wmi               GUID: 51F5230E-9677-46CD-A1CF-C0B23EE34DB7
-wmi               WMI Object:
+wmi               WMI Block:
 wmi                 Flags          : 0x05 (Expensive | String)
 wmi                 Object ID      : A0
 wmi                 Instance       : 0x50
 wmi                 Driver         : think-lmi (Lenovo)
+wmi             PASSED: Test 1, 51F5230E-9677-46CD-A1CF-C0B23EE34DB7 has
+wmi             associated query method \_SB_.WMI1.WQA0
 wmi
 wmi             \_SB_.WMI1._WDG (2 of 9)
 wmi               GUID: 98479A64-33F5-4E33-A707-8E251EBBC3A1
@@ -51,11 +53,13 @@ wmi             associated method \_SB_.WMI1.WMA4
 wmi
 wmi             \_SB_.WMI1._WDG (6 of 9)
 wmi               GUID: 8ADB159E-1E32-455C-BC93-308A7ED98246
-wmi               WMI Object:
+wmi               WMI Block:
 wmi                 Flags          : 0x01 (Expensive)
 wmi                 Object ID      : A5
 wmi                 Instance       : 0x01
 wmi                 Driver         : think-lmi (Lenovo)
+wmi             PASSED: Test 1, 8ADB159E-1E32-455C-BC93-308A7ED98246 has
+wmi             associated query method \_SB_.WMI1.WQA5
 wmi
 wmi             \_SB_.WMI1._WDG (7 of 9)
 wmi               GUID: 2651D9FD-911C-4B69-B94E-D0DED5963BD7
@@ -79,17 +83,21 @@ wmi             associated method \_SB_.WMI1.WMA7
 wmi
 wmi             \_SB_.WMI1._WDG (9 of 9)
 wmi               GUID: 05901221-D566-11D1-B2F0-00A0C9062910
-wmi               WMI Object:
+wmi               WMI Block:
 wmi                 Flags          : 0x00 (None)
 wmi                 Object ID      : BA
 wmi                 Instance       : 0x01
+wmi             PASSED: Test 1, 05901221-D566-11D1-B2F0-00A0C9062910 has
+wmi             associated query method \_SB_.WMI1.WQBA
 wmi
 wmi             \_SB_.WMI2._WDG (1 of 5)
 wmi               GUID: FCB424F1-075A-4E0E-BFC4-62F3E71771FA
-wmi               WMI Object:
+wmi               WMI Block:
 wmi                 Flags          : 0x01 (Expensive)
 wmi                 Object ID      : A7
 wmi                 Instance       : 0x01
+wmi             PASSED: Test 1, FCB424F1-075A-4E0E-BFC4-62F3E71771FA has
+wmi             associated query method \_SB_.WMI2.WQA7
 wmi
 wmi             \_SB_.WMI2._WDG (2 of 5)
 wmi               GUID: E2BE5EE3-42DA-49DB-8378-1F5247388202
@@ -102,10 +110,12 @@ wmi             associated method \_SB_.WMI2.WMA8
 wmi
 wmi             \_SB_.WMI2._WDG (3 of 5)
 wmi               GUID: 7430019A-DCE9-4548-BAB0-9FDE0935CAFF
-wmi               WMI Object:
+wmi               WMI Block:
 wmi                 Flags          : 0x05 (Expensive | String)
 wmi                 Object ID      : A9
 wmi                 Instance       : 0x0a
+wmi             PASSED: Test 1, 7430019A-DCE9-4548-BAB0-9FDE0935CAFF has
+wmi             associated query method \_SB_.WMI2.WQA9
 wmi
 wmi             \_SB_.WMI2._WDG (4 of 5)
 wmi               GUID: 7FF47003-3B6C-4E5E-A227-E979824A85D1
@@ -118,12 +128,14 @@ wmi             associated method \_SB_.WMI2.WMAA
 wmi
 wmi             \_SB_.WMI2._WDG (5 of 5)
 wmi               GUID: 05901221-D566-11D1-B2F0-00A0C9062910
-wmi               WMI Object:
+wmi               WMI Block:
 wmi                 Flags          : 0x00 (None)
 wmi                 Object ID      : BB
 wmi                 Instance       : 0x01
+wmi             PASSED: Test 1, 05901221-D566-11D1-B2F0-00A0C9062910 has
+wmi             associated query method \_SB_.WMI2.WQBB
 wmi
 wmi             ==========================================================
-wmi             8 passed, 0 failed, 0 warning, 0 aborted, 0 skipped, 0
+wmi             14 passed, 0 failed, 0 warning, 0 aborted, 0 skipped, 0
 wmi             info only.
 wmi             ==========================================================
diff --git a/fwts-test/wmi-0001/wmi-0003.log b/fwts-test/wmi-0001/wmi-0003.log
index 06d60d9e..b157f0be 100644
--- a/fwts-test/wmi-0001/wmi-0003.log
+++ b/fwts-test/wmi-0001/wmi-0003.log
@@ -5,11 +5,13 @@ wmi             Test 1 of 1: Windows Management Instrumentation test.
 wmi
 wmi             \_SB_.AMW0._WDG (1 of 6)
 wmi               GUID: 8D9DDCBC-A997-11DA-B012-B622A1EF5492
-wmi               WMI Object:
+wmi               WMI Block:
 wmi                 Flags          : 0x00 (None)
 wmi                 Object ID      : AA
 wmi                 Instance       : 0x01
 wmi                 Driver         : dell-wmi-descriptor (Dell)
+wmi             PASSED: Test 1, 8D9DDCBC-A997-11DA-B012-B622A1EF5492 has
+wmi             associated query method \_SB_.AMW0.WQAA
 wmi
 wmi             \_SB_.AMW0._WDG (2 of 6)
 wmi               GUID: A80593CE-A997-11DA-B012-B622A1EF5492
@@ -41,21 +43,27 @@ wmi                 Driver         : dell-wmi-base (Dell)
 wmi
 wmi             \_SB_.AMW0._WDG (5 of 6)
 wmi               GUID: A3776CE0-1E88-11DB-A98B-0800200C9A66
-wmi               WMI Object:
+wmi               WMI Block:
 wmi                 Flags          : 0x00 (None)
 wmi                 Object ID      : BC
 wmi                 Instance       : 0x01
+wmi             FAILED [LOW] WMIMissingQueryMethod: Test 1, GUID
+wmi             A3776CE0-1E88-11DB-A98B-0800200C9A66 should have an
+wmi             associated query method WQBC defined, however this does
+wmi             not seem to exist.
 wmi
 wmi             \_SB_.AMW0._WDG (6 of 6)
 wmi               GUID: 05901221-D566-11D1-B2F0-00A0C9062910
-wmi               WMI Object:
+wmi               WMI Block:
 wmi                 Flags          : 0x00 (None)
 wmi                 Object ID      : MO
 wmi                 Instance       : 0x01
+wmi             PASSED: Test 1, 05901221-D566-11D1-B2F0-00A0C9062910 has
+wmi             associated query method \_SB_.AMW0.WQMO
 wmi             PASSED: Test 1, All events associated with \_SB_.AMW0._WDG
 wmi             are handled by a kernel driver.
 wmi
 wmi             ==========================================================
-wmi             3 passed, 0 failed, 0 warning, 0 aborted, 0 skipped, 0
+wmi             5 passed, 1 failed, 0 warning, 0 aborted, 0 skipped, 0
 wmi             info only.
 wmi             ==========================================================
diff --git a/src/acpi/wmi/wmi.c b/src/acpi/wmi/wmi.c
index 58b13fce..be9e56d0 100644
--- a/src/acpi/wmi/wmi.c
+++ b/src/acpi/wmi/wmi.c
@@ -211,6 +211,100 @@ static char *wmi_wdg_flags_to_text(const fwts_wmi_flags flags)
 	return buffer;
 }

+/*
+ * wmi_acpi_get_parent_name()
+ *	get parent name of acpi object, the result needs to be freed
+ */
+static char *wmi_acpi_get_parent_name(const char *object_name)
+{
+	size_t parent_name_length;
+	char *parent_name;
+	char *separator;
+
+	separator = strrchr(object_name, '.');
+	if (!separator)
+		return NULL;
+
+	parent_name_length = separator - object_name;
+	parent_name = malloc(parent_name_length + 1);
+	if (!parent_name)
+		return NULL;
+
+	memcpy(parent_name, object_name, parent_name_length);
+	parent_name[parent_name_length] = '\0';
+
+	return parent_name;
+}
+
+/*
+ * wmi_acpi_method_count_on_object()
+ *	count occurance of methods on acpi object
+ */
+static int wmi_acpi_method_count_on_object(const char *object_name, const char *method_name)
+{
+	const size_t object_name_length = strlen(object_name);
+	const size_t method_name_length = strlen(method_name);
+	fwts_list_link *item;
+	fwts_list *objects;
+	int count = 0;
+
+	objects = fwts_acpi_object_get_names();
+	if (!objects)
+		return 0;
+
+	fwts_list_foreach(item, objects) {
+		char *name = fwts_list_data(char *, item);
+		const size_t name_length = strlen(name);
+
+		if (name_length != (object_name_length + method_name_length + 1))
+			continue;
+
+		if (strncmp(object_name, name, object_name_length))
+			continue;
+
+		if (!strncmp(method_name, name + name_length - method_name_length, method_name_length))
+			count++;
+	}
+
+	return count;
+}
+
+/*
+ * wmi_block_query_exist_count()
+ *	check if the mandatory block query method exists for the WDG object
+ */
+static void wmi_block_query_exist_count(
+	fwts_framework *fw,
+	const fwts_wdg_info *info,
+	const char *object_name,
+	const char *guid_str)
+{
+	char wm_name[5];
+	int count;
+
+	snprintf(wm_name, sizeof(wm_name), "WQ%c%c", info->id.obj_id[0], info->id.obj_id[1]);
+
+	count = wmi_acpi_method_count_on_object(object_name, wm_name);
+	switch (count) {
+	case 0:
+		fwts_failed(fw, LOG_LEVEL_LOW, "WMIMissingQueryMethod",
+			"GUID %s should have an associated query method %s defined, "
+			"however this does not seem to exist.",
+			guid_str, wm_name);
+		break;
+	case 1:
+		fwts_passed(fw, "%s has associated query method %s.%s",
+			guid_str, object_name, wm_name);
+		break;
+	default:
+		fwts_failed(fw, LOG_LEVEL_LOW, "WMIMultipleQueryMethod",
+			"GUID %s has multiple associated query methods %s defined, "
+			"this is a firmware bug that leads to ambiguous behaviour.",
+			guid_str, wm_name);
+		break;
+	}
+}
+
 /*
  *  wmi_method_exist_count()
  *	check if an associated method exists for the WDG object
@@ -328,6 +422,14 @@ static void wmi_parse_wdg_data(
 	const fwts_wdg_info *info = (const fwts_wdg_info *)wdg_data;
 	bool all_events_known = true;
 	bool events = false;
+	char *acpi_object_name;
+
+	acpi_object_name = wmi_acpi_get_parent_name(name);
+	if (!acpi_object_name) {
+		fwts_log_info(fw, "Unable to the get parent name of %s", name);
+		return;
+	}
+

 	for (i = 0; i < (size / sizeof(fwts_wdg_info)); i++, info++) {
 		const uint8_t *guid = info->guid;
@@ -365,14 +467,17 @@ static void wmi_parse_wdg_data(
 				all_events_known = false;
 			}
 		} else {
-			fwts_log_info_verbatim(fw, "  WMI Object:");
+			fwts_log_info_verbatim(fw, "  WMI Block:");
 			wmi_dump_object(fw, info);
 			wmi_known_driver(fw, known);
+			wmi_block_query_exist_count(fw, info, acpi_object_name, guid_str);
 		}
 	}

 	if (events && all_events_known)
 		fwts_passed(fw, "All events associated with %s are handled by a kernel driver.", name);
+
+	free(acpi_object_name);
 }

 static int wmi_test1(fwts_framework *fw)
--
2.30.2




More information about the fwts-devel mailing list