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/errno.h> 16 #include <linux/fs.h> 17 #include <linux/string.h> 18 #include <linux/types.h> 19 #include <linux/wmi.h> 20 #include "firmware_attributes_class.h" 21 #include "think-lmi.h" 22 23 static bool debug_support; 24 module_param(debug_support, bool, 0444); 25 MODULE_PARM_DESC(debug_support, "Enable debug command support"); 26 27 /* 28 * Name: 29 * Lenovo_BiosSetting 30 * Description: 31 * Get item name and settings for current LMI instance. 32 * Type: 33 * Query 34 * Returns: 35 * "Item,Value" 36 * Example: 37 * "WakeOnLAN,Enable" 38 */ 39 #define LENOVO_BIOS_SETTING_GUID "51F5230E-9677-46CD-A1CF-C0B23EE34DB7" 40 41 /* 42 * Name: 43 * Lenovo_SetBiosSetting 44 * Description: 45 * Change the BIOS setting to the desired value using the Lenovo_SetBiosSetting 46 * class. To save the settings, use the Lenovo_SaveBiosSetting class. 47 * BIOS settings and values are case sensitive. 48 * After making changes to the BIOS settings, you must reboot the computer 49 * before the changes will take effect. 50 * Type: 51 * Method 52 * Arguments: 53 * "Item,Value,Password,Encoding,KbdLang;" 54 * Example: 55 * "WakeOnLAN,Disable,pa55w0rd,ascii,us;" 56 */ 57 #define LENOVO_SET_BIOS_SETTINGS_GUID "98479A64-33F5-4E33-A707-8E251EBBC3A1" 58 59 /* 60 * Name: 61 * Lenovo_SaveBiosSettings 62 * Description: 63 * Save any pending changes in settings. 64 * Type: 65 * Method 66 * Arguments: 67 * "Password,Encoding,KbdLang;" 68 * Example: 69 * "pa55w0rd,ascii,us;" 70 */ 71 #define LENOVO_SAVE_BIOS_SETTINGS_GUID "6A4B54EF-A5ED-4D33-9455-B0D9B48DF4B3" 72 73 /* 74 * Name: 75 * Lenovo_BiosPasswordSettings 76 * Description: 77 * Return BIOS Password settings 78 * Type: 79 * Query 80 * Returns: 81 * PasswordMode, PasswordState, MinLength, MaxLength, 82 * SupportedEncoding, SupportedKeyboard 83 */ 84 #define LENOVO_BIOS_PASSWORD_SETTINGS_GUID "8ADB159E-1E32-455C-BC93-308A7ED98246" 85 86 /* 87 * Name: 88 * Lenovo_SetBiosPassword 89 * Description: 90 * Change a specific password. 91 * - BIOS settings cannot be changed at the same boot as power-on 92 * passwords (POP) and hard disk passwords (HDP). If you want to change 93 * BIOS settings and POP or HDP, you must reboot the system after changing 94 * one of them. 95 * - A password cannot be set using this method when one does not already 96 * exist. Passwords can only be updated or cleared. 97 * Type: 98 * Method 99 * Arguments: 100 * "PasswordType,CurrentPassword,NewPassword,Encoding,KbdLang;" 101 * Example: 102 * "pop,pa55w0rd,newpa55w0rd,ascii,us;” 103 */ 104 #define LENOVO_SET_BIOS_PASSWORD_GUID "2651D9FD-911C-4B69-B94E-D0DED5963BD7" 105 106 /* 107 * Name: 108 * Lenovo_GetBiosSelections 109 * Description: 110 * Return a list of valid settings for a given item. 111 * Type: 112 * Method 113 * Arguments: 114 * "Item" 115 * Returns: 116 * "Value1,Value2,Value3,..." 117 * Example: 118 * -> "FlashOverLAN" 119 * <- "Enabled,Disabled" 120 */ 121 #define LENOVO_GET_BIOS_SELECTIONS_GUID "7364651A-132F-4FE7-ADAA-40C6C7EE2E3B" 122 123 /* 124 * Name: 125 * Lenovo_DebugCmdGUID 126 * Description 127 * Debug entry GUID method for entering debug commands to the BIOS 128 */ 129 #define LENOVO_DEBUG_CMD_GUID "7FF47003-3B6C-4E5E-A227-E979824A85D1" 130 131 /* 132 * Name: 133 * Lenovo_OpcodeIF 134 * Description: 135 * Opcode interface which provides the ability to set multiple 136 * parameters and then trigger an action with a final command. 137 * This is particularly useful for simplifying setting passwords. 138 * With this support comes the ability to set System, HDD and NVMe 139 * passwords. 140 * This is currently available on ThinkCenter and ThinkStations platforms 141 */ 142 #define LENOVO_OPCODE_IF_GUID "DFDDEF2C-57D4-48ce-B196-0FB787D90836" 143 144 #define TLMI_POP_PWD (1 << 0) 145 #define TLMI_PAP_PWD (1 << 1) 146 #define TLMI_HDD_PWD (1 << 2) 147 #define TLMI_SYS_PWD (1 << 3) 148 #define to_tlmi_pwd_setting(kobj) container_of(kobj, struct tlmi_pwd_setting, kobj) 149 #define to_tlmi_attr_setting(kobj) container_of(kobj, struct tlmi_attr_setting, kobj) 150 151 static const struct tlmi_err_codes tlmi_errs[] = { 152 {"Success", 0}, 153 {"Not Supported", -EOPNOTSUPP}, 154 {"Invalid Parameter", -EINVAL}, 155 {"Access Denied", -EACCES}, 156 {"System Busy", -EBUSY}, 157 }; 158 159 static const char * const encoding_options[] = { 160 [TLMI_ENCODING_ASCII] = "ascii", 161 [TLMI_ENCODING_SCANCODE] = "scancode", 162 }; 163 static const char * const level_options[] = { 164 [TLMI_LEVEL_USER] = "user", 165 [TLMI_LEVEL_MASTER] = "master", 166 }; 167 static struct think_lmi tlmi_priv; 168 static struct class *fw_attr_class; 169 170 /* ------ Utility functions ------------*/ 171 /* Convert BIOS WMI error string to suitable error code */ 172 static int tlmi_errstr_to_err(const char *errstr) 173 { 174 int i; 175 176 for (i = 0; i < sizeof(tlmi_errs)/sizeof(struct tlmi_err_codes); i++) { 177 if (!strcmp(tlmi_errs[i].err_str, errstr)) 178 return tlmi_errs[i].err_code; 179 } 180 return -EPERM; 181 } 182 183 /* Extract error string from WMI return buffer */ 184 static int tlmi_extract_error(const struct acpi_buffer *output) 185 { 186 const union acpi_object *obj; 187 188 obj = output->pointer; 189 if (!obj) 190 return -ENOMEM; 191 if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer) 192 return -EIO; 193 194 return tlmi_errstr_to_err(obj->string.pointer); 195 } 196 197 /* Utility function to execute WMI call to BIOS */ 198 static int tlmi_simple_call(const char *guid, const char *arg) 199 { 200 const struct acpi_buffer input = { strlen(arg), (char *)arg }; 201 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 202 acpi_status status; 203 int i, err; 204 205 /* 206 * Duplicated call required to match BIOS workaround for behavior 207 * seen when WMI accessed via scripting on other OS. 208 */ 209 for (i = 0; i < 2; i++) { 210 /* (re)initialize output buffer to default state */ 211 output.length = ACPI_ALLOCATE_BUFFER; 212 output.pointer = NULL; 213 214 status = wmi_evaluate_method(guid, 0, 0, &input, &output); 215 if (ACPI_FAILURE(status)) { 216 kfree(output.pointer); 217 return -EIO; 218 } 219 err = tlmi_extract_error(&output); 220 kfree(output.pointer); 221 if (err) 222 return err; 223 } 224 return 0; 225 } 226 227 /* Extract output string from WMI return buffer */ 228 static int tlmi_extract_output_string(const struct acpi_buffer *output, 229 char **string) 230 { 231 const union acpi_object *obj; 232 char *s; 233 234 obj = output->pointer; 235 if (!obj) 236 return -ENOMEM; 237 if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer) 238 return -EIO; 239 240 s = kstrdup(obj->string.pointer, GFP_KERNEL); 241 if (!s) 242 return -ENOMEM; 243 *string = s; 244 return 0; 245 } 246 247 /* ------ Core interface functions ------------*/ 248 249 /* Get password settings from BIOS */ 250 static int tlmi_get_pwd_settings(struct tlmi_pwdcfg *pwdcfg) 251 { 252 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 253 const union acpi_object *obj; 254 acpi_status status; 255 int copy_size; 256 257 if (!tlmi_priv.can_get_password_settings) 258 return -EOPNOTSUPP; 259 260 status = wmi_query_block(LENOVO_BIOS_PASSWORD_SETTINGS_GUID, 0, 261 &output); 262 if (ACPI_FAILURE(status)) 263 return -EIO; 264 265 obj = output.pointer; 266 if (!obj) 267 return -ENOMEM; 268 if (obj->type != ACPI_TYPE_BUFFER || !obj->buffer.pointer) { 269 kfree(obj); 270 return -EIO; 271 } 272 /* 273 * The size of thinkpad_wmi_pcfg on ThinkStation is larger than ThinkPad. 274 * To make the driver compatible on different brands, we permit it to get 275 * the data in below case. 276 * Settings must have at minimum the core fields available 277 */ 278 if (obj->buffer.length < sizeof(struct tlmi_pwdcfg_core)) { 279 pr_warn("Unknown pwdcfg buffer length %d\n", obj->buffer.length); 280 kfree(obj); 281 return -EIO; 282 } 283 284 copy_size = obj->buffer.length < sizeof(struct tlmi_pwdcfg) ? 285 obj->buffer.length : sizeof(struct tlmi_pwdcfg); 286 memcpy(pwdcfg, obj->buffer.pointer, copy_size); 287 kfree(obj); 288 289 if (WARN_ON(pwdcfg->core.max_length >= TLMI_PWD_BUFSIZE)) 290 pwdcfg->core.max_length = TLMI_PWD_BUFSIZE - 1; 291 return 0; 292 } 293 294 static int tlmi_save_bios_settings(const char *password) 295 { 296 return tlmi_simple_call(LENOVO_SAVE_BIOS_SETTINGS_GUID, 297 password); 298 } 299 300 static int tlmi_opcode_setting(char *setting, const char *value) 301 { 302 char *opcode_str; 303 int ret; 304 305 opcode_str = kasprintf(GFP_KERNEL, "%s:%s;", setting, value); 306 if (!opcode_str) 307 return -ENOMEM; 308 309 ret = tlmi_simple_call(LENOVO_OPCODE_IF_GUID, opcode_str); 310 kfree(opcode_str); 311 return ret; 312 } 313 314 static int tlmi_setting(int item, char **value, const char *guid_string) 315 { 316 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 317 acpi_status status; 318 int ret; 319 320 status = wmi_query_block(guid_string, item, &output); 321 if (ACPI_FAILURE(status)) { 322 kfree(output.pointer); 323 return -EIO; 324 } 325 326 ret = tlmi_extract_output_string(&output, value); 327 kfree(output.pointer); 328 return ret; 329 } 330 331 static int tlmi_get_bios_selections(const char *item, char **value) 332 { 333 const struct acpi_buffer input = { strlen(item), (char *)item }; 334 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 335 acpi_status status; 336 int ret; 337 338 status = wmi_evaluate_method(LENOVO_GET_BIOS_SELECTIONS_GUID, 339 0, 0, &input, &output); 340 341 if (ACPI_FAILURE(status)) { 342 kfree(output.pointer); 343 return -EIO; 344 } 345 346 ret = tlmi_extract_output_string(&output, value); 347 kfree(output.pointer); 348 return ret; 349 } 350 351 /* ---- Authentication sysfs --------------------------------------------------------- */ 352 static ssize_t is_enabled_show(struct kobject *kobj, struct kobj_attribute *attr, 353 char *buf) 354 { 355 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 356 357 return sysfs_emit(buf, "%d\n", setting->valid); 358 } 359 360 static struct kobj_attribute auth_is_pass_set = __ATTR_RO(is_enabled); 361 362 static ssize_t current_password_store(struct kobject *kobj, 363 struct kobj_attribute *attr, 364 const char *buf, size_t count) 365 { 366 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 367 size_t pwdlen; 368 char *p; 369 370 pwdlen = strlen(buf); 371 /* pwdlen == 0 is allowed to clear the password */ 372 if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) 373 return -EINVAL; 374 375 strscpy(setting->password, buf, setting->maxlen); 376 /* Strip out CR if one is present, setting password won't work if it is present */ 377 p = strchrnul(setting->password, '\n'); 378 *p = '\0'; 379 return count; 380 } 381 382 static struct kobj_attribute auth_current_password = __ATTR_WO(current_password); 383 384 static ssize_t new_password_store(struct kobject *kobj, 385 struct kobj_attribute *attr, 386 const char *buf, size_t count) 387 { 388 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 389 char *auth_str, *new_pwd, *p; 390 size_t pwdlen; 391 int ret; 392 393 if (!capable(CAP_SYS_ADMIN)) 394 return -EPERM; 395 396 if (!tlmi_priv.can_set_bios_password) 397 return -EOPNOTSUPP; 398 399 new_pwd = kstrdup(buf, GFP_KERNEL); 400 if (!new_pwd) 401 return -ENOMEM; 402 403 /* Strip out CR if one is present, setting password won't work if it is present */ 404 p = strchrnul(new_pwd, '\n'); 405 *p = '\0'; 406 407 pwdlen = strlen(new_pwd); 408 /* pwdlen == 0 is allowed to clear the password */ 409 if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) { 410 ret = -EINVAL; 411 goto out; 412 } 413 414 /* If opcode support is present use that interface */ 415 if (tlmi_priv.opcode_support) { 416 char pwd_type[8]; 417 418 /* Special handling required for HDD and NVMe passwords */ 419 if (setting == tlmi_priv.pwd_hdd) { 420 if (setting->level == TLMI_LEVEL_USER) 421 sprintf(pwd_type, "uhdp%d", setting->index); 422 else 423 sprintf(pwd_type, "mhdp%d", setting->index); 424 } else if (setting == tlmi_priv.pwd_nvme) { 425 if (setting->level == TLMI_LEVEL_USER) 426 sprintf(pwd_type, "unvp%d", setting->index); 427 else 428 sprintf(pwd_type, "mnvp%d", setting->index); 429 } else { 430 sprintf(pwd_type, "%s", setting->pwd_type); 431 } 432 433 ret = tlmi_opcode_setting("WmiOpcodePasswordType", pwd_type); 434 if (ret) 435 goto out; 436 437 if (tlmi_priv.pwd_admin->valid) { 438 ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", 439 tlmi_priv.pwd_admin->password); 440 if (ret) 441 goto out; 442 } 443 ret = tlmi_opcode_setting("WmiOpcodePasswordCurrent01", setting->password); 444 if (ret) 445 goto out; 446 ret = tlmi_opcode_setting("WmiOpcodePasswordNew01", new_pwd); 447 if (ret) 448 goto out; 449 ret = tlmi_simple_call(LENOVO_OPCODE_IF_GUID, "WmiOpcodePasswordSetUpdate;"); 450 } else { 451 /* Format: 'PasswordType,CurrentPw,NewPw,Encoding,KbdLang;' */ 452 auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s,%s,%s;", 453 setting->pwd_type, setting->password, new_pwd, 454 encoding_options[setting->encoding], setting->kbdlang); 455 if (!auth_str) { 456 ret = -ENOMEM; 457 goto out; 458 } 459 ret = tlmi_simple_call(LENOVO_SET_BIOS_PASSWORD_GUID, auth_str); 460 kfree(auth_str); 461 } 462 out: 463 kfree(new_pwd); 464 return ret ?: count; 465 } 466 467 static struct kobj_attribute auth_new_password = __ATTR_WO(new_password); 468 469 static ssize_t min_password_length_show(struct kobject *kobj, struct kobj_attribute *attr, 470 char *buf) 471 { 472 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 473 474 return sysfs_emit(buf, "%d\n", setting->minlen); 475 } 476 477 static struct kobj_attribute auth_min_pass_length = __ATTR_RO(min_password_length); 478 479 static ssize_t max_password_length_show(struct kobject *kobj, struct kobj_attribute *attr, 480 char *buf) 481 { 482 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 483 484 return sysfs_emit(buf, "%d\n", setting->maxlen); 485 } 486 static struct kobj_attribute auth_max_pass_length = __ATTR_RO(max_password_length); 487 488 static ssize_t mechanism_show(struct kobject *kobj, struct kobj_attribute *attr, 489 char *buf) 490 { 491 return sysfs_emit(buf, "password\n"); 492 } 493 static struct kobj_attribute auth_mechanism = __ATTR_RO(mechanism); 494 495 static ssize_t encoding_show(struct kobject *kobj, struct kobj_attribute *attr, 496 char *buf) 497 { 498 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 499 500 return sysfs_emit(buf, "%s\n", encoding_options[setting->encoding]); 501 } 502 503 static ssize_t encoding_store(struct kobject *kobj, 504 struct kobj_attribute *attr, 505 const char *buf, size_t count) 506 { 507 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 508 int i; 509 510 /* Scan for a matching profile */ 511 i = sysfs_match_string(encoding_options, buf); 512 if (i < 0) 513 return -EINVAL; 514 515 setting->encoding = i; 516 return count; 517 } 518 519 static struct kobj_attribute auth_encoding = __ATTR_RW(encoding); 520 521 static ssize_t kbdlang_show(struct kobject *kobj, struct kobj_attribute *attr, 522 char *buf) 523 { 524 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 525 526 return sysfs_emit(buf, "%s\n", setting->kbdlang); 527 } 528 529 static ssize_t kbdlang_store(struct kobject *kobj, 530 struct kobj_attribute *attr, 531 const char *buf, size_t count) 532 { 533 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 534 int length; 535 536 /* Calculate length till '\n' or terminating 0 */ 537 length = strchrnul(buf, '\n') - buf; 538 if (!length || length >= TLMI_LANG_MAXLEN) 539 return -EINVAL; 540 541 memcpy(setting->kbdlang, buf, length); 542 setting->kbdlang[length] = '\0'; 543 return count; 544 } 545 546 static struct kobj_attribute auth_kbdlang = __ATTR_RW(kbdlang); 547 548 static ssize_t role_show(struct kobject *kobj, struct kobj_attribute *attr, 549 char *buf) 550 { 551 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 552 553 return sysfs_emit(buf, "%s\n", setting->role); 554 } 555 static struct kobj_attribute auth_role = __ATTR_RO(role); 556 557 static ssize_t index_show(struct kobject *kobj, struct kobj_attribute *attr, 558 char *buf) 559 { 560 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 561 562 return sysfs_emit(buf, "%d\n", setting->index); 563 } 564 565 static ssize_t index_store(struct kobject *kobj, 566 struct kobj_attribute *attr, 567 const char *buf, size_t count) 568 { 569 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 570 int err, val; 571 572 err = kstrtoint(buf, 10, &val); 573 if (err < 0) 574 return err; 575 576 if (val < 0 || val > TLMI_INDEX_MAX) 577 return -EINVAL; 578 579 setting->index = val; 580 return count; 581 } 582 583 static struct kobj_attribute auth_index = __ATTR_RW(index); 584 585 static ssize_t level_show(struct kobject *kobj, struct kobj_attribute *attr, 586 char *buf) 587 { 588 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 589 590 return sysfs_emit(buf, "%s\n", level_options[setting->level]); 591 } 592 593 static ssize_t level_store(struct kobject *kobj, 594 struct kobj_attribute *attr, 595 const char *buf, size_t count) 596 { 597 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 598 int i; 599 600 /* Scan for a matching profile */ 601 i = sysfs_match_string(level_options, buf); 602 if (i < 0) 603 return -EINVAL; 604 605 setting->level = i; 606 return count; 607 } 608 609 static struct kobj_attribute auth_level = __ATTR_RW(level); 610 611 static umode_t auth_attr_is_visible(struct kobject *kobj, 612 struct attribute *attr, int n) 613 { 614 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 615 616 /*We only want to display level and index settings on HDD/NVMe */ 617 if ((attr == (struct attribute *)&auth_index) || 618 (attr == (struct attribute *)&auth_level)) { 619 if ((setting == tlmi_priv.pwd_hdd) || (setting == tlmi_priv.pwd_nvme)) 620 return attr->mode; 621 return 0; 622 } 623 return attr->mode; 624 } 625 626 static struct attribute *auth_attrs[] = { 627 &auth_is_pass_set.attr, 628 &auth_min_pass_length.attr, 629 &auth_max_pass_length.attr, 630 &auth_current_password.attr, 631 &auth_new_password.attr, 632 &auth_role.attr, 633 &auth_mechanism.attr, 634 &auth_encoding.attr, 635 &auth_kbdlang.attr, 636 &auth_index.attr, 637 &auth_level.attr, 638 NULL 639 }; 640 641 static const struct attribute_group auth_attr_group = { 642 .is_visible = auth_attr_is_visible, 643 .attrs = auth_attrs, 644 }; 645 646 /* ---- Attributes sysfs --------------------------------------------------------- */ 647 static ssize_t display_name_show(struct kobject *kobj, struct kobj_attribute *attr, 648 char *buf) 649 { 650 struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj); 651 652 return sysfs_emit(buf, "%s\n", setting->display_name); 653 } 654 655 static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 656 { 657 struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj); 658 char *item, *value; 659 int ret; 660 661 ret = tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID); 662 if (ret) 663 return ret; 664 665 /* validate and split from `item,value` -> `value` */ 666 value = strpbrk(item, ","); 667 if (!value || value == item || !strlen(value + 1)) 668 return -EINVAL; 669 670 ret = sysfs_emit(buf, "%s\n", value + 1); 671 kfree(item); 672 return ret; 673 } 674 675 static ssize_t possible_values_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 676 { 677 struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj); 678 679 if (!tlmi_priv.can_get_bios_selections) 680 return -EOPNOTSUPP; 681 682 return sysfs_emit(buf, "%s\n", setting->possible_values); 683 } 684 685 static ssize_t current_value_store(struct kobject *kobj, 686 struct kobj_attribute *attr, 687 const char *buf, size_t count) 688 { 689 struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj); 690 char *set_str = NULL, *new_setting = NULL; 691 char *auth_str = NULL; 692 char *p; 693 int ret; 694 695 if (!tlmi_priv.can_set_bios_settings) 696 return -EOPNOTSUPP; 697 698 new_setting = kstrdup(buf, GFP_KERNEL); 699 if (!new_setting) 700 return -ENOMEM; 701 702 /* Strip out CR if one is present */ 703 p = strchrnul(new_setting, '\n'); 704 *p = '\0'; 705 706 if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { 707 auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;", 708 tlmi_priv.pwd_admin->password, 709 encoding_options[tlmi_priv.pwd_admin->encoding], 710 tlmi_priv.pwd_admin->kbdlang); 711 if (!auth_str) { 712 ret = -ENOMEM; 713 goto out; 714 } 715 } 716 717 if (auth_str) 718 set_str = kasprintf(GFP_KERNEL, "%s,%s,%s", setting->display_name, 719 new_setting, auth_str); 720 else 721 set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->display_name, 722 new_setting); 723 if (!set_str) { 724 ret = -ENOMEM; 725 goto out; 726 } 727 728 ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str); 729 if (ret) 730 goto out; 731 732 if (auth_str) 733 ret = tlmi_save_bios_settings(auth_str); 734 else 735 ret = tlmi_save_bios_settings(""); 736 737 if (!ret && !tlmi_priv.pending_changes) { 738 tlmi_priv.pending_changes = true; 739 /* let userland know it may need to check reboot pending again */ 740 kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE); 741 } 742 out: 743 kfree(auth_str); 744 kfree(set_str); 745 kfree(new_setting); 746 return ret ?: count; 747 } 748 749 static struct kobj_attribute attr_displ_name = __ATTR_RO(display_name); 750 751 static struct kobj_attribute attr_possible_values = __ATTR_RO(possible_values); 752 753 static struct kobj_attribute attr_current_val = __ATTR_RW_MODE(current_value, 0600); 754 755 static struct attribute *tlmi_attrs[] = { 756 &attr_displ_name.attr, 757 &attr_current_val.attr, 758 &attr_possible_values.attr, 759 NULL 760 }; 761 762 static const struct attribute_group tlmi_attr_group = { 763 .attrs = tlmi_attrs, 764 }; 765 766 static ssize_t tlmi_attr_show(struct kobject *kobj, struct attribute *attr, 767 char *buf) 768 { 769 struct kobj_attribute *kattr; 770 771 kattr = container_of(attr, struct kobj_attribute, attr); 772 if (kattr->show) 773 return kattr->show(kobj, kattr, buf); 774 return -EIO; 775 } 776 777 static ssize_t tlmi_attr_store(struct kobject *kobj, struct attribute *attr, 778 const char *buf, size_t count) 779 { 780 struct kobj_attribute *kattr; 781 782 kattr = container_of(attr, struct kobj_attribute, attr); 783 if (kattr->store) 784 return kattr->store(kobj, kattr, buf, count); 785 return -EIO; 786 } 787 788 static const struct sysfs_ops tlmi_kobj_sysfs_ops = { 789 .show = tlmi_attr_show, 790 .store = tlmi_attr_store, 791 }; 792 793 static void tlmi_attr_setting_release(struct kobject *kobj) 794 { 795 struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj); 796 797 kfree(setting->possible_values); 798 kfree(setting); 799 } 800 801 static void tlmi_pwd_setting_release(struct kobject *kobj) 802 { 803 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 804 805 kfree(setting); 806 } 807 808 static struct kobj_type tlmi_attr_setting_ktype = { 809 .release = &tlmi_attr_setting_release, 810 .sysfs_ops = &tlmi_kobj_sysfs_ops, 811 }; 812 813 static struct kobj_type tlmi_pwd_setting_ktype = { 814 .release = &tlmi_pwd_setting_release, 815 .sysfs_ops = &tlmi_kobj_sysfs_ops, 816 }; 817 818 static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *attr, 819 char *buf) 820 { 821 return sprintf(buf, "%d\n", tlmi_priv.pending_changes); 822 } 823 824 static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot); 825 826 /* ---- Debug interface--------------------------------------------------------- */ 827 static ssize_t debug_cmd_store(struct kobject *kobj, struct kobj_attribute *attr, 828 const char *buf, size_t count) 829 { 830 char *set_str = NULL, *new_setting = NULL; 831 char *auth_str = NULL; 832 char *p; 833 int ret; 834 835 if (!tlmi_priv.can_debug_cmd) 836 return -EOPNOTSUPP; 837 838 new_setting = kstrdup(buf, GFP_KERNEL); 839 if (!new_setting) 840 return -ENOMEM; 841 842 /* Strip out CR if one is present */ 843 p = strchrnul(new_setting, '\n'); 844 *p = '\0'; 845 846 if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { 847 auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;", 848 tlmi_priv.pwd_admin->password, 849 encoding_options[tlmi_priv.pwd_admin->encoding], 850 tlmi_priv.pwd_admin->kbdlang); 851 if (!auth_str) { 852 ret = -ENOMEM; 853 goto out; 854 } 855 } 856 857 if (auth_str) 858 set_str = kasprintf(GFP_KERNEL, "%s,%s", new_setting, auth_str); 859 else 860 set_str = kasprintf(GFP_KERNEL, "%s;", new_setting); 861 if (!set_str) { 862 ret = -ENOMEM; 863 goto out; 864 } 865 866 ret = tlmi_simple_call(LENOVO_DEBUG_CMD_GUID, set_str); 867 if (ret) 868 goto out; 869 870 if (!ret && !tlmi_priv.pending_changes) { 871 tlmi_priv.pending_changes = true; 872 /* let userland know it may need to check reboot pending again */ 873 kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE); 874 } 875 out: 876 kfree(auth_str); 877 kfree(set_str); 878 kfree(new_setting); 879 return ret ?: count; 880 } 881 882 static struct kobj_attribute debug_cmd = __ATTR_WO(debug_cmd); 883 884 /* ---- Initialisation --------------------------------------------------------- */ 885 static void tlmi_release_attr(void) 886 { 887 int i; 888 889 /* Attribute structures */ 890 for (i = 0; i < TLMI_SETTINGS_COUNT; i++) { 891 if (tlmi_priv.setting[i]) { 892 sysfs_remove_group(&tlmi_priv.setting[i]->kobj, &tlmi_attr_group); 893 kobject_put(&tlmi_priv.setting[i]->kobj); 894 } 895 } 896 sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr); 897 if (tlmi_priv.can_debug_cmd && debug_support) 898 sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr); 899 kset_unregister(tlmi_priv.attribute_kset); 900 901 /* Authentication structures */ 902 sysfs_remove_group(&tlmi_priv.pwd_admin->kobj, &auth_attr_group); 903 kobject_put(&tlmi_priv.pwd_admin->kobj); 904 sysfs_remove_group(&tlmi_priv.pwd_power->kobj, &auth_attr_group); 905 kobject_put(&tlmi_priv.pwd_power->kobj); 906 907 if (tlmi_priv.opcode_support) { 908 sysfs_remove_group(&tlmi_priv.pwd_system->kobj, &auth_attr_group); 909 kobject_put(&tlmi_priv.pwd_system->kobj); 910 sysfs_remove_group(&tlmi_priv.pwd_hdd->kobj, &auth_attr_group); 911 kobject_put(&tlmi_priv.pwd_hdd->kobj); 912 sysfs_remove_group(&tlmi_priv.pwd_nvme->kobj, &auth_attr_group); 913 kobject_put(&tlmi_priv.pwd_nvme->kobj); 914 } 915 916 kset_unregister(tlmi_priv.authentication_kset); 917 } 918 919 static int tlmi_sysfs_init(void) 920 { 921 int i, ret; 922 923 ret = fw_attributes_class_get(&fw_attr_class); 924 if (ret) 925 return ret; 926 927 tlmi_priv.class_dev = device_create(fw_attr_class, NULL, MKDEV(0, 0), 928 NULL, "%s", "thinklmi"); 929 if (IS_ERR(tlmi_priv.class_dev)) { 930 ret = PTR_ERR(tlmi_priv.class_dev); 931 goto fail_class_created; 932 } 933 934 tlmi_priv.attribute_kset = kset_create_and_add("attributes", NULL, 935 &tlmi_priv.class_dev->kobj); 936 if (!tlmi_priv.attribute_kset) { 937 ret = -ENOMEM; 938 goto fail_device_created; 939 } 940 941 for (i = 0; i < TLMI_SETTINGS_COUNT; i++) { 942 /* Check if index is a valid setting - skip if it isn't */ 943 if (!tlmi_priv.setting[i]) 944 continue; 945 946 /* check for duplicate or reserved values */ 947 if (kset_find_obj(tlmi_priv.attribute_kset, tlmi_priv.setting[i]->display_name) || 948 !strcmp(tlmi_priv.setting[i]->display_name, "Reserved")) { 949 pr_debug("duplicate or reserved attribute name found - %s\n", 950 tlmi_priv.setting[i]->display_name); 951 kfree(tlmi_priv.setting[i]->possible_values); 952 kfree(tlmi_priv.setting[i]); 953 tlmi_priv.setting[i] = NULL; 954 continue; 955 } 956 957 /* Build attribute */ 958 tlmi_priv.setting[i]->kobj.kset = tlmi_priv.attribute_kset; 959 ret = kobject_add(&tlmi_priv.setting[i]->kobj, NULL, 960 "%s", tlmi_priv.setting[i]->display_name); 961 if (ret) 962 goto fail_create_attr; 963 964 ret = sysfs_create_group(&tlmi_priv.setting[i]->kobj, &tlmi_attr_group); 965 if (ret) 966 goto fail_create_attr; 967 } 968 969 ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr); 970 if (ret) 971 goto fail_create_attr; 972 973 if (tlmi_priv.can_debug_cmd && debug_support) { 974 ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr); 975 if (ret) 976 goto fail_create_attr; 977 } 978 /* Create authentication entries */ 979 tlmi_priv.authentication_kset = kset_create_and_add("authentication", NULL, 980 &tlmi_priv.class_dev->kobj); 981 if (!tlmi_priv.authentication_kset) { 982 ret = -ENOMEM; 983 goto fail_create_attr; 984 } 985 tlmi_priv.pwd_admin->kobj.kset = tlmi_priv.authentication_kset; 986 ret = kobject_add(&tlmi_priv.pwd_admin->kobj, NULL, "%s", "Admin"); 987 if (ret) 988 goto fail_create_attr; 989 990 ret = sysfs_create_group(&tlmi_priv.pwd_admin->kobj, &auth_attr_group); 991 if (ret) 992 goto fail_create_attr; 993 994 tlmi_priv.pwd_power->kobj.kset = tlmi_priv.authentication_kset; 995 ret = kobject_add(&tlmi_priv.pwd_power->kobj, NULL, "%s", "Power-on"); 996 if (ret) 997 goto fail_create_attr; 998 999 ret = sysfs_create_group(&tlmi_priv.pwd_power->kobj, &auth_attr_group); 1000 if (ret) 1001 goto fail_create_attr; 1002 1003 if (tlmi_priv.opcode_support) { 1004 tlmi_priv.pwd_system->kobj.kset = tlmi_priv.authentication_kset; 1005 ret = kobject_add(&tlmi_priv.pwd_system->kobj, NULL, "%s", "System"); 1006 if (ret) 1007 goto fail_create_attr; 1008 1009 ret = sysfs_create_group(&tlmi_priv.pwd_system->kobj, &auth_attr_group); 1010 if (ret) 1011 goto fail_create_attr; 1012 1013 tlmi_priv.pwd_hdd->kobj.kset = tlmi_priv.authentication_kset; 1014 ret = kobject_add(&tlmi_priv.pwd_hdd->kobj, NULL, "%s", "HDD"); 1015 if (ret) 1016 goto fail_create_attr; 1017 1018 ret = sysfs_create_group(&tlmi_priv.pwd_hdd->kobj, &auth_attr_group); 1019 if (ret) 1020 goto fail_create_attr; 1021 1022 tlmi_priv.pwd_nvme->kobj.kset = tlmi_priv.authentication_kset; 1023 ret = kobject_add(&tlmi_priv.pwd_nvme->kobj, NULL, "%s", "NVMe"); 1024 if (ret) 1025 goto fail_create_attr; 1026 1027 ret = sysfs_create_group(&tlmi_priv.pwd_nvme->kobj, &auth_attr_group); 1028 if (ret) 1029 goto fail_create_attr; 1030 } 1031 1032 return ret; 1033 1034 fail_create_attr: 1035 tlmi_release_attr(); 1036 fail_device_created: 1037 device_destroy(fw_attr_class, MKDEV(0, 0)); 1038 fail_class_created: 1039 fw_attributes_class_put(); 1040 return ret; 1041 } 1042 1043 /* ---- Base Driver -------------------------------------------------------- */ 1044 static struct tlmi_pwd_setting *tlmi_create_auth(const char *pwd_type, 1045 const char *pwd_role) 1046 { 1047 struct tlmi_pwd_setting *new_pwd; 1048 1049 new_pwd = kzalloc(sizeof(struct tlmi_pwd_setting), GFP_KERNEL); 1050 if (!new_pwd) 1051 return NULL; 1052 1053 strscpy(new_pwd->kbdlang, "us", TLMI_LANG_MAXLEN); 1054 new_pwd->encoding = TLMI_ENCODING_ASCII; 1055 new_pwd->pwd_type = pwd_type; 1056 new_pwd->role = pwd_role; 1057 new_pwd->minlen = tlmi_priv.pwdcfg.core.min_length; 1058 new_pwd->maxlen = tlmi_priv.pwdcfg.core.max_length; 1059 new_pwd->index = 0; 1060 1061 kobject_init(&new_pwd->kobj, &tlmi_pwd_setting_ktype); 1062 1063 return new_pwd; 1064 } 1065 1066 static int tlmi_analyze(void) 1067 { 1068 acpi_status status; 1069 int i, ret; 1070 1071 if (wmi_has_guid(LENOVO_SET_BIOS_SETTINGS_GUID) && 1072 wmi_has_guid(LENOVO_SAVE_BIOS_SETTINGS_GUID)) 1073 tlmi_priv.can_set_bios_settings = true; 1074 1075 if (wmi_has_guid(LENOVO_GET_BIOS_SELECTIONS_GUID)) 1076 tlmi_priv.can_get_bios_selections = true; 1077 1078 if (wmi_has_guid(LENOVO_SET_BIOS_PASSWORD_GUID)) 1079 tlmi_priv.can_set_bios_password = true; 1080 1081 if (wmi_has_guid(LENOVO_BIOS_PASSWORD_SETTINGS_GUID)) 1082 tlmi_priv.can_get_password_settings = true; 1083 1084 if (wmi_has_guid(LENOVO_DEBUG_CMD_GUID)) 1085 tlmi_priv.can_debug_cmd = true; 1086 1087 if (wmi_has_guid(LENOVO_OPCODE_IF_GUID)) 1088 tlmi_priv.opcode_support = true; 1089 1090 /* 1091 * Try to find the number of valid settings of this machine 1092 * and use it to create sysfs attributes. 1093 */ 1094 for (i = 0; i < TLMI_SETTINGS_COUNT; ++i) { 1095 struct tlmi_attr_setting *setting; 1096 char *item = NULL; 1097 char *p; 1098 1099 tlmi_priv.setting[i] = NULL; 1100 status = tlmi_setting(i, &item, LENOVO_BIOS_SETTING_GUID); 1101 if (ACPI_FAILURE(status)) 1102 break; 1103 if (!item) 1104 break; 1105 if (!*item) { 1106 kfree(item); 1107 continue; 1108 } 1109 1110 /* It is not allowed to have '/' for file name. Convert it into '\'. */ 1111 strreplace(item, '/', '\\'); 1112 1113 /* Remove the value part */ 1114 p = strchrnul(item, ','); 1115 *p = '\0'; 1116 1117 /* Create a setting entry */ 1118 setting = kzalloc(sizeof(*setting), GFP_KERNEL); 1119 if (!setting) { 1120 ret = -ENOMEM; 1121 kfree(item); 1122 goto fail_clear_attr; 1123 } 1124 setting->index = i; 1125 strscpy(setting->display_name, item, TLMI_SETTINGS_MAXLEN); 1126 /* If BIOS selections supported, load those */ 1127 if (tlmi_priv.can_get_bios_selections) { 1128 ret = tlmi_get_bios_selections(setting->display_name, 1129 &setting->possible_values); 1130 if (ret || !setting->possible_values) 1131 pr_info("Error retrieving possible values for %d : %s\n", 1132 i, setting->display_name); 1133 } 1134 kobject_init(&setting->kobj, &tlmi_attr_setting_ktype); 1135 tlmi_priv.setting[i] = setting; 1136 kfree(item); 1137 } 1138 1139 /* Create password setting structure */ 1140 ret = tlmi_get_pwd_settings(&tlmi_priv.pwdcfg); 1141 if (ret) 1142 goto fail_clear_attr; 1143 1144 /* All failures below boil down to kmalloc failures */ 1145 ret = -ENOMEM; 1146 1147 tlmi_priv.pwd_admin = tlmi_create_auth("pap", "bios-admin"); 1148 if (!tlmi_priv.pwd_admin) 1149 goto fail_clear_attr; 1150 1151 if (tlmi_priv.pwdcfg.core.password_state & TLMI_PAP_PWD) 1152 tlmi_priv.pwd_admin->valid = true; 1153 1154 tlmi_priv.pwd_power = tlmi_create_auth("pop", "power-on"); 1155 if (!tlmi_priv.pwd_power) 1156 goto fail_clear_attr; 1157 1158 if (tlmi_priv.pwdcfg.core.password_state & TLMI_POP_PWD) 1159 tlmi_priv.pwd_power->valid = true; 1160 1161 if (tlmi_priv.opcode_support) { 1162 tlmi_priv.pwd_system = tlmi_create_auth("sys", "system"); 1163 if (!tlmi_priv.pwd_system) 1164 goto fail_clear_attr; 1165 1166 if (tlmi_priv.pwdcfg.core.password_state & TLMI_SYS_PWD) 1167 tlmi_priv.pwd_system->valid = true; 1168 1169 tlmi_priv.pwd_hdd = tlmi_create_auth("hdd", "hdd"); 1170 if (!tlmi_priv.pwd_hdd) 1171 goto fail_clear_attr; 1172 1173 tlmi_priv.pwd_nvme = tlmi_create_auth("nvm", "nvme"); 1174 if (!tlmi_priv.pwd_nvme) 1175 goto fail_clear_attr; 1176 1177 if (tlmi_priv.pwdcfg.core.password_state & TLMI_HDD_PWD) { 1178 /* Check if PWD is configured and set index to first drive found */ 1179 if (tlmi_priv.pwdcfg.ext.hdd_user_password || 1180 tlmi_priv.pwdcfg.ext.hdd_master_password) { 1181 tlmi_priv.pwd_hdd->valid = true; 1182 if (tlmi_priv.pwdcfg.ext.hdd_master_password) 1183 tlmi_priv.pwd_hdd->index = 1184 ffs(tlmi_priv.pwdcfg.ext.hdd_master_password) - 1; 1185 else 1186 tlmi_priv.pwd_hdd->index = 1187 ffs(tlmi_priv.pwdcfg.ext.hdd_user_password) - 1; 1188 } 1189 if (tlmi_priv.pwdcfg.ext.nvme_user_password || 1190 tlmi_priv.pwdcfg.ext.nvme_master_password) { 1191 tlmi_priv.pwd_nvme->valid = true; 1192 if (tlmi_priv.pwdcfg.ext.nvme_master_password) 1193 tlmi_priv.pwd_nvme->index = 1194 ffs(tlmi_priv.pwdcfg.ext.nvme_master_password) - 1; 1195 else 1196 tlmi_priv.pwd_nvme->index = 1197 ffs(tlmi_priv.pwdcfg.ext.nvme_user_password) - 1; 1198 } 1199 } 1200 } 1201 return 0; 1202 1203 fail_clear_attr: 1204 for (i = 0; i < TLMI_SETTINGS_COUNT; ++i) { 1205 if (tlmi_priv.setting[i]) { 1206 kfree(tlmi_priv.setting[i]->possible_values); 1207 kfree(tlmi_priv.setting[i]); 1208 } 1209 } 1210 kfree(tlmi_priv.pwd_admin); 1211 kfree(tlmi_priv.pwd_power); 1212 kfree(tlmi_priv.pwd_system); 1213 kfree(tlmi_priv.pwd_hdd); 1214 kfree(tlmi_priv.pwd_nvme); 1215 return ret; 1216 } 1217 1218 static void tlmi_remove(struct wmi_device *wdev) 1219 { 1220 tlmi_release_attr(); 1221 device_destroy(fw_attr_class, MKDEV(0, 0)); 1222 fw_attributes_class_put(); 1223 } 1224 1225 static int tlmi_probe(struct wmi_device *wdev, const void *context) 1226 { 1227 int ret; 1228 1229 ret = tlmi_analyze(); 1230 if (ret) 1231 return ret; 1232 1233 return tlmi_sysfs_init(); 1234 } 1235 1236 static const struct wmi_device_id tlmi_id_table[] = { 1237 { .guid_string = LENOVO_BIOS_SETTING_GUID }, 1238 { } 1239 }; 1240 MODULE_DEVICE_TABLE(wmi, tlmi_id_table); 1241 1242 static struct wmi_driver tlmi_driver = { 1243 .driver = { 1244 .name = "think-lmi", 1245 }, 1246 .id_table = tlmi_id_table, 1247 .probe = tlmi_probe, 1248 .remove = tlmi_remove, 1249 }; 1250 1251 MODULE_AUTHOR("Sugumaran L <slacshiminar@lenovo.com>"); 1252 MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>"); 1253 MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>"); 1254 MODULE_DESCRIPTION("ThinkLMI Driver"); 1255 MODULE_LICENSE("GPL"); 1256 1257 module_wmi_driver(tlmi_driver); 1258