]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
platform/x86: think-lmi: add debug_cmd
authorMark Pearson <markpearson@lenovo.com>
Tue, 17 Aug 2021 00:15:01 +0000 (20:15 -0400)
committerHans de Goede <hdegoede@redhat.com>
Wed, 18 Aug 2021 07:41:14 +0000 (09:41 +0200)
Many Lenovo BIOS's support the ability to send a debug command which
is useful for debugging and testing unreleased or early features.

Adding support for this feature as a module parameter.

Signed-off-by: Mark Pearson <markpearson@lenovo.com>
Link: https://lore.kernel.org/r/20210817001501.293501-1-markpearson@lenovo.com
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Documentation/ABI/testing/sysfs-class-firmware-attributes
drivers/platform/x86/think-lmi.c
drivers/platform/x86/think-lmi.h

index 0b43997b76e3b7e826907bc05fc064ae615859a7..90fdf935aa5eab6a2a051cac7a3adfc96c040c91 100644 (file)
@@ -272,3 +272,14 @@ Description:
 
                Note that any changes to this attribute requires a reboot
                for changes to take effect.
+
+What:          /sys/class/firmware-attributes/*/attributes/debug_cmd
+Date:          July 2021
+KernelVersion: 5.14
+Contact:       Mark Pearson <markpearson@lenovo.com>
+Description:
+               This write only attribute can be used to send debug commands to the BIOS.
+               This should only be used when recommended by the BIOS vendor. Vendors may
+               use it to enable extra debug attributes or BIOS features for testing purposes.
+
+               Note that any changes to this attribute requires a reboot for changes to take effect.
index 6cfed4427fb0bf91c302dff0f40f9c555dfc6604..9472aae72df29c83fc6fc4351dfc2b8afbde560b 100644 (file)
 #include "firmware_attributes_class.h"
 #include "think-lmi.h"
 
+static bool debug_support;
+module_param(debug_support, bool, 0444);
+MODULE_PARM_DESC(debug_support, "Enable debug command support");
+
 /*
  * Name:
  *  Lenovo_BiosSetting
  */
 #define LENOVO_GET_BIOS_SELECTIONS_GUID        "7364651A-132F-4FE7-ADAA-40C6C7EE2E3B"
 
+/*
+ * Name:
+ *  Lenovo_DebugCmdGUID
+ * Description
+ *  Debug entry GUID method for entering debug commands to the BIOS
+ */
+#define LENOVO_DEBUG_CMD_GUID "7FF47003-3B6C-4E5E-A227-E979824A85D1"
+
 #define TLMI_POP_PWD (1 << 0)
 #define TLMI_PAP_PWD (1 << 1)
 #define to_tlmi_pwd_setting(kobj)  container_of(kobj, struct tlmi_pwd_setting, kobj)
@@ -660,6 +672,64 @@ static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *
 
 static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot);
 
+/* ---- Debug interface--------------------------------------------------------- */
+static ssize_t debug_cmd_store(struct kobject *kobj, struct kobj_attribute *attr,
+                               const char *buf, size_t count)
+{
+       char *set_str = NULL, *new_setting = NULL;
+       char *auth_str = NULL;
+       char *p;
+       int ret;
+
+       if (!tlmi_priv.can_debug_cmd)
+               return -EOPNOTSUPP;
+
+       new_setting = kstrdup(buf, GFP_KERNEL);
+       if (!new_setting)
+               return -ENOMEM;
+
+       /* Strip out CR if one is present */
+       p = strchrnul(new_setting, '\n');
+       *p = '\0';
+
+       if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
+               auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
+                               tlmi_priv.pwd_admin->password,
+                               encoding_options[tlmi_priv.pwd_admin->encoding],
+                               tlmi_priv.pwd_admin->kbdlang);
+               if (!auth_str) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+       }
+
+       if (auth_str)
+               set_str = kasprintf(GFP_KERNEL, "%s,%s", new_setting, auth_str);
+       else
+               set_str = kasprintf(GFP_KERNEL, "%s;", new_setting);
+       if (!set_str) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = tlmi_simple_call(LENOVO_DEBUG_CMD_GUID, set_str);
+       if (ret)
+               goto out;
+
+       if (!ret && !tlmi_priv.pending_changes) {
+               tlmi_priv.pending_changes = true;
+               /* let userland know it may need to check reboot pending again */
+               kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE);
+       }
+out:
+       kfree(auth_str);
+       kfree(set_str);
+       kfree(new_setting);
+       return ret ?: count;
+}
+
+static struct kobj_attribute debug_cmd = __ATTR_WO(debug_cmd);
+
 /* ---- Initialisation --------------------------------------------------------- */
 static void tlmi_release_attr(void)
 {
@@ -673,6 +743,8 @@ static void tlmi_release_attr(void)
                }
        }
        sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr);
+       if (tlmi_priv.can_debug_cmd && debug_support)
+               sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr);
        kset_unregister(tlmi_priv.attribute_kset);
 
        /* Authentication structures */
@@ -737,6 +809,11 @@ static int tlmi_sysfs_init(void)
        if (ret)
                goto fail_create_attr;
 
+       if (tlmi_priv.can_debug_cmd && debug_support) {
+               ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr);
+               if (ret)
+                       goto fail_create_attr;
+       }
        /* Create authentication entries */
        tlmi_priv.authentication_kset = kset_create_and_add("authentication", NULL,
                                                                &tlmi_priv.class_dev->kobj);
@@ -793,6 +870,9 @@ static int tlmi_analyze(void)
        if (wmi_has_guid(LENOVO_BIOS_PASSWORD_SETTINGS_GUID))
                tlmi_priv.can_get_password_settings = true;
 
+       if (wmi_has_guid(LENOVO_DEBUG_CMD_GUID))
+               tlmi_priv.can_debug_cmd = true;
+
        /*
         * Try to find the number of valid settings of this machine
         * and use it to create sysfs attributes.
index eb598846628a6450e4024c730485923d0b06e395..f8e26823075fde7bc399ff80557d4d4c8513442a 100644 (file)
@@ -61,6 +61,7 @@ struct think_lmi {
        bool can_set_bios_password;
        bool can_get_password_settings;
        bool pending_changes;
+       bool can_debug_cmd;
 
        struct tlmi_attr_setting *setting[TLMI_SETTINGS_COUNT];
        struct device *class_dev;