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