File Index
Files and directories
Sign in
FILE

think-lmi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/platform/x86/lenovo/think-lmi.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Think LMI BIOS configuration driver
   4 *
   5 * Copyright(C) 2019-2021 Lenovo
   6 *
   7 * Original code from Thinkpad-wmi project https://github.com/iksaif/thinkpad-wmi
   8 * Copyright(C) 2017 Corentin Chary <corentin.chary@gmail.com>
   9 * Distributed under the GPL-2.0 license
  10 */
  11
  12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13
  14#include <linux/acpi.h>
  15#include <linux/array_size.h>
  16#include <linux/errno.h>
  17#include <linux/fs.h>
  18#include <linux/mutex.h>
  19#include <linux/string_helpers.h>
  20#include <linux/types.h>
  21#include <linux/dmi.h>
  22#include <linux/wmi.h>
  23#include "../firmware_attributes_class.h"
  24#include "think-lmi.h"
  25
  26static bool debug_support;
  27module_param(debug_support, bool, 0444);
  28MODULE_PARM_DESC(debug_support, "Enable debug command support");
  29
  30/*
  31 * Name: BiosSetting
  32 * Description: Get item name and settings for current LMI instance.
  33 * Type: Query
  34 * Returns: "Item,Value"
  35 * Example: "WakeOnLAN,Enable"
  36 */
  37#define LENOVO_BIOS_SETTING_GUID "51F5230E-9677-46CD-A1CF-C0B23EE34DB7"
  38
  39/*
  40 * Name: SetBiosSetting
  41 * Description: Change the BIOS setting to the desired value using the SetBiosSetting
  42 *  class. To save the settings, use the SaveBiosSetting class.
  43 *  BIOS settings and values are case sensitive.
  44 *  After making changes to the BIOS settings, you must reboot the computer
  45 *  before the changes will take effect.
  46 * Type: Method
  47 * Arguments: "Item,Value,Password,Encoding,KbdLang;"
  48 * Example: "WakeOnLAN,Disable,pa55w0rd,ascii,us;"
  49 */
  50#define LENOVO_SET_BIOS_SETTINGS_GUID "98479A64-33F5-4E33-A707-8E251EBBC3A1"
  51
  52/*
  53 * Name: SaveBiosSettings
  54 * Description: Save any pending changes in settings.
  55 * Type: Method
  56 * Arguments: "Password,Encoding,KbdLang;"
  57 * Example: "pa55w0rd,ascii,us;"
  58 */
  59#define LENOVO_SAVE_BIOS_SETTINGS_GUID "6A4B54EF-A5ED-4D33-9455-B0D9B48DF4B3"
  60
  61/*
  62 * Name: BiosPasswordSettings
  63 * Description: Return BIOS Password settings
  64 * Type: Query
  65 * Returns: PasswordMode, PasswordState, MinLength, MaxLength,
  66 *  SupportedEncoding, SupportedKeyboard
  67 */
  68#define LENOVO_BIOS_PASSWORD_SETTINGS_GUID "8ADB159E-1E32-455C-BC93-308A7ED98246"
  69
  70/*
  71 * Name: SetBiosPassword
  72 * Description: Change a specific password.
  73 *  - BIOS settings cannot be changed at the same boot as power-on
  74 *    passwords (POP) and hard disk passwords (HDP). If you want to change
  75 *    BIOS settings and POP or HDP, you must reboot the system after changing
  76 *    one of them.
  77 *  - A password cannot be set using this method when one does not already
  78 *    exist. Passwords can only be updated or cleared.
  79 * Type: Method
  80 * Arguments: "PasswordType,CurrentPassword,NewPassword,Encoding,KbdLang;"
  81 * Example: "pop,pa55w0rd,newpa55w0rd,ascii,us;”
  82 */
  83#define LENOVO_SET_BIOS_PASSWORD_GUID "2651D9FD-911C-4B69-B94E-D0DED5963BD7"
  84
  85/*
  86 * Name: GetBiosSelections
  87 * Description: Return a list of valid settings for a given item.
  88 * Type: Method
  89 * Arguments: "Item"
  90 * Returns: "Value1,Value2,Value3,..."
  91 * Example:
  92 *  -> "FlashOverLAN"
  93 *  <- "Enabled,Disabled"
  94 */
  95#define LENOVO_GET_BIOS_SELECTIONS_GUID	"7364651A-132F-4FE7-ADAA-40C6C7EE2E3B"
  96
  97/*
  98 * Name: DebugCmd
  99 * Description: Debug entry method for entering debug commands to the BIOS
 100 */
 101#define LENOVO_DEBUG_CMD_GUID "7FF47003-3B6C-4E5E-A227-E979824A85D1"
 102
 103/*
 104 * Name: OpcodeIF
 105 * Description: Opcode interface which provides the ability to set multiple
 106 *  parameters and then trigger an action with a final command.
 107 *  This is particularly useful for simplifying setting passwords.
 108 *  With this support comes the ability to set System, HDD and NVMe
 109 *  passwords.
 110 *  This is currently available on ThinkCenter and ThinkStations platforms
 111 */
 112#define LENOVO_OPCODE_IF_GUID "DFDDEF2C-57D4-48ce-B196-0FB787D90836"
 113
 114/*
 115 * Name: SetBiosCert
 116 * Description: Install BIOS certificate.
 117 * Type: Method
 118 * Arguments: "Certificate,Password"
 119 * You must reboot the computer before the changes will take effect.
 120 */
 121#define LENOVO_SET_BIOS_CERT_GUID    "26861C9F-47E9-44C4-BD8B-DFE7FA2610FE"
 122#define LENOVO_TC_SET_BIOS_CERT_GUID "955aaf7d-8bc4-4f04-90aa-97469512f167"
 123
 124/*
 125 * Name: UpdateBiosCert
 126 * Description: Update BIOS certificate.
 127 * Type: Method
 128 * Format: "Certificate,Signature"
 129 * You must reboot the computer before the changes will take effect.
 130 */
 131#define LENOVO_UPDATE_BIOS_CERT_GUID "9AA3180A-9750-41F7-B9F7-D5D3B1BAC3CE"
 132#define LENOVO_TC_UPDATE_BIOS_CERT_GUID "5f5bbbb2-c72f-4fb8-8129-228eef4fdbed"
 133
 134/*
 135 * Name: ClearBiosCert
 136 * Description: Uninstall BIOS certificate.
 137 * Type: Method
 138 * Format: "Serial,Signature"
 139 * You must reboot the computer before the changes will take effect.
 140 */
 141#define LENOVO_CLEAR_BIOS_CERT_GUID  "B2BC39A7-78DD-4D71-B059-A510DEC44890"
 142#define LENOVO_TC_CLEAR_BIOS_CERT_GUID  "97849cb6-cb44-42d1-a750-26a596a9eec4"
 143
 144/*
 145 * Name: CertToPassword
 146 * Description: Switch from certificate to password authentication.
 147 * Type: Method
 148 * Format: "Password,Signature"
 149 * You must reboot the computer before the changes will take effect.
 150 */
 151#define LENOVO_CERT_TO_PASSWORD_GUID "0DE8590D-5510-4044-9621-77C227F5A70D"
 152#define LENOVO_TC_CERT_TO_PASSWORD_GUID "ef65480d-38c9-420d-b700-ab3d6c8ebaca"
 153
 154/*
 155 * Name: SetBiosSettingCert
 156 * Description: Set attribute using certificate authentication.
 157 * Type: Method
 158 * Format: "Item,Value,Signature"
 159 */
 160#define LENOVO_SET_BIOS_SETTING_CERT_GUID  "34A008CC-D205-4B62-9E67-31DFA8B90003"
 161#define LENOVO_TC_SET_BIOS_SETTING_CERT_GUID  "19ecba3b-b318-4192-a89b-43d94bc60cea"
 162
 163/*
 164 * Name: SaveBiosSettingCert
 165 * Description: Save any pending changes in settings.
 166 * Type: Method
 167 * Format: "Signature"
 168 */
 169#define LENOVO_SAVE_BIOS_SETTING_CERT_GUID "C050FB9D-DF5F-4606-B066-9EFC401B2551"
 170#define LENOVO_TC_SAVE_BIOS_SETTING_CERT_GUID "0afaf46f-7cca-450a-b455-a826a0bf1af5"
 171
 172/*
 173 * Name: CertThumbprint
 174 * Description: Display Certificate thumbprints
 175 * Type: Query
 176 * Returns: MD5, SHA1 & SHA256 thumbprints
 177 */
 178#define LENOVO_CERT_THUMBPRINT_GUID "C59119ED-1C0D-4806-A8E9-59AA318176C4"
 179
 180#define TLMI_POP_PWD  BIT(0) /* Supervisor */
 181#define TLMI_PAP_PWD  BIT(1) /* Power-on */
 182#define TLMI_HDD_PWD  BIT(2) /* HDD/NVME */
 183#define TLMI_SMP_PWD  BIT(6) /* System Management */
 184#define TLMI_CERT_SVC BIT(7) /* Admin Certificate Based */
 185#define TLMI_CERT_SMC BIT(8) /* System Certificate Based */
 186
 187static const struct tlmi_cert_guids thinkpad_cert_guid = {
 188	.thumbprint = LENOVO_CERT_THUMBPRINT_GUID,
 189	.set_bios_setting = LENOVO_SET_BIOS_SETTING_CERT_GUID,
 190	.save_bios_setting = LENOVO_SAVE_BIOS_SETTING_CERT_GUID,
 191	.cert_to_password = LENOVO_CERT_TO_PASSWORD_GUID,
 192	.clear_bios_cert = LENOVO_CLEAR_BIOS_CERT_GUID,
 193	.update_bios_cert = LENOVO_UPDATE_BIOS_CERT_GUID,
 194	.set_bios_cert = LENOVO_SET_BIOS_CERT_GUID,
 195};
 196
 197static const struct tlmi_cert_guids thinkcenter_cert_guid = {
 198	.thumbprint = LENOVO_CERT_THUMBPRINT_GUID, /* Same GUID as TP */
 199	.set_bios_setting = LENOVO_TC_SET_BIOS_SETTING_CERT_GUID,
 200	.save_bios_setting = LENOVO_TC_SAVE_BIOS_SETTING_CERT_GUID,
 201	.cert_to_password = LENOVO_TC_CERT_TO_PASSWORD_GUID,
 202	.clear_bios_cert = LENOVO_TC_CLEAR_BIOS_CERT_GUID,
 203	.update_bios_cert = LENOVO_TC_UPDATE_BIOS_CERT_GUID,
 204	.set_bios_cert = LENOVO_TC_SET_BIOS_CERT_GUID,
 205};
 206
 207static const struct tlmi_err_codes tlmi_errs[] = {
 208	{"Success", 0},
 209	{"Set Certificate operation was successful.", 0},
 210	{"Not Supported", -EOPNOTSUPP},
 211	{"Invalid Parameter", -EINVAL},
 212	{"Access Denied", -EACCES},
 213	{"System Busy", -EBUSY},
 214	{"Set Certificate operation failed with status:Invalid Parameter.", -EINVAL},
 215	{"Set Certificate operation failed with status:Invalid certificate type.", -EINVAL},
 216	{"Set Certificate operation failed with status:Invalid password format.", -EINVAL},
 217	{"Set Certificate operation failed with status:Password retry count exceeded.", -EACCES},
 218	{"Set Certificate operation failed with status:Password Invalid.", -EACCES},
 219	{"Set Certificate operation failed with status:Operation aborted.", -EBUSY},
 220	{"Set Certificate operation failed with status:No free slots to write.", -ENOSPC},
 221	{"Set Certificate operation failed with status:Certificate not found.", -EEXIST},
 222	{"Set Certificate operation failed with status:Internal error.", -EFAULT},
 223	{"Set Certificate operation failed with status:Certificate too large.", -EFBIG},
 224};
 225
 226static const char * const encoding_options[] = {
 227	[TLMI_ENCODING_ASCII] = "ascii",
 228	[TLMI_ENCODING_SCANCODE] = "scancode",
 229};
 230static const char * const level_options[] = {
 231	[TLMI_LEVEL_USER] = "user",
 232	[TLMI_LEVEL_MASTER] = "master",
 233};
 234static struct think_lmi tlmi_priv;
 235static DEFINE_MUTEX(tlmi_mutex);
 236
 237static inline struct tlmi_pwd_setting *to_tlmi_pwd_setting(struct kobject *kobj)
 238{
 239	return container_of(kobj, struct tlmi_pwd_setting, kobj);
 240}
 241
 242static inline struct tlmi_attr_setting *to_tlmi_attr_setting(struct kobject *kobj)
 243{
 244	return container_of(kobj, struct tlmi_attr_setting, kobj);
 245}
 246
 247/* Convert BIOS WMI error string to suitable error code */
 248static int tlmi_errstr_to_err(const char *errstr)
 249{
 250	int i;
 251
 252	for (i = 0; i < sizeof(tlmi_errs)/sizeof(struct tlmi_err_codes); i++) {
 253		if (!strcmp(tlmi_errs[i].err_str, errstr))
 254			return tlmi_errs[i].err_code;
 255	}
 256	return -EPERM;
 257}
 258
 259/* Extract error string from WMI return buffer */
 260static int tlmi_extract_error(const struct acpi_buffer *output)
 261{
 262	const union acpi_object *obj;
 263
 264	obj = output->pointer;
 265	if (!obj)
 266		return -ENOMEM;
 267	if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer)
 268		return -EIO;
 269
 270	return tlmi_errstr_to_err(obj->string.pointer);
 271}
 272
 273/* Utility function to execute WMI call to BIOS */
 274static int tlmi_simple_call(const char *guid, const char *arg)
 275{
 276	const struct acpi_buffer input = { strlen(arg), (char *)arg };
 277	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 278	acpi_status status;
 279	int i, err;
 280
 281	/*
 282	 * Duplicated call required to match BIOS workaround for behavior
 283	 * seen when WMI accessed via scripting on other OS.
 284	 */
 285	for (i = 0; i < 2; i++) {
 286		/* (re)initialize output buffer to default state */
 287		output.length = ACPI_ALLOCATE_BUFFER;
 288		output.pointer = NULL;
 289
 290		status = wmi_evaluate_method(guid, 0, 0, &input, &output);
 291		if (ACPI_FAILURE(status)) {
 292			kfree(output.pointer);
 293			return -EIO;
 294		}
 295		err = tlmi_extract_error(&output);
 296		kfree(output.pointer);
 297		if (err)
 298			return err;
 299	}
 300	return 0;
 301}
 302
 303/* Extract output string from WMI return value */
 304static int tlmi_extract_output_string(union acpi_object *obj, char **string)
 305{
 306	char *s;
 307
 308	if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer)
 309		return -EIO;
 310
 311	s = kstrdup(obj->string.pointer, GFP_KERNEL);
 312	if (!s)
 313		return -ENOMEM;
 314	*string = s;
 315	return 0;
 316}
 317
 318/* ------ Core interface functions ------------*/
 319
 320/* Get password settings from BIOS */
 321static int tlmi_get_pwd_settings(struct tlmi_pwdcfg *pwdcfg)
 322{
 323	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 324	const union acpi_object *obj;
 325	acpi_status status;
 326	int copy_size;
 327
 328	if (!tlmi_priv.can_get_password_settings)
 329		return -EOPNOTSUPP;
 330
 331	status = wmi_query_block(LENOVO_BIOS_PASSWORD_SETTINGS_GUID, 0,
 332				 &output);
 333	if (ACPI_FAILURE(status))
 334		return -EIO;
 335
 336	obj = output.pointer;
 337	if (!obj)
 338		return -ENOMEM;
 339	if (obj->type != ACPI_TYPE_BUFFER || !obj->buffer.pointer) {
 340		kfree(obj);
 341		return -EIO;
 342	}
 343	/*
 344	 * The size of thinkpad_wmi_pcfg on ThinkStation is larger than ThinkPad.
 345	 * To make the driver compatible on different brands, we permit it to get
 346	 * the data in below case.
 347	 * Settings must have at minimum the core fields available
 348	 */
 349	if (obj->buffer.length < sizeof(struct tlmi_pwdcfg_core)) {
 350		pr_warn("Unknown pwdcfg buffer length %d\n", obj->buffer.length);
 351		kfree(obj);
 352		return -EIO;
 353	}
 354
 355	copy_size = min_t(size_t, obj->buffer.length, sizeof(struct tlmi_pwdcfg));
 356
 357	memcpy(pwdcfg, obj->buffer.pointer, copy_size);
 358	kfree(obj);
 359
 360	if (WARN_ON(pwdcfg->core.max_length >= TLMI_PWD_BUFSIZE))
 361		pwdcfg->core.max_length = TLMI_PWD_BUFSIZE - 1;
 362	return 0;
 363}
 364
 365static int tlmi_save_bios_settings(const char *password)
 366{
 367	return tlmi_simple_call(LENOVO_SAVE_BIOS_SETTINGS_GUID,
 368				password);
 369}
 370
 371static int tlmi_opcode_setting(char *setting, const char *value)
 372{
 373	char *opcode_str;
 374	int ret;
 375
 376	opcode_str = kasprintf(GFP_KERNEL, "%s:%s;", setting, value);
 377	if (!opcode_str)
 378		return -ENOMEM;
 379
 380	ret = tlmi_simple_call(LENOVO_OPCODE_IF_GUID, opcode_str);
 381	kfree(opcode_str);
 382	return ret;
 383}
 384
 385static int tlmi_setting(struct wmi_device *wdev, int item, char **value)
 386{
 387	union acpi_object *obj;
 388	int ret;
 389
 390	obj = wmidev_block_query(wdev, item);
 391	if (!obj)
 392		return -EIO;
 393
 394	ret = tlmi_extract_output_string(obj, value);
 395	kfree(obj);
 396
 397	return ret;
 398}
 399
 400static int tlmi_get_bios_selections(const char *item, char **value)
 401{
 402	const struct acpi_buffer input = { strlen(item), (char *)item };
 403	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 404	union acpi_object *obj;
 405	acpi_status status;
 406	int ret;
 407
 408	status = wmi_evaluate_method(LENOVO_GET_BIOS_SELECTIONS_GUID,
 409				     0, 0, &input, &output);
 410	if (ACPI_FAILURE(status))
 411		return -EIO;
 412
 413	obj = output.pointer;
 414	if (!obj)
 415		return -ENODATA;
 416
 417	ret = tlmi_extract_output_string(obj, value);
 418	kfree(obj);
 419
 420	return ret;
 421}
 422
 423/* ---- Authentication sysfs --------------------------------------------------------- */
 424static ssize_t is_enabled_show(struct kobject *kobj, struct kobj_attribute *attr,
 425					  char *buf)
 426{
 427	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 428
 429	return sysfs_emit(buf, "%d\n", setting->pwd_enabled || setting->cert_installed);
 430}
 431
 432static struct kobj_attribute auth_is_pass_set = __ATTR_RO(is_enabled);
 433
 434static ssize_t current_password_store(struct kobject *kobj,
 435				      struct kobj_attribute *attr,
 436				      const char *buf, size_t count)
 437{
 438	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 439	size_t pwdlen;
 440
 441	pwdlen = strlen(buf);
 442	/* pwdlen == 0 is allowed to clear the password */
 443	if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen)))
 444		return -EINVAL;
 445
 446	strscpy(setting->password, buf, setting->maxlen);
 447	/* Strip out CR if one is present, setting password won't work if it is present */
 448	strreplace(setting->password, '\n', '\0');
 449	return count;
 450}
 451
 452static struct kobj_attribute auth_current_password = __ATTR_WO(current_password);
 453
 454static ssize_t new_password_store(struct kobject *kobj,
 455				  struct kobj_attribute *attr,
 456				  const char *buf, size_t count)
 457{
 458	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 459	char *auth_str, *new_pwd;
 460	size_t pwdlen;
 461	int ret;
 462
 463	if (!capable(CAP_SYS_ADMIN))
 464		return -EPERM;
 465
 466	if (!tlmi_priv.can_set_bios_password)
 467		return -EOPNOTSUPP;
 468
 469	/* Strip out CR if one is present, setting password won't work if it is present */
 470	new_pwd = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
 471	if (!new_pwd)
 472		return -ENOMEM;
 473
 474	/* Use lock in case multiple WMI operations needed */
 475	mutex_lock(&tlmi_mutex);
 476
 477	pwdlen = strlen(new_pwd);
 478	/* pwdlen == 0 is allowed to clear the password */
 479	if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) {
 480		ret = -EINVAL;
 481		goto out;
 482	}
 483
 484	/* If opcode support is present use that interface */
 485	if (tlmi_priv.opcode_support) {
 486		char pwd_type[8];
 487
 488		/* Special handling required for HDD and NVMe passwords */
 489		if (setting == tlmi_priv.pwd_hdd) {
 490			if (setting->level == TLMI_LEVEL_USER)
 491				sprintf(pwd_type, "uhdp%d", setting->index);
 492			else
 493				sprintf(pwd_type, "mhdp%d", setting->index);
 494		} else if (setting == tlmi_priv.pwd_nvme) {
 495			if (setting->level == TLMI_LEVEL_USER)
 496				sprintf(pwd_type, "udrp%d", setting->index);
 497			else
 498				sprintf(pwd_type, "adrp%d", setting->index);
 499		} else {
 500			sprintf(pwd_type, "%s", setting->pwd_type);
 501		}
 502
 503		ret = tlmi_opcode_setting("WmiOpcodePasswordType", pwd_type);
 504		if (ret)
 505			goto out;
 506
 507		/*
 508		 * Note admin password is not always required if SMPControl enabled in BIOS,
 509		 * So only set if it's configured.
 510		 * Let BIOS figure it out - we'll get an error if operation is not permitted
 511		 */
 512		if (tlmi_priv.pwd_admin->pwd_enabled && strlen(tlmi_priv.pwd_admin->password)) {
 513			ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
 514					tlmi_priv.pwd_admin->password);
 515			if (ret)
 516				goto out;
 517		}
 518		ret = tlmi_opcode_setting("WmiOpcodePasswordCurrent01", setting->password);
 519		if (ret)
 520			goto out;
 521		ret = tlmi_opcode_setting("WmiOpcodePasswordNew01", new_pwd);
 522		if (ret)
 523			goto out;
 524		ret = tlmi_simple_call(LENOVO_OPCODE_IF_GUID, "WmiOpcodePasswordSetUpdate;");
 525	} else {
 526		/* Format: 'PasswordType,CurrentPw,NewPw,Encoding,KbdLang;' */
 527		auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s,%s,%s;",
 528				setting->pwd_type, setting->password, new_pwd,
 529				encoding_options[setting->encoding], setting->kbdlang);
 530		if (!auth_str) {
 531			ret = -ENOMEM;
 532			goto out;
 533		}
 534		ret = tlmi_simple_call(LENOVO_SET_BIOS_PASSWORD_GUID, auth_str);
 535		kfree(auth_str);
 536	}
 537out:
 538	mutex_unlock(&tlmi_mutex);
 539	kfree(new_pwd);
 540	return ret ?: count;
 541}
 542
 543static struct kobj_attribute auth_new_password = __ATTR_WO(new_password);
 544
 545static ssize_t min_password_length_show(struct kobject *kobj, struct kobj_attribute *attr,
 546			 char *buf)
 547{
 548	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 549
 550	return sysfs_emit(buf, "%d\n", setting->minlen);
 551}
 552
 553static struct kobj_attribute auth_min_pass_length = __ATTR_RO(min_password_length);
 554
 555static ssize_t max_password_length_show(struct kobject *kobj, struct kobj_attribute *attr,
 556			 char *buf)
 557{
 558	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 559
 560	return sysfs_emit(buf, "%d\n", setting->maxlen);
 561}
 562static struct kobj_attribute auth_max_pass_length = __ATTR_RO(max_password_length);
 563
 564static ssize_t mechanism_show(struct kobject *kobj, struct kobj_attribute *attr,
 565			 char *buf)
 566{
 567	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 568
 569	if (setting->cert_installed)
 570		return sysfs_emit(buf, "certificate\n");
 571	return sysfs_emit(buf, "password\n");
 572}
 573static struct kobj_attribute auth_mechanism = __ATTR_RO(mechanism);
 574
 575static ssize_t encoding_show(struct kobject *kobj, struct kobj_attribute *attr,
 576			 char *buf)
 577{
 578	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 579
 580	return sysfs_emit(buf, "%s\n", encoding_options[setting->encoding]);
 581}
 582
 583static ssize_t encoding_store(struct kobject *kobj,
 584				  struct kobj_attribute *attr,
 585				  const char *buf, size_t count)
 586{
 587	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 588	int i;
 589
 590	/* Scan for a matching profile */
 591	i = sysfs_match_string(encoding_options, buf);
 592	if (i < 0)
 593		return -EINVAL;
 594
 595	setting->encoding = i;
 596	return count;
 597}
 598
 599static struct kobj_attribute auth_encoding = __ATTR_RW(encoding);
 600
 601static ssize_t kbdlang_show(struct kobject *kobj, struct kobj_attribute *attr,
 602			 char *buf)
 603{
 604	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 605
 606	return sysfs_emit(buf, "%s\n", setting->kbdlang);
 607}
 608
 609static ssize_t kbdlang_store(struct kobject *kobj,
 610				  struct kobj_attribute *attr,
 611				  const char *buf, size_t count)
 612{
 613	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 614	int length;
 615
 616	/* Calculate length till '\n' or terminating 0 */
 617	length = strchrnul(buf, '\n') - buf;
 618	if (!length || length >= TLMI_LANG_MAXLEN)
 619		return -EINVAL;
 620
 621	memcpy(setting->kbdlang, buf, length);
 622	setting->kbdlang[length] = '\0';
 623	return count;
 624}
 625
 626static struct kobj_attribute auth_kbdlang = __ATTR_RW(kbdlang);
 627
 628static ssize_t role_show(struct kobject *kobj, struct kobj_attribute *attr,
 629			 char *buf)
 630{
 631	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 632
 633	return sysfs_emit(buf, "%s\n", setting->role);
 634}
 635static struct kobj_attribute auth_role = __ATTR_RO(role);
 636
 637static ssize_t index_show(struct kobject *kobj, struct kobj_attribute *attr,
 638			 char *buf)
 639{
 640	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 641
 642	return sysfs_emit(buf, "%d\n", setting->index);
 643}
 644
 645static ssize_t index_store(struct kobject *kobj,
 646				  struct kobj_attribute *attr,
 647				  const char *buf, size_t count)
 648{
 649	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 650	int err, val;
 651
 652	err = kstrtoint(buf, 10, &val);
 653	if (err < 0)
 654		return err;
 655
 656	if (val < 0 || val > TLMI_INDEX_MAX)
 657		return -EINVAL;
 658
 659	setting->index = val;
 660	return count;
 661}
 662
 663static struct kobj_attribute auth_index = __ATTR_RW(index);
 664
 665static ssize_t level_show(struct kobject *kobj, struct kobj_attribute *attr,
 666			 char *buf)
 667{
 668	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 669
 670	return sysfs_emit(buf, "%s\n", level_options[setting->level]);
 671}
 672
 673static ssize_t level_store(struct kobject *kobj,
 674				  struct kobj_attribute *attr,
 675				  const char *buf, size_t count)
 676{
 677	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 678	int i;
 679
 680	/* Scan for a matching profile */
 681	i = sysfs_match_string(level_options, buf);
 682	if (i < 0)
 683		return -EINVAL;
 684
 685	setting->level = i;
 686	return count;
 687}
 688
 689static struct kobj_attribute auth_level = __ATTR_RW(level);
 690
 691static char *cert_command(struct tlmi_pwd_setting *setting, const char *arg1, const char *arg2)
 692{
 693	/* Prepend with SVC or SMC if multicert supported */
 694	if (tlmi_priv.pwdcfg.core.password_mode >= TLMI_PWDCFG_MODE_MULTICERT)
 695		return kasprintf(GFP_KERNEL, "%s,%s,%s",
 696				 setting == tlmi_priv.pwd_admin ? "SVC" : "SMC",
 697				 arg1, arg2);
 698	else
 699		return kasprintf(GFP_KERNEL, "%s,%s", arg1, arg2);
 700}
 701
 702static ssize_t cert_thumbprint(char *buf, const char *arg, int count)
 703{
 704	const struct acpi_buffer input = { strlen(arg), (char *)arg };
 705	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 706	const union acpi_object *obj;
 707	acpi_status status;
 708
 709	if (!tlmi_priv.cert_guid->thumbprint)
 710		return -EOPNOTSUPP;
 711
 712	/* Older ThinkCenter BIOS may not have support */
 713	if (!wmi_has_guid(tlmi_priv.cert_guid->thumbprint))
 714		return -EOPNOTSUPP;
 715
 716	status = wmi_evaluate_method(tlmi_priv.cert_guid->thumbprint, 0, 0, &input, &output);
 717	if (ACPI_FAILURE(status)) {
 718		kfree(output.pointer);
 719		return -EIO;
 720	}
 721	obj = output.pointer;
 722	if (!obj)
 723		return -ENOMEM;
 724	if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer) {
 725		kfree(output.pointer);
 726		return -EIO;
 727	}
 728	count += sysfs_emit_at(buf, count, "%s : %s\n", arg, (char *)obj->string.pointer);
 729	kfree(output.pointer);
 730
 731	return count;
 732}
 733
 734static char *thumbtypes[] = {"Md5", "Sha1", "Sha256"};
 735
 736static ssize_t certificate_thumbprint_show(struct kobject *kobj, struct kobj_attribute *attr,
 737			 char *buf)
 738{
 739	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 740	unsigned int i;
 741	int count = 0;
 742	char *wmistr;
 743
 744	if (!tlmi_priv.certificate_support || !setting->cert_installed)
 745		return -EOPNOTSUPP;
 746
 747	for (i = 0; i < ARRAY_SIZE(thumbtypes); i++) {
 748		if (tlmi_priv.pwdcfg.core.password_mode >= TLMI_PWDCFG_MODE_MULTICERT) {
 749			/* Format: 'SVC | SMC, Thumbtype' */
 750			wmistr = kasprintf(GFP_KERNEL, "%s,%s",
 751					   setting == tlmi_priv.pwd_admin ? "SVC" : "SMC",
 752					   thumbtypes[i]);
 753		} else {
 754			/* Format: 'Thumbtype' */
 755			wmistr = kasprintf(GFP_KERNEL, "%s", thumbtypes[i]);
 756		}
 757		if (!wmistr)
 758			return -ENOMEM;
 759		count += cert_thumbprint(buf, wmistr, count);
 760		kfree(wmistr);
 761	}
 762
 763	return count;
 764}
 765
 766static struct kobj_attribute auth_cert_thumb = __ATTR_RO(certificate_thumbprint);
 767
 768static ssize_t cert_to_password_store(struct kobject *kobj,
 769				  struct kobj_attribute *attr,
 770				  const char *buf, size_t count)
 771{
 772	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 773	char *auth_str, *passwd;
 774	int ret;
 775
 776	if (!capable(CAP_SYS_ADMIN))
 777		return -EPERM;
 778
 779	if (!tlmi_priv.certificate_support)
 780		return -EOPNOTSUPP;
 781
 782	if (!setting->cert_installed)
 783		return -EINVAL;
 784
 785	if (!setting->signature || !setting->signature[0])
 786		return -EACCES;
 787
 788	/* Strip out CR if one is present */
 789	passwd = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
 790	if (!passwd)
 791		return -ENOMEM;
 792
 793	/* Format: 'Password,Signature' */
 794	auth_str = cert_command(setting, passwd, setting->signature);
 795	if (!auth_str) {
 796		kfree_sensitive(passwd);
 797		return -ENOMEM;
 798	}
 799	ret = tlmi_simple_call(tlmi_priv.cert_guid->cert_to_password, auth_str);
 800	kfree(auth_str);
 801	kfree_sensitive(passwd);
 802
 803	return ret ?: count;
 804}
 805
 806static struct kobj_attribute auth_cert_to_password = __ATTR_WO(cert_to_password);
 807
 808enum cert_install_mode {
 809	TLMI_CERT_INSTALL,
 810	TLMI_CERT_UPDATE,
 811};
 812
 813static ssize_t certificate_store(struct kobject *kobj,
 814				  struct kobj_attribute *attr,
 815				  const char *buf, size_t count)
 816{
 817	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 818	enum cert_install_mode install_mode = TLMI_CERT_INSTALL;
 819	char *auth_str, *new_cert;
 820	const char *serial;
 821	char *signature;
 822	const char *guid;
 823	int ret;
 824
 825	if (!capable(CAP_SYS_ADMIN))
 826		return -EPERM;
 827
 828	if (!tlmi_priv.certificate_support)
 829		return -EOPNOTSUPP;
 830
 831	/* If empty then clear installed certificate */
 832	if ((buf[0] == '\0') || (buf[0] == '\n')) { /* Clear installed certificate */
 833		/* Check that signature is set */
 834		if (!setting->signature || !setting->signature[0])
 835			return -EACCES;
 836
 837		/* Format: 'serial#, signature' */
 838		serial = dmi_get_system_info(DMI_PRODUCT_SERIAL);
 839		if (!serial)
 840			return -ENODEV;
 841		auth_str = cert_command(setting, serial, setting->signature);
 842		if (!auth_str)
 843			return -ENOMEM;
 844
 845		ret = tlmi_simple_call(tlmi_priv.cert_guid->clear_bios_cert, auth_str);
 846		kfree(auth_str);
 847
 848		return ret ?: count;
 849	}
 850
 851	/* Strip out CR if one is present */
 852	new_cert = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
 853	if (!new_cert)
 854		return -ENOMEM;
 855
 856	if (setting->cert_installed) {
 857		/* Certificate is installed so this is an update */
 858		install_mode = TLMI_CERT_UPDATE;
 859		/* If admin account enabled - need to use its signature */
 860		if (tlmi_priv.pwd_admin->pwd_enabled)
 861			signature = tlmi_priv.pwd_admin->signature;
 862		else
 863			signature = setting->signature;
 864	} else { /* Cert install */
 865		/* Check if SMC and SVC already installed */
 866		if ((setting == tlmi_priv.pwd_system) && tlmi_priv.pwd_admin->cert_installed) {
 867			/* This gets treated as a cert update */
 868			install_mode = TLMI_CERT_UPDATE;
 869			signature = tlmi_priv.pwd_admin->signature;
 870		} else { /* Regular cert install */
 871			install_mode = TLMI_CERT_INSTALL;
 872			signature = setting->signature;
 873		}
 874	}
 875
 876	if (install_mode == TLMI_CERT_UPDATE) {
 877		/* This is a certificate update */
 878		if (!signature || !signature[0]) {
 879			kfree(new_cert);
 880			return -EACCES;
 881		}
 882		guid = tlmi_priv.cert_guid->update_bios_cert;
 883		/* Format: 'Certificate,Signature' */
 884		auth_str = cert_command(setting, new_cert, signature);
 885	} else {
 886		/* This is a fresh install */
 887		/* To set admin cert, a password must be enabled */
 888		if ((setting == tlmi_priv.pwd_admin) &&
 889		    (!setting->pwd_enabled || !setting->password[0])) {
 890			kfree(new_cert);
 891			return -EACCES;
 892		}
 893		guid = tlmi_priv.cert_guid->set_bios_cert;
 894		if (tlmi_priv.thinkcenter_mode) {
 895			/* Format: 'Certificate, password, encoding, kbdlang' */
 896			auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s,%s", new_cert,
 897					     setting->password,
 898					     encoding_options[setting->encoding],
 899					     setting->kbdlang);
 900		} else {
 901			/* Format: 'Certificate, password' */
 902			auth_str = cert_command(setting, new_cert, setting->password);
 903		}
 904	}
 905	kfree(new_cert);
 906	if (!auth_str)
 907		return -ENOMEM;
 908
 909	ret = tlmi_simple_call(guid, auth_str);
 910	kfree(auth_str);
 911
 912	return ret ?: count;
 913}
 914
 915static struct kobj_attribute auth_certificate = __ATTR_WO(certificate);
 916
 917static ssize_t signature_store(struct kobject *kobj,
 918				  struct kobj_attribute *attr,
 919				  const char *buf, size_t count)
 920{
 921	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 922	char *new_signature;
 923
 924	if (!capable(CAP_SYS_ADMIN))
 925		return -EPERM;
 926
 927	if (!tlmi_priv.certificate_support)
 928		return -EOPNOTSUPP;
 929
 930	/* Strip out CR if one is present */
 931	new_signature = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
 932	if (!new_signature)
 933		return -ENOMEM;
 934
 935	/* Free any previous signature */
 936	kfree(setting->signature);
 937	setting->signature = new_signature;
 938
 939	return count;
 940}
 941
 942static struct kobj_attribute auth_signature = __ATTR_WO(signature);
 943
 944static ssize_t save_signature_store(struct kobject *kobj,
 945				  struct kobj_attribute *attr,
 946				  const char *buf, size_t count)
 947{
 948	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 949	char *new_signature;
 950
 951	if (!capable(CAP_SYS_ADMIN))
 952		return -EPERM;
 953
 954	if (!tlmi_priv.certificate_support)
 955		return -EOPNOTSUPP;
 956
 957	/* Strip out CR if one is present */
 958	new_signature = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
 959	if (!new_signature)
 960		return -ENOMEM;
 961
 962	/* Free any previous signature */
 963	kfree(setting->save_signature);
 964	setting->save_signature = new_signature;
 965
 966	return count;
 967}
 968
 969static struct kobj_attribute auth_save_signature = __ATTR_WO(save_signature);
 970
 971static umode_t auth_attr_is_visible(struct kobject *kobj,
 972					     struct attribute *attr, int n)
 973{
 974	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
 975
 976	/* We only want to display level and index settings on HDD/NVMe */
 977	if (attr == &auth_index.attr || attr == &auth_level.attr) {
 978		if ((setting == tlmi_priv.pwd_hdd) || (setting == tlmi_priv.pwd_nvme))
 979			return attr->mode;
 980		return 0;
 981	}
 982
 983	/* We only display certificates, if supported */
 984	if (attr == &auth_certificate.attr ||
 985	    attr == &auth_signature.attr ||
 986	    attr == &auth_save_signature.attr ||
 987	    attr == &auth_cert_thumb.attr ||
 988	    attr == &auth_cert_to_password.attr) {
 989		if (tlmi_priv.certificate_support) {
 990			if (setting == tlmi_priv.pwd_admin)
 991				return attr->mode;
 992			if ((tlmi_priv.pwdcfg.core.password_mode >= TLMI_PWDCFG_MODE_MULTICERT) &&
 993			    (setting == tlmi_priv.pwd_system))
 994				return attr->mode;
 995		}
 996		return 0;
 997	}
 998
 999	/* Don't display un-needed settings if opcode available */
1000	if ((attr == &auth_encoding.attr || attr == &auth_kbdlang.attr) &&
1001	    tlmi_priv.opcode_support)
1002		return 0;
1003
1004	return attr->mode;
1005}
1006
1007static struct attribute *auth_attrs[] = {
1008	&auth_is_pass_set.attr,
1009	&auth_min_pass_length.attr,
1010	&auth_max_pass_length.attr,
1011	&auth_current_password.attr,
1012	&auth_new_password.attr,
1013	&auth_role.attr,
1014	&auth_mechanism.attr,
1015	&auth_encoding.attr,
1016	&auth_kbdlang.attr,
1017	&auth_index.attr,
1018	&auth_level.attr,
1019	&auth_certificate.attr,
1020	&auth_signature.attr,
1021	&auth_save_signature.attr,
1022	&auth_cert_thumb.attr,
1023	&auth_cert_to_password.attr,
1024	NULL
1025};
1026
1027static const struct attribute_group auth_attr_group = {
1028	.is_visible = auth_attr_is_visible,
1029	.attrs = auth_attrs,
1030};
1031__ATTRIBUTE_GROUPS(auth_attr);
1032
1033/* ---- Attributes sysfs --------------------------------------------------------- */
1034static ssize_t display_name_show(struct kobject *kobj, struct kobj_attribute *attr,
1035		char *buf)
1036{
1037	struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
1038
1039	return sysfs_emit(buf, "%s\n", setting->display_name);
1040}
1041
1042static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
1043{
1044	struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
1045	char *item, *value;
1046	int ret;
1047
1048	ret = tlmi_setting(setting->wdev, setting->index, &item);
1049	if (ret)
1050		return ret;
1051
1052	/* validate and split from `item,value` -> `value` */
1053	value = strpbrk(item, ",");
1054	if (!value || value == item || !strlen(value + 1))
1055		ret = -EINVAL;
1056	else {
1057		/* On Workstations remove the Options part after the value */
1058		strreplace(value, ';', '\0');
1059		ret = sysfs_emit(buf, "%s\n", value + 1);
1060	}
1061	kfree(item);
1062
1063	return ret;
1064}
1065
1066static ssize_t possible_values_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
1067{
1068	struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
1069
1070	return sysfs_emit(buf, "%s\n", setting->possible_values);
1071}
1072
1073static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
1074		char *buf)
1075{
1076	struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
1077
1078	if (setting->possible_values) {
1079		/* Figure out what setting type is as BIOS does not return this */
1080		if (strchr(setting->possible_values, ';'))
1081			return sysfs_emit(buf, "enumeration\n");
1082	}
1083	/* Anything else is going to be a string */
1084	return sysfs_emit(buf, "string\n");
1085}
1086
1087static ssize_t current_value_store(struct kobject *kobj,
1088		struct kobj_attribute *attr,
1089		const char *buf, size_t count)
1090{
1091	struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
1092	char *set_str = NULL, *new_setting = NULL;
1093	char *auth_str = NULL;
1094	int ret;
1095
1096	if (!tlmi_priv.can_set_bios_settings)
1097		return -EOPNOTSUPP;
1098
1099	/*
1100	 * If we are using bulk saves a reboot should be done once save has
1101	 * been called
1102	 */
1103	if (tlmi_priv.save_mode == TLMI_SAVE_BULK && tlmi_priv.reboot_required)
1104		return -EPERM;
1105
1106	/* Strip out CR if one is present */
1107	new_setting = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
1108	if (!new_setting)
1109		return -ENOMEM;
1110
1111	/* Use lock in case multiple WMI operations needed */
1112	mutex_lock(&tlmi_mutex);
1113
1114	/* Check if certificate authentication is enabled and active */
1115	if (tlmi_priv.certificate_support && tlmi_priv.pwd_admin->cert_installed) {
1116		if (!tlmi_priv.pwd_admin->signature || !tlmi_priv.pwd_admin->save_signature) {
1117			ret = -EINVAL;
1118			goto out;
1119		}
1120		set_str = kasprintf(GFP_KERNEL, "%s,%s,%s", setting->name,
1121				    new_setting, tlmi_priv.pwd_admin->signature);
1122		if (!set_str) {
1123			ret = -ENOMEM;
1124			goto out;
1125		}
1126
1127		ret = tlmi_simple_call(tlmi_priv.cert_guid->set_bios_setting, set_str);
1128		if (ret)
1129			goto out;
1130		if (tlmi_priv.save_mode == TLMI_SAVE_BULK)
1131			tlmi_priv.save_required = true;
1132		else
1133			ret = tlmi_simple_call(tlmi_priv.cert_guid->save_bios_setting,
1134					       tlmi_priv.pwd_admin->save_signature);
1135	} else if (tlmi_priv.opcode_support) {
1136		/*
1137		 * If opcode support is present use that interface.
1138		 * Note - this sets the variable and then the password as separate
1139		 * WMI calls. Function tlmi_save_bios_settings will error if the
1140		 * password is incorrect.
1141		 * Workstation's require the opcode to be set before changing the
1142		 * attribute.
1143		 */
1144		if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) {
1145			ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
1146						  tlmi_priv.pwd_admin->password);
1147			if (ret)
1148				goto out;
1149		}
1150
1151		set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->name,
1152				    new_setting);
1153		if (!set_str) {
1154			ret = -ENOMEM;
1155			goto out;
1156		}
1157
1158		ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str);
1159		if (ret)
1160			goto out;
1161
1162		if (tlmi_priv.save_mode == TLMI_SAVE_BULK)
1163			tlmi_priv.save_required = true;
1164		else
1165			ret = tlmi_save_bios_settings("");
1166	} else { /* old non-opcode based authentication method (deprecated) */
1167		if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) {
1168			auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
1169					tlmi_priv.pwd_admin->password,
1170					encoding_options[tlmi_priv.pwd_admin->encoding],
1171					tlmi_priv.pwd_admin->kbdlang);
1172			if (!auth_str) {
1173				ret = -ENOMEM;
1174				goto out;
1175			}
1176		}
1177
1178		if (auth_str)
1179			set_str = kasprintf(GFP_KERNEL, "%s,%s,%s", setting->name,
1180					    new_setting, auth_str);
1181		else
1182			set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->name,
1183					    new_setting);
1184		if (!set_str) {
1185			ret = -ENOMEM;
1186			goto out;
1187		}
1188
1189		ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str);
1190		if (ret)
1191			goto out;
1192
1193		if (tlmi_priv.save_mode == TLMI_SAVE_BULK) {
1194			tlmi_priv.save_required = true;
1195		} else {
1196			if (auth_str)
1197				ret = tlmi_save_bios_settings(auth_str);
1198			else
1199				ret = tlmi_save_bios_settings("");
1200		}
1201	}
1202	if (!ret && !tlmi_priv.pending_changes) {
1203		tlmi_priv.pending_changes = true;
1204		/* let userland know it may need to check reboot pending again */
1205		kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE);
1206	}
1207out:
1208	mutex_unlock(&tlmi_mutex);
1209	kfree(auth_str);
1210	kfree(set_str);
1211	kfree(new_setting);
1212	return ret ?: count;
1213}
1214
1215static struct kobj_attribute attr_displ_name = __ATTR_RO(display_name);
1216
1217static struct kobj_attribute attr_possible_values = __ATTR_RO(possible_values);
1218
1219static struct kobj_attribute attr_current_val = __ATTR_RW_MODE(current_value, 0600);
1220
1221static struct kobj_attribute attr_type = __ATTR_RO(type);
1222
1223static umode_t attr_is_visible(struct kobject *kobj,
1224					     struct attribute *attr, int n)
1225{
1226	struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
1227
1228	/* We don't want to display possible_values attributes if not available */
1229	if ((attr == &attr_possible_values.attr) && (!setting->possible_values))
1230		return 0;
1231
1232	return attr->mode;
1233}
1234
1235static struct attribute *tlmi_attrs[] = {
1236	&attr_displ_name.attr,
1237	&attr_current_val.attr,
1238	&attr_possible_values.attr,
1239	&attr_type.attr,
1240	NULL
1241};
1242
1243static const struct attribute_group tlmi_attr_group = {
1244	.is_visible = attr_is_visible,
1245	.attrs = tlmi_attrs,
1246};
1247__ATTRIBUTE_GROUPS(tlmi_attr);
1248
1249static void tlmi_attr_setting_release(struct kobject *kobj)
1250{
1251	struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
1252
1253	kfree(setting->possible_values);
1254	kfree(setting);
1255}
1256
1257static void tlmi_pwd_setting_release(struct kobject *kobj)
1258{
1259	struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
1260
1261	kfree(setting);
1262}
1263
1264static const struct kobj_type tlmi_attr_setting_ktype = {
1265	.release        = &tlmi_attr_setting_release,
1266	.sysfs_ops	= &kobj_sysfs_ops,
1267	.default_groups = tlmi_attr_groups,
1268};
1269
1270static const struct kobj_type tlmi_pwd_setting_ktype = {
1271	.release        = &tlmi_pwd_setting_release,
1272	.sysfs_ops	= &kobj_sysfs_ops,
1273	.default_groups = auth_attr_groups,
1274};
1275
1276static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *attr,
1277				   char *buf)
1278{
1279	return sprintf(buf, "%d\n", tlmi_priv.pending_changes);
1280}
1281
1282static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot);
1283
1284static const char * const save_mode_strings[] = {
1285	[TLMI_SAVE_SINGLE] = "single",
1286	[TLMI_SAVE_BULK] = "bulk",
1287	[TLMI_SAVE_SAVE] = "save"
1288};
1289
1290static ssize_t save_settings_show(struct kobject *kobj, struct kobj_attribute *attr,
1291				  char *buf)
1292{
1293	/* Check that setting is valid */
1294	if (WARN_ON(tlmi_priv.save_mode < TLMI_SAVE_SINGLE ||
1295		    tlmi_priv.save_mode > TLMI_SAVE_BULK))
1296		return -EIO;
1297	return sysfs_emit(buf, "%s\n", save_mode_strings[tlmi_priv.save_mode]);
1298}
1299
1300static ssize_t save_settings_store(struct kobject *kobj, struct kobj_attribute *attr,
1301				   const char *buf, size_t count)
1302{
1303	char *auth_str = NULL;
1304	int ret = 0;
1305	int cmd;
1306
1307	cmd = sysfs_match_string(save_mode_strings, buf);
1308	if (cmd < 0)
1309		return cmd;
1310
1311	/* Use lock in case multiple WMI operations needed */
1312	mutex_lock(&tlmi_mutex);
1313
1314	switch (cmd) {
1315	case TLMI_SAVE_SINGLE:
1316	case TLMI_SAVE_BULK:
1317		tlmi_priv.save_mode = cmd;
1318		goto out;
1319	case TLMI_SAVE_SAVE:
1320		/* Check if supported*/
1321		if (!tlmi_priv.can_set_bios_settings ||
1322		    tlmi_priv.save_mode == TLMI_SAVE_SINGLE) {
1323			ret = -EOPNOTSUPP;
1324			goto out;
1325		}
1326		/* Check there is actually something to save */
1327		if (!tlmi_priv.save_required) {
1328			ret = -ENOENT;
1329			goto out;
1330		}
1331		/* Check if certificate authentication is enabled and active */
1332		if (tlmi_priv.certificate_support && tlmi_priv.pwd_admin->cert_installed) {
1333			if (!tlmi_priv.pwd_admin->signature ||
1334			    !tlmi_priv.pwd_admin->save_signature) {
1335				ret = -EINVAL;
1336				goto out;
1337			}
1338			ret = tlmi_simple_call(tlmi_priv.cert_guid->save_bios_setting,
1339					       tlmi_priv.pwd_admin->save_signature);
1340			if (ret)
1341				goto out;
1342		} else if (tlmi_priv.opcode_support) {
1343			if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) {
1344				ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
1345							  tlmi_priv.pwd_admin->password);
1346				if (ret)
1347					goto out;
1348			}
1349			ret = tlmi_save_bios_settings("");
1350		} else { /* old non-opcode based authentication method (deprecated) */
1351			if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) {
1352				auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
1353						     tlmi_priv.pwd_admin->password,
1354						     encoding_options[tlmi_priv.pwd_admin->encoding],
1355						     tlmi_priv.pwd_admin->kbdlang);
1356				if (!auth_str) {
1357					ret = -ENOMEM;
1358					goto out;
1359				}
1360			}
1361
1362			if (auth_str)
1363				ret = tlmi_save_bios_settings(auth_str);
1364			else
1365				ret = tlmi_save_bios_settings("");
1366		}
1367		tlmi_priv.save_required = false;
1368		tlmi_priv.reboot_required = true;
1369
1370		if (!ret && !tlmi_priv.pending_changes) {
1371			tlmi_priv.pending_changes = true;
1372			/* let userland know it may need to check reboot pending again */
1373			kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE);
1374		}
1375		break;
1376	}
1377out:
1378	mutex_unlock(&tlmi_mutex);
1379	kfree(auth_str);
1380	return ret ?: count;
1381}
1382
1383static struct kobj_attribute save_settings = __ATTR_RW(save_settings);
1384
1385/* ---- Debug interface--------------------------------------------------------- */
1386static ssize_t debug_cmd_store(struct kobject *kobj, struct kobj_attribute *attr,
1387				const char *buf, size_t count)
1388{
1389	char *set_str = NULL, *new_setting = NULL;
1390	char *auth_str = NULL;
1391	int ret;
1392
1393	if (!tlmi_priv.can_debug_cmd)
1394		return -EOPNOTSUPP;
1395
1396	/* Strip out CR if one is present */
1397	new_setting = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
1398	if (!new_setting)
1399		return -ENOMEM;
1400
1401	if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) {
1402		auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
1403				tlmi_priv.pwd_admin->password,
1404				encoding_options[tlmi_priv.pwd_admin->encoding],
1405				tlmi_priv.pwd_admin->kbdlang);
1406		if (!auth_str) {
1407			ret = -ENOMEM;
1408			goto out;
1409		}
1410	}
1411
1412	if (auth_str)
1413		set_str = kasprintf(GFP_KERNEL, "%s,%s", new_setting, auth_str);
1414	else
1415		set_str = kasprintf(GFP_KERNEL, "%s;", new_setting);
1416	if (!set_str) {
1417		ret = -ENOMEM;
1418		goto out;
1419	}
1420
1421	ret = tlmi_simple_call(LENOVO_DEBUG_CMD_GUID, set_str);
1422	if (ret)
1423		goto out;
1424
1425	if (!ret && !tlmi_priv.pending_changes) {
1426		tlmi_priv.pending_changes = true;
1427		/* let userland know it may need to check reboot pending again */
1428		kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE);
1429	}
1430out:
1431	kfree(auth_str);
1432	kfree(set_str);
1433	kfree(new_setting);
1434	return ret ?: count;
1435}
1436
1437static struct kobj_attribute debug_cmd = __ATTR_WO(debug_cmd);
1438
1439/* ---- Initialisation --------------------------------------------------------- */
1440static void tlmi_release_attr(void)
1441{
1442	struct kobject *pos, *n;
1443
1444	/* Attribute structures */
1445	sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr);
1446	sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &save_settings.attr);
1447
1448	if (tlmi_priv.can_debug_cmd && debug_support)
1449		sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr);
1450
1451	list_for_each_entry_safe(pos, n, &tlmi_priv.attribute_kset->list, entry)
1452		kobject_put(pos);
1453
1454	kset_unregister(tlmi_priv.attribute_kset);
1455
1456	/* Free up any saved signatures */
1457	kfree(tlmi_priv.pwd_admin->signature);
1458	kfree(tlmi_priv.pwd_admin->save_signature);
1459
1460	/* Authentication structures */
1461	list_for_each_entry_safe(pos, n, &tlmi_priv.authentication_kset->list, entry)
1462		kobject_put(pos);
1463
1464	kset_unregister(tlmi_priv.authentication_kset);
1465}
1466
1467static int tlmi_validate_setting_name(struct kset *attribute_kset, char *name)
1468{
1469	struct kobject *duplicate;
1470
1471	if (!strcmp(name, "Reserved"))
1472		return -EINVAL;
1473
1474	duplicate = kset_find_obj(attribute_kset, name);
1475	if (duplicate) {
1476		pr_debug("Duplicate attribute name found - %s\n", name);
1477		/* kset_find_obj() returns a reference */
1478		kobject_put(duplicate);
1479		return -EBUSY;
1480	}
1481
1482	return 0;
1483}
1484
1485static int tlmi_sysfs_init(void)
1486{
1487	int i, ret;
1488
1489	tlmi_priv.class_dev = device_create(&firmware_attributes_class, NULL, MKDEV(0, 0),
1490			NULL, "%s", "thinklmi");
1491	if (IS_ERR(tlmi_priv.class_dev)) {
1492		ret = PTR_ERR(tlmi_priv.class_dev);
1493		goto fail_class_created;
1494	}
1495
1496	tlmi_priv.attribute_kset = kset_create_and_add("attributes", NULL,
1497			&tlmi_priv.class_dev->kobj);
1498	if (!tlmi_priv.attribute_kset) {
1499		ret = -ENOMEM;
1500		goto fail_device_created;
1501	}
1502
1503	tlmi_priv.authentication_kset = kset_create_and_add("authentication", NULL,
1504							    &tlmi_priv.class_dev->kobj);
1505	if (!tlmi_priv.authentication_kset) {
1506		kset_unregister(tlmi_priv.attribute_kset);
1507		ret = -ENOMEM;
1508		goto fail_device_created;
1509	}
1510
1511	for (i = 0; i < TLMI_SETTINGS_COUNT; i++) {
1512		/* Check if index is a valid setting - skip if it isn't */
1513		if (!tlmi_priv.setting[i])
1514			continue;
1515
1516		/* check for duplicate or reserved values */
1517		if (tlmi_validate_setting_name(tlmi_priv.attribute_kset,
1518					       tlmi_priv.setting[i]->display_name) < 0) {
1519			kfree(tlmi_priv.setting[i]->possible_values);
1520			kfree(tlmi_priv.setting[i]);
1521			tlmi_priv.setting[i] = NULL;
1522			continue;
1523		}
1524
1525		/* Build attribute */
1526		tlmi_priv.setting[i]->kobj.kset = tlmi_priv.attribute_kset;
1527		ret = kobject_init_and_add(&tlmi_priv.setting[i]->kobj, &tlmi_attr_setting_ktype,
1528					   NULL, "%s", tlmi_priv.setting[i]->display_name);
1529		if (ret)
1530			goto fail_create_attr;
1531	}
1532
1533	ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr);
1534	if (ret)
1535		goto fail_create_attr;
1536
1537	ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &save_settings.attr);
1538	if (ret)
1539		goto fail_create_attr;
1540
1541	if (tlmi_priv.can_debug_cmd && debug_support) {
1542		ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr);
1543		if (ret)
1544			goto fail_create_attr;
1545	}
1546
1547	/* Create authentication entries */
1548	tlmi_priv.pwd_admin->kobj.kset = tlmi_priv.authentication_kset;
1549	ret = kobject_init_and_add(&tlmi_priv.pwd_admin->kobj, &tlmi_pwd_setting_ktype,
1550				   NULL, "%s", "Admin");
1551	if (ret)
1552		goto fail_create_attr;
1553
1554	tlmi_priv.pwd_power->kobj.kset = tlmi_priv.authentication_kset;
1555	ret = kobject_init_and_add(&tlmi_priv.pwd_power->kobj, &tlmi_pwd_setting_ktype,
1556				   NULL, "%s", "Power-on");
1557	if (ret)
1558		goto fail_create_attr;
1559
1560	if (tlmi_priv.opcode_support) {
1561		tlmi_priv.pwd_system->kobj.kset = tlmi_priv.authentication_kset;
1562		ret = kobject_init_and_add(&tlmi_priv.pwd_system->kobj, &tlmi_pwd_setting_ktype,
1563					   NULL, "%s", "System");
1564		if (ret)
1565			goto fail_create_attr;
1566
1567		tlmi_priv.pwd_hdd->kobj.kset = tlmi_priv.authentication_kset;
1568		ret = kobject_init_and_add(&tlmi_priv.pwd_hdd->kobj, &tlmi_pwd_setting_ktype,
1569					   NULL, "%s", "HDD");
1570		if (ret)
1571			goto fail_create_attr;
1572
1573		tlmi_priv.pwd_nvme->kobj.kset = tlmi_priv.authentication_kset;
1574		ret = kobject_init_and_add(&tlmi_priv.pwd_nvme->kobj, &tlmi_pwd_setting_ktype,
1575					   NULL, "%s", "NVMe");
1576		if (ret)
1577			goto fail_create_attr;
1578	}
1579
1580	return ret;
1581
1582fail_create_attr:
1583	tlmi_release_attr();
1584fail_device_created:
1585	device_unregister(tlmi_priv.class_dev);
1586fail_class_created:
1587	return ret;
1588}
1589
1590/* ---- Base Driver -------------------------------------------------------- */
1591static struct tlmi_pwd_setting *tlmi_create_auth(const char *pwd_type,
1592			    const char *pwd_role)
1593{
1594	struct tlmi_pwd_setting *new_pwd;
1595
1596	new_pwd = kzalloc(sizeof(struct tlmi_pwd_setting), GFP_KERNEL);
1597	if (!new_pwd)
1598		return NULL;
1599
1600	strscpy(new_pwd->kbdlang, "us");
1601	new_pwd->encoding = TLMI_ENCODING_ASCII;
1602	new_pwd->pwd_type = pwd_type;
1603	new_pwd->role = pwd_role;
1604	new_pwd->minlen = tlmi_priv.pwdcfg.core.min_length;
1605	new_pwd->maxlen = tlmi_priv.pwdcfg.core.max_length;
1606	new_pwd->index = 0;
1607
1608	return new_pwd;
1609}
1610
1611static int tlmi_analyze(struct wmi_device *wdev)
1612{
1613	int i, ret;
1614
1615	if (wmi_has_guid(LENOVO_SET_BIOS_SETTINGS_GUID) &&
1616	    wmi_has_guid(LENOVO_SAVE_BIOS_SETTINGS_GUID))
1617		tlmi_priv.can_set_bios_settings = true;
1618
1619	if (wmi_has_guid(LENOVO_GET_BIOS_SELECTIONS_GUID))
1620		tlmi_priv.can_get_bios_selections = true;
1621
1622	if (wmi_has_guid(LENOVO_SET_BIOS_PASSWORD_GUID))
1623		tlmi_priv.can_set_bios_password = true;
1624
1625	if (wmi_has_guid(LENOVO_BIOS_PASSWORD_SETTINGS_GUID))
1626		tlmi_priv.can_get_password_settings = true;
1627
1628	if (wmi_has_guid(LENOVO_DEBUG_CMD_GUID))
1629		tlmi_priv.can_debug_cmd = true;
1630
1631	if (wmi_has_guid(LENOVO_OPCODE_IF_GUID))
1632		tlmi_priv.opcode_support = true;
1633
1634	if (wmi_has_guid(LENOVO_SET_BIOS_CERT_GUID) &&
1635		wmi_has_guid(LENOVO_SET_BIOS_SETTING_CERT_GUID) &&
1636		wmi_has_guid(LENOVO_SAVE_BIOS_SETTING_CERT_GUID))
1637		tlmi_priv.certificate_support = true;
1638
1639	/* ThinkCenter uses different GUIDs for certificate support */
1640	if (wmi_has_guid(LENOVO_TC_SET_BIOS_CERT_GUID) &&
1641	    wmi_has_guid(LENOVO_TC_SET_BIOS_SETTING_CERT_GUID) &&
1642	    wmi_has_guid(LENOVO_TC_SAVE_BIOS_SETTING_CERT_GUID)) {
1643		tlmi_priv.certificate_support = true;
1644		tlmi_priv.thinkcenter_mode = true;
1645		pr_info("ThinkCenter modified support being used\n");
1646	}
1647
1648	/*
1649	 * Try to find the number of valid settings of this machine
1650	 * and use it to create sysfs attributes.
1651	 */
1652	for (i = 0; i < TLMI_SETTINGS_COUNT; ++i) {
1653		struct tlmi_attr_setting *setting;
1654		char *item = NULL;
1655
1656		tlmi_priv.setting[i] = NULL;
1657		ret = tlmi_setting(wdev, i, &item);
1658		if (ret)
1659			break;
1660		if (!item)
1661			break;
1662		if (!*item) {
1663			kfree(item);
1664			continue;
1665		}
1666
1667		/* Remove the value part */
1668		strreplace(item, ',', '\0');
1669
1670		/* Create a setting entry */
1671		setting = kzalloc(sizeof(*setting), GFP_KERNEL);
1672		if (!setting) {
1673			ret = -ENOMEM;
1674			kfree(item);
1675			goto fail_clear_attr;
1676		}
1677		setting->wdev = wdev;
1678		setting->index = i;
1679
1680		strscpy(setting->name, item);
1681		/* It is not allowed to have '/' for file name. Convert it into '\'. */
1682		strreplace(item, '/', '\\');
1683		strscpy(setting->display_name, item);
1684
1685		/* If BIOS selections supported, load those */
1686		if (tlmi_priv.can_get_bios_selections) {
1687			ret = tlmi_get_bios_selections(setting->name,
1688						       &setting->possible_values);
1689			if (ret || !setting->possible_values)
1690				pr_info("Error retrieving possible values for %d : %s\n",
1691						i, setting->display_name);
1692		} else {
1693			/*
1694			 * Older Thinkstations don't support the bios_selections API.
1695			 * Instead they store this as a [Optional:Option1,Option2] section of the
1696			 * name string.
1697			 * Try and pull that out if it's available.
1698			 */
1699			char *optitem, *optstart, *optend;
1700
1701			if (!tlmi_setting(setting->wdev, setting->index, &optitem)) {
1702				optstart = strstr(optitem, "[Optional:");
1703				if (optstart) {
1704					optstart += strlen("[Optional:");
1705					optend = strstr(optstart, "]");
1706					if (optend)
1707						setting->possible_values =
1708							kstrndup(optstart, optend - optstart,
1709									GFP_KERNEL);
1710				}
1711				kfree(optitem);
1712			}
1713		}
1714		/*
1715		 * firmware-attributes requires that possible_values are separated by ';' but
1716		 * Lenovo FW uses ','. Replace appropriately.
1717		 */
1718		if (setting->possible_values)
1719			strreplace(setting->possible_values, ',', ';');
1720
1721		tlmi_priv.setting[i] = setting;
1722		kfree(item);
1723	}
1724
1725	/* Create password setting structure */
1726	ret = tlmi_get_pwd_settings(&tlmi_priv.pwdcfg);
1727	if (ret)
1728		goto fail_clear_attr;
1729
1730	/* All failures below boil down to kmalloc failures */
1731	ret = -ENOMEM;
1732
1733	tlmi_priv.pwd_admin = tlmi_create_auth("pap", "bios-admin");
1734	if (!tlmi_priv.pwd_admin)
1735		goto fail_clear_attr;
1736
1737	if (tlmi_priv.pwdcfg.core.password_state & TLMI_PAP_PWD)
1738		tlmi_priv.pwd_admin->pwd_enabled = true;
1739
1740	tlmi_priv.pwd_power = tlmi_create_auth("pop", "power-on");
1741	if (!tlmi_priv.pwd_power)
1742		goto fail_clear_attr;
1743
1744	if (tlmi_priv.pwdcfg.core.password_state & TLMI_POP_PWD)
1745		tlmi_priv.pwd_power->pwd_enabled = true;
1746
1747	if (tlmi_priv.opcode_support) {
1748		tlmi_priv.pwd_system = tlmi_create_auth("smp", "system");
1749		if (!tlmi_priv.pwd_system)
1750			goto fail_clear_attr;
1751
1752		if (tlmi_priv.pwdcfg.core.password_state & TLMI_SMP_PWD)
1753			tlmi_priv.pwd_system->pwd_enabled = true;
1754
1755		tlmi_priv.pwd_hdd = tlmi_create_auth("hdd", "hdd");
1756		if (!tlmi_priv.pwd_hdd)
1757			goto fail_clear_attr;
1758
1759		tlmi_priv.pwd_nvme = tlmi_create_auth("nvm", "nvme");
1760		if (!tlmi_priv.pwd_nvme)
1761			goto fail_clear_attr;
1762
1763		/* Set default hdd/nvme index to 1 as there is no device 0 */
1764		tlmi_priv.pwd_hdd->index = 1;
1765		tlmi_priv.pwd_nvme->index = 1;
1766
1767		if (tlmi_priv.pwdcfg.core.password_state & TLMI_HDD_PWD) {
1768			/* Check if PWD is configured and set index to first drive found */
1769			if (tlmi_priv.pwdcfg.ext.hdd_user_password ||
1770					tlmi_priv.pwdcfg.ext.hdd_master_password) {
1771				tlmi_priv.pwd_hdd->pwd_enabled = true;
1772				if (tlmi_priv.pwdcfg.ext.hdd_master_password)
1773					tlmi_priv.pwd_hdd->index =
1774						ffs(tlmi_priv.pwdcfg.ext.hdd_master_password) - 1;
1775				else
1776					tlmi_priv.pwd_hdd->index =
1777						ffs(tlmi_priv.pwdcfg.ext.hdd_user_password) - 1;
1778			}
1779			if (tlmi_priv.pwdcfg.ext.nvme_user_password ||
1780					tlmi_priv.pwdcfg.ext.nvme_master_password) {
1781				tlmi_priv.pwd_nvme->pwd_enabled = true;
1782				if (tlmi_priv.pwdcfg.ext.nvme_master_password)
1783					tlmi_priv.pwd_nvme->index =
1784						ffs(tlmi_priv.pwdcfg.ext.nvme_master_password) - 1;
1785				else
1786					tlmi_priv.pwd_nvme->index =
1787						ffs(tlmi_priv.pwdcfg.ext.nvme_user_password) - 1;
1788			}
1789		}
1790	}
1791
1792	if (tlmi_priv.certificate_support) {
1793		if (tlmi_priv.thinkcenter_mode) {
1794			tlmi_priv.cert_guid = &thinkcenter_cert_guid;
1795			tlmi_priv.pwd_admin->cert_installed = tlmi_priv.pwdcfg.core.password_mode;
1796		} else {
1797			tlmi_priv.cert_guid = &thinkpad_cert_guid;
1798			tlmi_priv.pwd_admin->cert_installed =
1799				tlmi_priv.pwdcfg.core.password_state & TLMI_CERT_SVC;
1800			tlmi_priv.pwd_system->cert_installed =
1801				tlmi_priv.pwdcfg.core.password_state & TLMI_CERT_SMC;
1802		}
1803	}
1804	return 0;
1805
1806fail_clear_attr:
1807	for (i = 0; i < TLMI_SETTINGS_COUNT; ++i) {
1808		if (tlmi_priv.setting[i]) {
1809			kfree(tlmi_priv.setting[i]->possible_values);
1810			kfree(tlmi_priv.setting[i]);
1811		}
1812	}
1813	kfree(tlmi_priv.pwd_admin);
1814	kfree(tlmi_priv.pwd_power);
1815	kfree(tlmi_priv.pwd_system);
1816	kfree(tlmi_priv.pwd_hdd);
1817	kfree(tlmi_priv.pwd_nvme);
1818	return ret;
1819}
1820
1821static void tlmi_remove(struct wmi_device *wdev)
1822{
1823	tlmi_release_attr();
1824	device_unregister(tlmi_priv.class_dev);
1825}
1826
1827static int tlmi_probe(struct wmi_device *wdev, const void *context)
1828{
1829	int ret;
1830
1831	ret = tlmi_analyze(wdev);
1832	if (ret)
1833		return ret;
1834
1835	return tlmi_sysfs_init();
1836}
1837
1838static const struct wmi_device_id tlmi_id_table[] = {
1839	{ .guid_string = LENOVO_BIOS_SETTING_GUID },
1840	{ }
1841};
1842MODULE_DEVICE_TABLE(wmi, tlmi_id_table);
1843
1844static struct wmi_driver tlmi_driver = {
1845	.driver = {
1846		.name = "think-lmi",
1847	},
1848	.id_table = tlmi_id_table,
1849	.probe = tlmi_probe,
1850	.remove = tlmi_remove,
1851};
1852
1853MODULE_AUTHOR("Sugumaran L <slacshiminar@lenovo.com>");
1854MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>");
1855MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>");
1856MODULE_DESCRIPTION("ThinkLMI Driver");
1857MODULE_LICENSE("GPL");
1858
1859module_wmi_driver(tlmi_driver);
~/ Read-only file preview.