mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
platform/x86: think-lmi: add debug_cmd
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>
This commit is contained in:
parent
45b6f75eab
commit
f5bc0157be
@ -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.
|
||||
|
@ -20,6 +20,10 @@
|
||||
#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
|
||||
@ -116,6 +120,14 @@
|
||||
*/
|
||||
#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.
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user