diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-07-01 00:50:00 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-07-01 00:50:00 +0300 |
commit | 9c3255a8f3946a4c8844f1e2e093313f3b71cb30 (patch) | |
tree | 5ca0e29c41444c96406a3ed4874800300de69d8e /drivers/platform/x86/think-lmi.c | |
parent | 6cdbb0907a3c562723455e351c940037bdec9b7a (diff) | |
parent | d2a7bd3690990ab8a8239096ee432ad51985d5b6 (diff) | |
download | linux-9c3255a8f3946a4c8844f1e2e093313f3b71cb30.tar.xz |
Merge tag 'platform-drivers-x86-v6.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86
Pull x86 platform driver updates from Hans de Goede:
"AMD PMC and PMF drivers:
- Various bugfixes
- Improved debugging support
Intel PMC:
- Refactor to support hw with multiple PMCs
- Various other improvements / new hw support
Intel Speed Select Technology (ISST):
- TPMI Uncore Frequency + Cluster Level Power Controls
- Various bugfixes
- tools/intel-speed-select: Misc improvements
Dell-DDV: Add documentation
INT3472 ACPI camera sensor glue code:
- Evaluate device's _DSM method to control imaging clock
- Drop the need to have a table with per sensor-model info
Lenovo Yogabook:
- Refactor / rework to also support Android models
Think-LMI:
- Multiple improvements and fixes
WMI:
- Add proper API documentation for the WMI bus
x86-android-tablets:
- Misc new hw support
Miscellaneous other cleanups / fixes"
* tag 'platform-drivers-x86-v6.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (91 commits)
platform/x86:intel/pmc: Add Meteor Lake IOE-M PMC related maps
platform/x86:intel/pmc: Add Meteor Lake IOE-P PMC related maps
platform/x86:intel/pmc: Use SSRAM to discover pwrm base address of primary PMC
platform/x86:intel/pmc: Discover PMC devices
platform/x86:intel/pmc: Enable debugfs multiple PMC support
platform/x86:intel/pmc: Add support to handle multiple PMCs
platform/x86:intel/pmc: Combine core_init() and core_configure()
platform/x86:intel/pmc: Update maps for Meteor Lake P/M platforms
platform/x86/intel: tpmi: Remove hardcoded unit and offset
platform/x86: int3472: discrete: Log a warning if the pin-numbers don't match
platform/x86: int3472: discrete: Use FIELD_GET() on the GPIO _DSM return value
platform/x86: int3472: discrete: Add alternative "AVDD" regulator supply name
platform/x86: int3472: discrete: Add support for 1 GPIO regulator shared between 2 sensors
platform/x86: int3472: discrete: Remove sensor_config-s
platform/x86: int3472: discrete: Drop GPIO remapping support
platform/x86: apple-gmux: don't use be32_to_cpu and cpu_to_be32
platform/x86/dell/dell-rbtn: Fix resources leaking on error path
platform/x86: ISST: Fix usage counter
platform/x86: ISST: Reset default callback on unregister
platform/x86: int3472: Switch back to use struct i2c_driver's .probe()
...
Diffstat (limited to 'drivers/platform/x86/think-lmi.c')
-rw-r--r-- | drivers/platform/x86/think-lmi.c | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c index 1138f770149d..52d1ce8dfe44 100644 --- a/drivers/platform/x86/think-lmi.c +++ b/drivers/platform/x86/think-lmi.c @@ -14,6 +14,7 @@ #include <linux/acpi.h> #include <linux/errno.h> #include <linux/fs.h> +#include <linux/mutex.h> #include <linux/string.h> #include <linux/types.h> #include <linux/dmi.h> @@ -168,11 +169,11 @@ MODULE_PARM_DESC(debug_support, "Enable debug command support"); */ #define LENOVO_CERT_THUMBPRINT_GUID "C59119ED-1C0D-4806-A8E9-59AA318176C4" -#define TLMI_POP_PWD (1 << 0) -#define TLMI_PAP_PWD (1 << 1) -#define TLMI_HDD_PWD (1 << 2) -#define TLMI_SYS_PWD (1 << 3) -#define TLMI_CERT (1 << 7) +#define TLMI_POP_PWD BIT(0) /* Supervisor */ +#define TLMI_PAP_PWD BIT(1) /* Power-on */ +#define TLMI_HDD_PWD BIT(2) /* HDD/NVME */ +#define TLMI_SMP_PWD BIT(6) /* System Management */ +#define TLMI_CERT BIT(7) /* Certificate Based */ #define to_tlmi_pwd_setting(kobj) container_of(kobj, struct tlmi_pwd_setting, kobj) #define to_tlmi_attr_setting(kobj) container_of(kobj, struct tlmi_attr_setting, kobj) @@ -195,6 +196,7 @@ static const char * const level_options[] = { }; static struct think_lmi tlmi_priv; static struct class *fw_attr_class; +static DEFINE_MUTEX(tlmi_mutex); /* ------ Utility functions ------------*/ /* Strip out CR if one is present */ @@ -437,6 +439,9 @@ static ssize_t new_password_store(struct kobject *kobj, /* Strip out CR if one is present, setting password won't work if it is present */ strip_cr(new_pwd); + /* Use lock in case multiple WMI operations needed */ + mutex_lock(&tlmi_mutex); + pwdlen = strlen(new_pwd); /* pwdlen == 0 is allowed to clear the password */ if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) { @@ -456,9 +461,9 @@ static ssize_t new_password_store(struct kobject *kobj, sprintf(pwd_type, "mhdp%d", setting->index); } else if (setting == tlmi_priv.pwd_nvme) { if (setting->level == TLMI_LEVEL_USER) - sprintf(pwd_type, "unvp%d", setting->index); + sprintf(pwd_type, "udrp%d", setting->index); else - sprintf(pwd_type, "mnvp%d", setting->index); + sprintf(pwd_type, "adrp%d", setting->index); } else { sprintf(pwd_type, "%s", setting->pwd_type); } @@ -493,6 +498,7 @@ static ssize_t new_password_store(struct kobject *kobj, kfree(auth_str); } out: + mutex_unlock(&tlmi_mutex); kfree(new_pwd); return ret ?: count; } @@ -879,6 +885,11 @@ static umode_t auth_attr_is_visible(struct kobject *kobj, return 0; } + /* Don't display un-needed settings if opcode available */ + if ((attr == &auth_encoding.attr || attr == &auth_kbdlang.attr) && + tlmi_priv.opcode_support) + return 0; + return attr->mode; } @@ -981,6 +992,9 @@ static ssize_t current_value_store(struct kobject *kobj, /* Strip out CR if one is present */ strip_cr(new_setting); + /* Use lock in case multiple WMI operations needed */ + mutex_lock(&tlmi_mutex); + /* Check if certificate authentication is enabled and active */ if (tlmi_priv.certificate_support && tlmi_priv.pwd_admin->cert_installed) { if (!tlmi_priv.pwd_admin->signature || !tlmi_priv.pwd_admin->save_signature) { @@ -1001,7 +1015,33 @@ static ssize_t current_value_store(struct kobject *kobj, tlmi_priv.pwd_admin->save_signature); if (ret) goto out; - } else { /* Non certiifcate based authentication */ + } else if (tlmi_priv.opcode_support) { + /* + * If opcode support is present use that interface. + * Note - this sets the variable and then the password as separate + * WMI calls. Function tlmi_save_bios_settings will error if the + * password is incorrect. + */ + set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->display_name, + new_setting); + if (!set_str) { + ret = -ENOMEM; + goto out; + } + + ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str); + if (ret) + goto out; + + if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { + ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", + tlmi_priv.pwd_admin->password); + if (ret) + goto out; + } + + ret = tlmi_save_bios_settings(""); + } else { /* old non-opcode based authentication method (deprecated) */ 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, @@ -1039,6 +1079,7 @@ static ssize_t current_value_store(struct kobject *kobj, kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE); } out: + mutex_unlock(&tlmi_mutex); kfree(auth_str); kfree(set_str); kfree(new_setting); @@ -1483,11 +1524,11 @@ static int tlmi_analyze(void) tlmi_priv.pwd_power->valid = true; if (tlmi_priv.opcode_support) { - tlmi_priv.pwd_system = tlmi_create_auth("sys", "system"); + tlmi_priv.pwd_system = tlmi_create_auth("smp", "system"); if (!tlmi_priv.pwd_system) goto fail_clear_attr; - if (tlmi_priv.pwdcfg.core.password_state & TLMI_SYS_PWD) + if (tlmi_priv.pwdcfg.core.password_state & TLMI_SMP_PWD) tlmi_priv.pwd_system->valid = true; tlmi_priv.pwd_hdd = tlmi_create_auth("hdd", "hdd"); @@ -1498,6 +1539,10 @@ static int tlmi_analyze(void) if (!tlmi_priv.pwd_nvme) goto fail_clear_attr; + /* Set default hdd/nvme index to 1 as there is no device 0 */ + tlmi_priv.pwd_hdd->index = 1; + tlmi_priv.pwd_nvme->index = 1; + if (tlmi_priv.pwdcfg.core.password_state & TLMI_HDD_PWD) { /* Check if PWD is configured and set index to first drive found */ if (tlmi_priv.pwdcfg.ext.hdd_user_password || |