Message ID | 20230628204235.7141-3-W_Armin@gmx.de |
---|---|
State | Accepted |
Headers | show |
Series | fwts: Fix various WMI issues | expand |
Thanks! Acked-by: Ivan Hu <ivan.hu@canonical.com> On 6/29/23 04:42, Armin Wolf wrote: > 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@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 > >
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)
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@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(-) -- 2.30.2