[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