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 /* 24 * Name: 25 * Lenovo_BiosSetting 26 * Description: 27 * Get item name and settings for current LMI instance. 28 * Type: 29 * Query 30 * Returns: 31 * "Item,Value" 32 * Example: 33 * "WakeOnLAN,Enable" 34 */ 35 #define LENOVO_BIOS_SETTING_GUID "51F5230E-9677-46CD-A1CF-C0B23EE34DB7" 36 37 /* 38 * Name: 39 * Lenovo_SetBiosSetting 40 * Description: 41 * Change the BIOS setting to the desired value using the Lenovo_SetBiosSetting 42 * class. To save the settings, use the Lenovo_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: 47 * Method 48 * Arguments: 49 * "Item,Value,Password,Encoding,KbdLang;" 50 * Example: 51 * "WakeOnLAN,Disable,pa55w0rd,ascii,us;" 52 */ 53 #define LENOVO_SET_BIOS_SETTINGS_GUID "98479A64-33F5-4E33-A707-8E251EBBC3A1" 54 55 /* 56 * Name: 57 * Lenovo_SaveBiosSettings 58 * Description: 59 * Save any pending changes in settings. 60 * Type: 61 * Method 62 * Arguments: 63 * "Password,Encoding,KbdLang;" 64 * Example: 65 * "pa55w0rd,ascii,us;" 66 */ 67 #define LENOVO_SAVE_BIOS_SETTINGS_GUID "6A4B54EF-A5ED-4D33-9455-B0D9B48DF4B3" 68 69 /* 70 * Name: 71 * Lenovo_BiosPasswordSettings 72 * Description: 73 * Return BIOS Password settings 74 * Type: 75 * Query 76 * Returns: 77 * PasswordMode, PasswordState, MinLength, MaxLength, 78 * SupportedEncoding, SupportedKeyboard 79 */ 80 #define LENOVO_BIOS_PASSWORD_SETTINGS_GUID "8ADB159E-1E32-455C-BC93-308A7ED98246" 81 82 /* 83 * Name: 84 * Lenovo_SetBiosPassword 85 * Description: 86 * Change a specific password. 87 * - BIOS settings cannot be changed at the same boot as power-on 88 * passwords (POP) and hard disk passwords (HDP). If you want to change 89 * BIOS settings and POP or HDP, you must reboot the system after changing 90 * one of them. 91 * - A password cannot be set using this method when one does not already 92 * exist. Passwords can only be updated or cleared. 93 * Type: 94 * Method 95 * Arguments: 96 * "PasswordType,CurrentPassword,NewPassword,Encoding,KbdLang;" 97 * Example: 98 * "pop,pa55w0rd,newpa55w0rd,ascii,us;” 99 */ 100 #define LENOVO_SET_BIOS_PASSWORD_GUID "2651D9FD-911C-4B69-B94E-D0DED5963BD7" 101 102 /* 103 * Name: 104 * Lenovo_GetBiosSelections 105 * Description: 106 * Return a list of valid settings for a given item. 107 * Type: 108 * Method 109 * Arguments: 110 * "Item" 111 * Returns: 112 * "Value1,Value2,Value3,..." 113 * Example: 114 * -> "FlashOverLAN" 115 * <- "Enabled,Disabled" 116 */ 117 #define LENOVO_GET_BIOS_SELECTIONS_GUID "7364651A-132F-4FE7-ADAA-40C6C7EE2E3B" 118 119 #define TLMI_POP_PWD (1 << 0) 120 #define TLMI_PAP_PWD (1 << 1) 121 #define to_tlmi_pwd_setting(kobj) container_of(kobj, struct tlmi_pwd_setting, kobj) 122 #define to_tlmi_attr_setting(kobj) container_of(kobj, struct tlmi_attr_setting, kobj) 123 124 static const struct tlmi_err_codes tlmi_errs[] = { 125 {"Success", 0}, 126 {"Not Supported", -EOPNOTSUPP}, 127 {"Invalid Parameter", -EINVAL}, 128 {"Access Denied", -EACCES}, 129 {"System Busy", -EBUSY}, 130 }; 131 132 static const char * const encoding_options[] = { 133 [TLMI_ENCODING_ASCII] = "ascii", 134 [TLMI_ENCODING_SCANCODE] = "scancode", 135 }; 136 static struct think_lmi tlmi_priv; 137 static struct class *fw_attr_class; 138 139 /* ------ Utility functions ------------*/ 140 /* Convert BIOS WMI error string to suitable error code */ 141 static int tlmi_errstr_to_err(const char *errstr) 142 { 143 int i; 144 145 for (i = 0; i < sizeof(tlmi_errs)/sizeof(struct tlmi_err_codes); i++) { 146 if (!strcmp(tlmi_errs[i].err_str, errstr)) 147 return tlmi_errs[i].err_code; 148 } 149 return -EPERM; 150 } 151 152 /* Extract error string from WMI return buffer */ 153 static int tlmi_extract_error(const struct acpi_buffer *output) 154 { 155 const union acpi_object *obj; 156 157 obj = output->pointer; 158 if (!obj) 159 return -ENOMEM; 160 if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer) 161 return -EIO; 162 163 return tlmi_errstr_to_err(obj->string.pointer); 164 } 165 166 /* Utility function to execute WMI call to BIOS */ 167 static int tlmi_simple_call(const char *guid, const char *arg) 168 { 169 const struct acpi_buffer input = { strlen(arg), (char *)arg }; 170 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 171 acpi_status status; 172 int i, err; 173 174 /* 175 * Duplicated call required to match BIOS workaround for behavior 176 * seen when WMI accessed via scripting on other OS. 177 */ 178 for (i = 0; i < 2; i++) { 179 /* (re)initialize output buffer to default state */ 180 output.length = ACPI_ALLOCATE_BUFFER; 181 output.pointer = NULL; 182 183 status = wmi_evaluate_method(guid, 0, 0, &input, &output); 184 if (ACPI_FAILURE(status)) { 185 kfree(output.pointer); 186 return -EIO; 187 } 188 err = tlmi_extract_error(&output); 189 kfree(output.pointer); 190 if (err) 191 return err; 192 } 193 return 0; 194 } 195 196 /* Extract output string from WMI return buffer */ 197 static int tlmi_extract_output_string(const struct acpi_buffer *output, 198 char **string) 199 { 200 const union acpi_object *obj; 201 char *s; 202 203 obj = output->pointer; 204 if (!obj) 205 return -ENOMEM; 206 if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer) 207 return -EIO; 208 209 s = kstrdup(obj->string.pointer, GFP_KERNEL); 210 if (!s) 211 return -ENOMEM; 212 *string = s; 213 return 0; 214 } 215 216 /* ------ Core interface functions ------------*/ 217 218 /* Get password settings from BIOS */ 219 static int tlmi_get_pwd_settings(struct tlmi_pwdcfg *pwdcfg) 220 { 221 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 222 const union acpi_object *obj; 223 acpi_status status; 224 225 if (!tlmi_priv.can_get_password_settings) 226 return -EOPNOTSUPP; 227 228 status = wmi_query_block(LENOVO_BIOS_PASSWORD_SETTINGS_GUID, 0, 229 &output); 230 if (ACPI_FAILURE(status)) 231 return -EIO; 232 233 obj = output.pointer; 234 if (!obj) 235 return -ENOMEM; 236 if (obj->type != ACPI_TYPE_BUFFER || !obj->buffer.pointer) { 237 kfree(obj); 238 return -EIO; 239 } 240 /* 241 * The size of thinkpad_wmi_pcfg on ThinkStation is larger than ThinkPad. 242 * To make the driver compatible on different brands, we permit it to get 243 * the data in below case. 244 */ 245 if (obj->buffer.length < sizeof(struct tlmi_pwdcfg)) { 246 pr_warn("Unknown pwdcfg buffer length %d\n", obj->buffer.length); 247 kfree(obj); 248 return -EIO; 249 } 250 memcpy(pwdcfg, obj->buffer.pointer, sizeof(struct tlmi_pwdcfg)); 251 kfree(obj); 252 return 0; 253 } 254 255 static int tlmi_save_bios_settings(const char *password) 256 { 257 return tlmi_simple_call(LENOVO_SAVE_BIOS_SETTINGS_GUID, 258 password); 259 } 260 261 static int tlmi_setting(int item, char **value, const char *guid_string) 262 { 263 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 264 acpi_status status; 265 int ret; 266 267 status = wmi_query_block(guid_string, item, &output); 268 if (ACPI_FAILURE(status)) { 269 kfree(output.pointer); 270 return -EIO; 271 } 272 273 ret = tlmi_extract_output_string(&output, value); 274 kfree(output.pointer); 275 return ret; 276 } 277 278 static int tlmi_get_bios_selections(const char *item, char **value) 279 { 280 const struct acpi_buffer input = { strlen(item), (char *)item }; 281 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 282 acpi_status status; 283 int ret; 284 285 status = wmi_evaluate_method(LENOVO_GET_BIOS_SELECTIONS_GUID, 286 0, 0, &input, &output); 287 288 if (ACPI_FAILURE(status)) { 289 kfree(output.pointer); 290 return -EIO; 291 } 292 293 ret = tlmi_extract_output_string(&output, value); 294 kfree(output.pointer); 295 return ret; 296 } 297 298 /* ---- Authentication sysfs --------------------------------------------------------- */ 299 static ssize_t is_enabled_show(struct kobject *kobj, struct kobj_attribute *attr, 300 char *buf) 301 { 302 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 303 304 return sysfs_emit(buf, "%d\n", setting->valid); 305 } 306 307 static struct kobj_attribute auth_is_pass_set = __ATTR_RO(is_enabled); 308 309 static ssize_t current_password_store(struct kobject *kobj, 310 struct kobj_attribute *attr, 311 const char *buf, size_t count) 312 { 313 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 314 size_t pwdlen; 315 char *p; 316 317 pwdlen = strlen(buf); 318 /* pwdlen == 0 is allowed to clear the password */ 319 if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) 320 return -EINVAL; 321 322 strscpy(setting->password, buf, setting->maxlen); 323 /* Strip out CR if one is present, setting password won't work if it is present */ 324 p = strchrnul(setting->password, '\n'); 325 *p = '\0'; 326 return count; 327 } 328 329 static struct kobj_attribute auth_current_password = __ATTR_WO(current_password); 330 331 static ssize_t new_password_store(struct kobject *kobj, 332 struct kobj_attribute *attr, 333 const char *buf, size_t count) 334 { 335 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 336 char *auth_str, *new_pwd, *p; 337 size_t pwdlen; 338 int ret; 339 340 if (!capable(CAP_SYS_ADMIN)) 341 return -EPERM; 342 343 if (!tlmi_priv.can_set_bios_password) 344 return -EOPNOTSUPP; 345 346 new_pwd = kstrdup(buf, GFP_KERNEL); 347 if (!new_pwd) 348 return -ENOMEM; 349 350 /* Strip out CR if one is present, setting password won't work if it is present */ 351 p = strchrnul(new_pwd, '\n'); 352 *p = '\0'; 353 354 pwdlen = strlen(new_pwd); 355 /* pwdlen == 0 is allowed to clear the password */ 356 if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) { 357 ret = -EINVAL; 358 goto out; 359 } 360 361 /* Format: 'PasswordType,CurrentPw,NewPw,Encoding,KbdLang;' */ 362 auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s,%s,%s;", 363 setting->pwd_type, setting->password, new_pwd, 364 encoding_options[setting->encoding], setting->kbdlang); 365 if (!auth_str) { 366 ret = -ENOMEM; 367 goto out; 368 } 369 ret = tlmi_simple_call(LENOVO_SET_BIOS_PASSWORD_GUID, auth_str); 370 kfree(auth_str); 371 out: 372 kfree(new_pwd); 373 return ret ?: count; 374 } 375 376 static struct kobj_attribute auth_new_password = __ATTR_WO(new_password); 377 378 static ssize_t min_password_length_show(struct kobject *kobj, struct kobj_attribute *attr, 379 char *buf) 380 { 381 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 382 383 return sysfs_emit(buf, "%d\n", setting->minlen); 384 } 385 386 static struct kobj_attribute auth_min_pass_length = __ATTR_RO(min_password_length); 387 388 static ssize_t max_password_length_show(struct kobject *kobj, struct kobj_attribute *attr, 389 char *buf) 390 { 391 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 392 393 return sysfs_emit(buf, "%d\n", setting->maxlen); 394 } 395 static struct kobj_attribute auth_max_pass_length = __ATTR_RO(max_password_length); 396 397 static ssize_t mechanism_show(struct kobject *kobj, struct kobj_attribute *attr, 398 char *buf) 399 { 400 return sysfs_emit(buf, "password\n"); 401 } 402 static struct kobj_attribute auth_mechanism = __ATTR_RO(mechanism); 403 404 static ssize_t encoding_show(struct kobject *kobj, struct kobj_attribute *attr, 405 char *buf) 406 { 407 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 408 409 return sysfs_emit(buf, "%s\n", encoding_options[setting->encoding]); 410 } 411 412 static ssize_t encoding_store(struct kobject *kobj, 413 struct kobj_attribute *attr, 414 const char *buf, size_t count) 415 { 416 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 417 int i; 418 419 /* Scan for a matching profile */ 420 i = sysfs_match_string(encoding_options, buf); 421 if (i < 0) 422 return -EINVAL; 423 424 setting->encoding = i; 425 return count; 426 } 427 428 static struct kobj_attribute auth_encoding = __ATTR_RW(encoding); 429 430 static ssize_t kbdlang_show(struct kobject *kobj, struct kobj_attribute *attr, 431 char *buf) 432 { 433 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 434 435 return sysfs_emit(buf, "%s\n", setting->kbdlang); 436 } 437 438 static ssize_t kbdlang_store(struct kobject *kobj, 439 struct kobj_attribute *attr, 440 const char *buf, size_t count) 441 { 442 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 443 int length; 444 445 /* Calculate length till '\n' or terminating 0 */ 446 length = strchrnul(buf, '\n') - buf; 447 if (!length || length >= TLMI_LANG_MAXLEN) 448 return -EINVAL; 449 450 memcpy(setting->kbdlang, buf, length); 451 setting->kbdlang[length] = '\0'; 452 return count; 453 } 454 455 static struct kobj_attribute auth_kbdlang = __ATTR_RW(kbdlang); 456 457 static ssize_t role_show(struct kobject *kobj, struct kobj_attribute *attr, 458 char *buf) 459 { 460 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 461 462 return sysfs_emit(buf, "%s\n", setting->role); 463 } 464 static struct kobj_attribute auth_role = __ATTR_RO(role); 465 466 static struct attribute *auth_attrs[] = { 467 &auth_is_pass_set.attr, 468 &auth_min_pass_length.attr, 469 &auth_max_pass_length.attr, 470 &auth_current_password.attr, 471 &auth_new_password.attr, 472 &auth_role.attr, 473 &auth_mechanism.attr, 474 &auth_encoding.attr, 475 &auth_kbdlang.attr, 476 NULL 477 }; 478 479 static const struct attribute_group auth_attr_group = { 480 .attrs = auth_attrs, 481 }; 482 483 /* ---- Attributes sysfs --------------------------------------------------------- */ 484 static ssize_t display_name_show(struct kobject *kobj, struct kobj_attribute *attr, 485 char *buf) 486 { 487 struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj); 488 489 return sysfs_emit(buf, "%s\n", setting->display_name); 490 } 491 492 static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 493 { 494 struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj); 495 char *item, *value; 496 int ret; 497 498 ret = tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID); 499 if (ret) 500 return ret; 501 502 /* validate and split from `item,value` -> `value` */ 503 value = strpbrk(item, ","); 504 if (!value || value == item || !strlen(value + 1)) 505 return -EINVAL; 506 507 ret = sysfs_emit(buf, "%s\n", value + 1); 508 kfree(item); 509 return ret; 510 } 511 512 static ssize_t possible_values_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 513 { 514 struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj); 515 516 if (!tlmi_priv.can_get_bios_selections) 517 return -EOPNOTSUPP; 518 519 return sysfs_emit(buf, "%s\n", setting->possible_values); 520 } 521 522 static ssize_t current_value_store(struct kobject *kobj, 523 struct kobj_attribute *attr, 524 const char *buf, size_t count) 525 { 526 struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj); 527 char *set_str = NULL, *new_setting = NULL; 528 char *auth_str = NULL; 529 char *p; 530 int ret; 531 532 if (!tlmi_priv.can_set_bios_settings) 533 return -EOPNOTSUPP; 534 535 new_setting = kstrdup(buf, GFP_KERNEL); 536 if (!new_setting) 537 return -ENOMEM; 538 539 /* Strip out CR if one is present */ 540 p = strchrnul(new_setting, '\n'); 541 *p = '\0'; 542 543 if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { 544 auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;", 545 tlmi_priv.pwd_admin->password, 546 encoding_options[tlmi_priv.pwd_admin->encoding], 547 tlmi_priv.pwd_admin->kbdlang); 548 if (!auth_str) { 549 ret = -ENOMEM; 550 goto out; 551 } 552 } 553 554 if (auth_str) 555 set_str = kasprintf(GFP_KERNEL, "%s,%s,%s", setting->display_name, 556 new_setting, auth_str); 557 else 558 set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->display_name, 559 new_setting); 560 if (!set_str) { 561 ret = -ENOMEM; 562 goto out; 563 } 564 565 ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str); 566 if (ret) 567 goto out; 568 569 if (auth_str) 570 ret = tlmi_save_bios_settings(auth_str); 571 else 572 ret = tlmi_save_bios_settings(""); 573 574 if (!ret && !tlmi_priv.pending_changes) { 575 tlmi_priv.pending_changes = true; 576 /* let userland know it may need to check reboot pending again */ 577 kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE); 578 } 579 out: 580 kfree(auth_str); 581 kfree(set_str); 582 kfree(new_setting); 583 return ret ?: count; 584 } 585 586 static struct kobj_attribute attr_displ_name = __ATTR_RO(display_name); 587 588 static struct kobj_attribute attr_possible_values = __ATTR_RO(possible_values); 589 590 static struct kobj_attribute attr_current_val = __ATTR_RW_MODE(current_value, 0600); 591 592 static struct attribute *tlmi_attrs[] = { 593 &attr_displ_name.attr, 594 &attr_current_val.attr, 595 &attr_possible_values.attr, 596 NULL 597 }; 598 599 static const struct attribute_group tlmi_attr_group = { 600 .attrs = tlmi_attrs, 601 }; 602 603 static ssize_t tlmi_attr_show(struct kobject *kobj, struct attribute *attr, 604 char *buf) 605 { 606 struct kobj_attribute *kattr; 607 608 kattr = container_of(attr, struct kobj_attribute, attr); 609 if (kattr->show) 610 return kattr->show(kobj, kattr, buf); 611 return -EIO; 612 } 613 614 static ssize_t tlmi_attr_store(struct kobject *kobj, struct attribute *attr, 615 const char *buf, size_t count) 616 { 617 struct kobj_attribute *kattr; 618 619 kattr = container_of(attr, struct kobj_attribute, attr); 620 if (kattr->store) 621 return kattr->store(kobj, kattr, buf, count); 622 return -EIO; 623 } 624 625 static const struct sysfs_ops tlmi_kobj_sysfs_ops = { 626 .show = tlmi_attr_show, 627 .store = tlmi_attr_store, 628 }; 629 630 static void tlmi_attr_setting_release(struct kobject *kobj) 631 { 632 struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj); 633 634 kfree(setting->possible_values); 635 kfree(setting); 636 } 637 638 static void tlmi_pwd_setting_release(struct kobject *kobj) 639 { 640 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 641 642 kfree(setting); 643 } 644 645 static struct kobj_type tlmi_attr_setting_ktype = { 646 .release = &tlmi_attr_setting_release, 647 .sysfs_ops = &tlmi_kobj_sysfs_ops, 648 }; 649 650 static struct kobj_type tlmi_pwd_setting_ktype = { 651 .release = &tlmi_pwd_setting_release, 652 .sysfs_ops = &tlmi_kobj_sysfs_ops, 653 }; 654 655 static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *attr, 656 char *buf) 657 { 658 return sprintf(buf, "%d\n", tlmi_priv.pending_changes); 659 } 660 661 static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot); 662 663 /* ---- Initialisation --------------------------------------------------------- */ 664 static void tlmi_release_attr(void) 665 { 666 int i; 667 668 /* Attribute structures */ 669 for (i = 0; i < TLMI_SETTINGS_COUNT; i++) { 670 if (tlmi_priv.setting[i]) { 671 sysfs_remove_group(&tlmi_priv.setting[i]->kobj, &tlmi_attr_group); 672 kobject_put(&tlmi_priv.setting[i]->kobj); 673 } 674 } 675 sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr); 676 kset_unregister(tlmi_priv.attribute_kset); 677 678 /* Authentication structures */ 679 sysfs_remove_group(&tlmi_priv.pwd_admin->kobj, &auth_attr_group); 680 kobject_put(&tlmi_priv.pwd_admin->kobj); 681 sysfs_remove_group(&tlmi_priv.pwd_power->kobj, &auth_attr_group); 682 kobject_put(&tlmi_priv.pwd_power->kobj); 683 kset_unregister(tlmi_priv.authentication_kset); 684 } 685 686 static int tlmi_sysfs_init(void) 687 { 688 int i, ret; 689 690 ret = fw_attributes_class_get(&fw_attr_class); 691 if (ret) 692 return ret; 693 694 tlmi_priv.class_dev = device_create(fw_attr_class, NULL, MKDEV(0, 0), 695 NULL, "%s", "thinklmi"); 696 if (IS_ERR(tlmi_priv.class_dev)) { 697 ret = PTR_ERR(tlmi_priv.class_dev); 698 goto fail_class_created; 699 } 700 701 tlmi_priv.attribute_kset = kset_create_and_add("attributes", NULL, 702 &tlmi_priv.class_dev->kobj); 703 if (!tlmi_priv.attribute_kset) { 704 ret = -ENOMEM; 705 goto fail_device_created; 706 } 707 708 for (i = 0; i < TLMI_SETTINGS_COUNT; i++) { 709 /* Check if index is a valid setting - skip if it isn't */ 710 if (!tlmi_priv.setting[i]) 711 continue; 712 713 /* check for duplicate or reserved values */ 714 if (kset_find_obj(tlmi_priv.attribute_kset, tlmi_priv.setting[i]->display_name) || 715 !strcmp(tlmi_priv.setting[i]->display_name, "Reserved")) { 716 pr_debug("duplicate or reserved attribute name found - %s\n", 717 tlmi_priv.setting[i]->display_name); 718 kfree(tlmi_priv.setting[i]->possible_values); 719 kfree(tlmi_priv.setting[i]); 720 tlmi_priv.setting[i] = NULL; 721 continue; 722 } 723 724 /* Build attribute */ 725 tlmi_priv.setting[i]->kobj.kset = tlmi_priv.attribute_kset; 726 ret = kobject_add(&tlmi_priv.setting[i]->kobj, NULL, 727 "%s", tlmi_priv.setting[i]->display_name); 728 if (ret) 729 goto fail_create_attr; 730 731 ret = sysfs_create_group(&tlmi_priv.setting[i]->kobj, &tlmi_attr_group); 732 if (ret) 733 goto fail_create_attr; 734 } 735 736 ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr); 737 if (ret) 738 goto fail_create_attr; 739 740 /* Create authentication entries */ 741 tlmi_priv.authentication_kset = kset_create_and_add("authentication", NULL, 742 &tlmi_priv.class_dev->kobj); 743 if (!tlmi_priv.authentication_kset) { 744 ret = -ENOMEM; 745 goto fail_create_attr; 746 } 747 tlmi_priv.pwd_admin->kobj.kset = tlmi_priv.authentication_kset; 748 ret = kobject_add(&tlmi_priv.pwd_admin->kobj, NULL, "%s", "Admin"); 749 if (ret) 750 goto fail_create_attr; 751 752 ret = sysfs_create_group(&tlmi_priv.pwd_admin->kobj, &auth_attr_group); 753 if (ret) 754 goto fail_create_attr; 755 756 tlmi_priv.pwd_power->kobj.kset = tlmi_priv.authentication_kset; 757 ret = kobject_add(&tlmi_priv.pwd_power->kobj, NULL, "%s", "System"); 758 if (ret) 759 goto fail_create_attr; 760 761 ret = sysfs_create_group(&tlmi_priv.pwd_power->kobj, &auth_attr_group); 762 if (ret) 763 goto fail_create_attr; 764 765 return ret; 766 767 fail_create_attr: 768 tlmi_release_attr(); 769 fail_device_created: 770 device_destroy(fw_attr_class, MKDEV(0, 0)); 771 fail_class_created: 772 fw_attributes_class_put(); 773 return ret; 774 } 775 776 /* ---- Base Driver -------------------------------------------------------- */ 777 static int tlmi_analyze(void) 778 { 779 struct tlmi_pwdcfg pwdcfg; 780 acpi_status status; 781 int i, ret; 782 783 if (wmi_has_guid(LENOVO_SET_BIOS_SETTINGS_GUID) && 784 wmi_has_guid(LENOVO_SAVE_BIOS_SETTINGS_GUID)) 785 tlmi_priv.can_set_bios_settings = true; 786 787 if (wmi_has_guid(LENOVO_GET_BIOS_SELECTIONS_GUID)) 788 tlmi_priv.can_get_bios_selections = true; 789 790 if (wmi_has_guid(LENOVO_SET_BIOS_PASSWORD_GUID)) 791 tlmi_priv.can_set_bios_password = true; 792 793 if (wmi_has_guid(LENOVO_BIOS_PASSWORD_SETTINGS_GUID)) 794 tlmi_priv.can_get_password_settings = true; 795 796 /* 797 * Try to find the number of valid settings of this machine 798 * and use it to create sysfs attributes. 799 */ 800 for (i = 0; i < TLMI_SETTINGS_COUNT; ++i) { 801 struct tlmi_attr_setting *setting; 802 char *item = NULL; 803 char *p; 804 805 tlmi_priv.setting[i] = NULL; 806 status = tlmi_setting(i, &item, LENOVO_BIOS_SETTING_GUID); 807 if (ACPI_FAILURE(status)) 808 break; 809 if (!item) 810 break; 811 if (!*item) 812 continue; 813 814 /* It is not allowed to have '/' for file name. Convert it into '\'. */ 815 strreplace(item, '/', '\\'); 816 817 /* Remove the value part */ 818 p = strchrnul(item, ','); 819 *p = '\0'; 820 821 /* Create a setting entry */ 822 setting = kzalloc(sizeof(*setting), GFP_KERNEL); 823 if (!setting) { 824 ret = -ENOMEM; 825 goto fail_clear_attr; 826 } 827 setting->index = i; 828 strscpy(setting->display_name, item, TLMI_SETTINGS_MAXLEN); 829 /* If BIOS selections supported, load those */ 830 if (tlmi_priv.can_get_bios_selections) { 831 ret = tlmi_get_bios_selections(setting->display_name, 832 &setting->possible_values); 833 if (ret || !setting->possible_values) 834 pr_info("Error retrieving possible values for %d : %s\n", 835 i, setting->display_name); 836 } 837 kobject_init(&setting->kobj, &tlmi_attr_setting_ktype); 838 tlmi_priv.setting[i] = setting; 839 tlmi_priv.settings_count++; 840 kfree(item); 841 } 842 843 /* Create password setting structure */ 844 ret = tlmi_get_pwd_settings(&pwdcfg); 845 if (ret) 846 goto fail_clear_attr; 847 848 tlmi_priv.pwd_admin = kzalloc(sizeof(struct tlmi_pwd_setting), GFP_KERNEL); 849 if (!tlmi_priv.pwd_admin) { 850 ret = -ENOMEM; 851 goto fail_clear_attr; 852 } 853 strscpy(tlmi_priv.pwd_admin->kbdlang, "us", TLMI_LANG_MAXLEN); 854 tlmi_priv.pwd_admin->encoding = TLMI_ENCODING_ASCII; 855 tlmi_priv.pwd_admin->pwd_type = "pap"; 856 tlmi_priv.pwd_admin->role = "bios-admin"; 857 tlmi_priv.pwd_admin->minlen = pwdcfg.min_length; 858 if (WARN_ON(pwdcfg.max_length >= TLMI_PWD_BUFSIZE)) 859 pwdcfg.max_length = TLMI_PWD_BUFSIZE - 1; 860 tlmi_priv.pwd_admin->maxlen = pwdcfg.max_length; 861 if (pwdcfg.password_state & TLMI_PAP_PWD) 862 tlmi_priv.pwd_admin->valid = true; 863 864 kobject_init(&tlmi_priv.pwd_admin->kobj, &tlmi_pwd_setting_ktype); 865 866 tlmi_priv.pwd_power = kzalloc(sizeof(struct tlmi_pwd_setting), GFP_KERNEL); 867 if (!tlmi_priv.pwd_power) { 868 ret = -ENOMEM; 869 goto fail_free_pwd_admin; 870 } 871 strscpy(tlmi_priv.pwd_power->kbdlang, "us", TLMI_LANG_MAXLEN); 872 tlmi_priv.pwd_power->encoding = TLMI_ENCODING_ASCII; 873 tlmi_priv.pwd_power->pwd_type = "pop"; 874 tlmi_priv.pwd_power->role = "power-on"; 875 tlmi_priv.pwd_power->minlen = pwdcfg.min_length; 876 tlmi_priv.pwd_power->maxlen = pwdcfg.max_length; 877 878 if (pwdcfg.password_state & TLMI_POP_PWD) 879 tlmi_priv.pwd_power->valid = true; 880 881 kobject_init(&tlmi_priv.pwd_power->kobj, &tlmi_pwd_setting_ktype); 882 883 return 0; 884 885 fail_free_pwd_admin: 886 kfree(tlmi_priv.pwd_admin); 887 fail_clear_attr: 888 for (i = 0; i < TLMI_SETTINGS_COUNT; ++i) { 889 if (tlmi_priv.setting[i]) { 890 kfree(tlmi_priv.setting[i]->possible_values); 891 kfree(tlmi_priv.setting[i]); 892 } 893 } 894 return ret; 895 } 896 897 static void tlmi_remove(struct wmi_device *wdev) 898 { 899 tlmi_release_attr(); 900 device_destroy(fw_attr_class, MKDEV(0, 0)); 901 fw_attributes_class_put(); 902 } 903 904 static int tlmi_probe(struct wmi_device *wdev, const void *context) 905 { 906 tlmi_analyze(); 907 return tlmi_sysfs_init(); 908 } 909 910 static const struct wmi_device_id tlmi_id_table[] = { 911 { .guid_string = LENOVO_BIOS_SETTING_GUID }, 912 { } 913 }; 914 MODULE_DEVICE_TABLE(wmi, tlmi_id_table); 915 916 static struct wmi_driver tlmi_driver = { 917 .driver = { 918 .name = "think-lmi", 919 }, 920 .id_table = tlmi_id_table, 921 .probe = tlmi_probe, 922 .remove = tlmi_remove, 923 }; 924 925 MODULE_AUTHOR("Sugumaran L <slacshiminar@lenovo.com>"); 926 MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>"); 927 MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>"); 928 MODULE_DESCRIPTION("ThinkLMI Driver"); 929 MODULE_LICENSE("GPL"); 930 931 module_wmi_driver(tlmi_driver); 932