Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Think LMI BIOS configuration driver
0004  *
0005  * Copyright(C) 2019-2021 Lenovo
0006  *
0007  * Original code from Thinkpad-wmi project https://github.com/iksaif/thinkpad-wmi
0008  * Copyright(C) 2017 Corentin Chary <corentin.chary@gmail.com>
0009  * Distributed under the GPL-2.0 license
0010  */
0011 
0012 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0013 
0014 #include <linux/acpi.h>
0015 #include <linux/errno.h>
0016 #include <linux/fs.h>
0017 #include <linux/string.h>
0018 #include <linux/types.h>
0019 #include <linux/dmi.h>
0020 #include <linux/wmi.h>
0021 #include "firmware_attributes_class.h"
0022 #include "think-lmi.h"
0023 
0024 static bool debug_support;
0025 module_param(debug_support, bool, 0444);
0026 MODULE_PARM_DESC(debug_support, "Enable debug command support");
0027 
0028 /*
0029  * Name: BiosSetting
0030  * Description: Get item name and settings for current LMI instance.
0031  * Type: Query
0032  * Returns: "Item,Value"
0033  * Example: "WakeOnLAN,Enable"
0034  */
0035 #define LENOVO_BIOS_SETTING_GUID "51F5230E-9677-46CD-A1CF-C0B23EE34DB7"
0036 
0037 /*
0038  * Name: SetBiosSetting
0039  * Description: Change the BIOS setting to the desired value using the SetBiosSetting
0040  *  class. To save the settings, use the SaveBiosSetting class.
0041  *  BIOS settings and values are case sensitive.
0042  *  After making changes to the BIOS settings, you must reboot the computer
0043  *  before the changes will take effect.
0044  * Type: Method
0045  * Arguments: "Item,Value,Password,Encoding,KbdLang;"
0046  * Example: "WakeOnLAN,Disable,pa55w0rd,ascii,us;"
0047  */
0048 #define LENOVO_SET_BIOS_SETTINGS_GUID "98479A64-33F5-4E33-A707-8E251EBBC3A1"
0049 
0050 /*
0051  * Name: SaveBiosSettings
0052  * Description: Save any pending changes in settings.
0053  * Type: Method
0054  * Arguments: "Password,Encoding,KbdLang;"
0055  * Example: "pa55w0rd,ascii,us;"
0056  */
0057 #define LENOVO_SAVE_BIOS_SETTINGS_GUID "6A4B54EF-A5ED-4D33-9455-B0D9B48DF4B3"
0058 
0059 /*
0060  * Name: BiosPasswordSettings
0061  * Description: Return BIOS Password settings
0062  * Type: Query
0063  * Returns: PasswordMode, PasswordState, MinLength, MaxLength,
0064  *  SupportedEncoding, SupportedKeyboard
0065  */
0066 #define LENOVO_BIOS_PASSWORD_SETTINGS_GUID "8ADB159E-1E32-455C-BC93-308A7ED98246"
0067 
0068 /*
0069  * Name: SetBiosPassword
0070  * Description: Change a specific password.
0071  *  - BIOS settings cannot be changed at the same boot as power-on
0072  *    passwords (POP) and hard disk passwords (HDP). If you want to change
0073  *    BIOS settings and POP or HDP, you must reboot the system after changing
0074  *    one of them.
0075  *  - A password cannot be set using this method when one does not already
0076  *    exist. Passwords can only be updated or cleared.
0077  * Type: Method
0078  * Arguments: "PasswordType,CurrentPassword,NewPassword,Encoding,KbdLang;"
0079  * Example: "pop,pa55w0rd,newpa55w0rd,ascii,us;”
0080  */
0081 #define LENOVO_SET_BIOS_PASSWORD_GUID "2651D9FD-911C-4B69-B94E-D0DED5963BD7"
0082 
0083 /*
0084  * Name: GetBiosSelections
0085  * Description: Return a list of valid settings for a given item.
0086  * Type: Method
0087  * Arguments: "Item"
0088  * Returns: "Value1,Value2,Value3,..."
0089  * Example:
0090  *  -> "FlashOverLAN"
0091  *  <- "Enabled,Disabled"
0092  */
0093 #define LENOVO_GET_BIOS_SELECTIONS_GUID "7364651A-132F-4FE7-ADAA-40C6C7EE2E3B"
0094 
0095 /*
0096  * Name: DebugCmd
0097  * Description: Debug entry method for entering debug commands to the BIOS
0098  */
0099 #define LENOVO_DEBUG_CMD_GUID "7FF47003-3B6C-4E5E-A227-E979824A85D1"
0100 
0101 /*
0102  * Name: OpcodeIF
0103  * Description: Opcode interface which provides the ability to set multiple
0104  *  parameters and then trigger an action with a final command.
0105  *  This is particularly useful for simplifying setting passwords.
0106  *  With this support comes the ability to set System, HDD and NVMe
0107  *  passwords.
0108  *  This is currently available on ThinkCenter and ThinkStations platforms
0109  */
0110 #define LENOVO_OPCODE_IF_GUID "DFDDEF2C-57D4-48ce-B196-0FB787D90836"
0111 
0112 /*
0113  * Name: SetBiosCert
0114  * Description: Install BIOS certificate.
0115  * Type: Method
0116  * Arguments: "Certificate,Password"
0117  * You must reboot the computer before the changes will take effect.
0118  */
0119 #define LENOVO_SET_BIOS_CERT_GUID    "26861C9F-47E9-44C4-BD8B-DFE7FA2610FE"
0120 
0121 /*
0122  * Name: UpdateBiosCert
0123  * Description: Update BIOS certificate.
0124  * Type: Method
0125  * Format: "Certificate,Signature"
0126  * You must reboot the computer before the changes will take effect.
0127  */
0128 #define LENOVO_UPDATE_BIOS_CERT_GUID "9AA3180A-9750-41F7-B9F7-D5D3B1BAC3CE"
0129 
0130 /*
0131  * Name: ClearBiosCert
0132  * Description: Uninstall BIOS certificate.
0133  * Type: Method
0134  * Format: "Serial,Signature"
0135  * You must reboot the computer before the changes will take effect.
0136  */
0137 #define LENOVO_CLEAR_BIOS_CERT_GUID  "B2BC39A7-78DD-4D71-B059-A510DEC44890"
0138 /*
0139  * Name: CertToPassword
0140  * Description: Switch from certificate to password authentication.
0141  * Type: Method
0142  * Format: "Password,Signature"
0143  * You must reboot the computer before the changes will take effect.
0144  */
0145 #define LENOVO_CERT_TO_PASSWORD_GUID "0DE8590D-5510-4044-9621-77C227F5A70D"
0146 
0147 /*
0148  * Name: SetBiosSettingCert
0149  * Description: Set attribute using certificate authentication.
0150  * Type: Method
0151  * Format: "Item,Value,Signature"
0152  */
0153 #define LENOVO_SET_BIOS_SETTING_CERT_GUID  "34A008CC-D205-4B62-9E67-31DFA8B90003"
0154 
0155 /*
0156  * Name: SaveBiosSettingCert
0157  * Description: Save any pending changes in settings.
0158  * Type: Method
0159  * Format: "Signature"
0160  */
0161 #define LENOVO_SAVE_BIOS_SETTING_CERT_GUID "C050FB9D-DF5F-4606-B066-9EFC401B2551"
0162 
0163 /*
0164  * Name: CertThumbprint
0165  * Description: Display Certificate thumbprints
0166  * Type: Query
0167  * Returns: MD5, SHA1 & SHA256 thumbprints
0168  */
0169 #define LENOVO_CERT_THUMBPRINT_GUID "C59119ED-1C0D-4806-A8E9-59AA318176C4"
0170 
0171 #define TLMI_POP_PWD (1 << 0)
0172 #define TLMI_PAP_PWD (1 << 1)
0173 #define TLMI_HDD_PWD (1 << 2)
0174 #define TLMI_SYS_PWD (1 << 3)
0175 #define TLMI_CERT    (1 << 7)
0176 
0177 #define to_tlmi_pwd_setting(kobj)  container_of(kobj, struct tlmi_pwd_setting, kobj)
0178 #define to_tlmi_attr_setting(kobj)  container_of(kobj, struct tlmi_attr_setting, kobj)
0179 
0180 static const struct tlmi_err_codes tlmi_errs[] = {
0181     {"Success", 0},
0182     {"Not Supported", -EOPNOTSUPP},
0183     {"Invalid Parameter", -EINVAL},
0184     {"Access Denied", -EACCES},
0185     {"System Busy", -EBUSY},
0186 };
0187 
0188 static const char * const encoding_options[] = {
0189     [TLMI_ENCODING_ASCII] = "ascii",
0190     [TLMI_ENCODING_SCANCODE] = "scancode",
0191 };
0192 static const char * const level_options[] = {
0193     [TLMI_LEVEL_USER] = "user",
0194     [TLMI_LEVEL_MASTER] = "master",
0195 };
0196 static struct think_lmi tlmi_priv;
0197 static struct class *fw_attr_class;
0198 
0199 /* ------ Utility functions ------------*/
0200 /* Strip out CR if one is present */
0201 static void strip_cr(char *str)
0202 {
0203     char *p = strchrnul(str, '\n');
0204     *p = '\0';
0205 }
0206 
0207 /* Convert BIOS WMI error string to suitable error code */
0208 static int tlmi_errstr_to_err(const char *errstr)
0209 {
0210     int i;
0211 
0212     for (i = 0; i < sizeof(tlmi_errs)/sizeof(struct tlmi_err_codes); i++) {
0213         if (!strcmp(tlmi_errs[i].err_str, errstr))
0214             return tlmi_errs[i].err_code;
0215     }
0216     return -EPERM;
0217 }
0218 
0219 /* Extract error string from WMI return buffer */
0220 static int tlmi_extract_error(const struct acpi_buffer *output)
0221 {
0222     const union acpi_object *obj;
0223 
0224     obj = output->pointer;
0225     if (!obj)
0226         return -ENOMEM;
0227     if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer)
0228         return -EIO;
0229 
0230     return tlmi_errstr_to_err(obj->string.pointer);
0231 }
0232 
0233 /* Utility function to execute WMI call to BIOS */
0234 static int tlmi_simple_call(const char *guid, const char *arg)
0235 {
0236     const struct acpi_buffer input = { strlen(arg), (char *)arg };
0237     struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
0238     acpi_status status;
0239     int i, err;
0240 
0241     /*
0242      * Duplicated call required to match BIOS workaround for behavior
0243      * seen when WMI accessed via scripting on other OS.
0244      */
0245     for (i = 0; i < 2; i++) {
0246         /* (re)initialize output buffer to default state */
0247         output.length = ACPI_ALLOCATE_BUFFER;
0248         output.pointer = NULL;
0249 
0250         status = wmi_evaluate_method(guid, 0, 0, &input, &output);
0251         if (ACPI_FAILURE(status)) {
0252             kfree(output.pointer);
0253             return -EIO;
0254         }
0255         err = tlmi_extract_error(&output);
0256         kfree(output.pointer);
0257         if (err)
0258             return err;
0259     }
0260     return 0;
0261 }
0262 
0263 /* Extract output string from WMI return buffer */
0264 static int tlmi_extract_output_string(const struct acpi_buffer *output,
0265                       char **string)
0266 {
0267     const union acpi_object *obj;
0268     char *s;
0269 
0270     obj = output->pointer;
0271     if (!obj)
0272         return -ENOMEM;
0273     if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer)
0274         return -EIO;
0275 
0276     s = kstrdup(obj->string.pointer, GFP_KERNEL);
0277     if (!s)
0278         return -ENOMEM;
0279     *string = s;
0280     return 0;
0281 }
0282 
0283 /* ------ Core interface functions ------------*/
0284 
0285 /* Get password settings from BIOS */
0286 static int tlmi_get_pwd_settings(struct tlmi_pwdcfg *pwdcfg)
0287 {
0288     struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
0289     const union acpi_object *obj;
0290     acpi_status status;
0291     int copy_size;
0292 
0293     if (!tlmi_priv.can_get_password_settings)
0294         return -EOPNOTSUPP;
0295 
0296     status = wmi_query_block(LENOVO_BIOS_PASSWORD_SETTINGS_GUID, 0,
0297                  &output);
0298     if (ACPI_FAILURE(status))
0299         return -EIO;
0300 
0301     obj = output.pointer;
0302     if (!obj)
0303         return -ENOMEM;
0304     if (obj->type != ACPI_TYPE_BUFFER || !obj->buffer.pointer) {
0305         kfree(obj);
0306         return -EIO;
0307     }
0308     /*
0309      * The size of thinkpad_wmi_pcfg on ThinkStation is larger than ThinkPad.
0310      * To make the driver compatible on different brands, we permit it to get
0311      * the data in below case.
0312      * Settings must have at minimum the core fields available
0313      */
0314     if (obj->buffer.length < sizeof(struct tlmi_pwdcfg_core)) {
0315         pr_warn("Unknown pwdcfg buffer length %d\n", obj->buffer.length);
0316         kfree(obj);
0317         return -EIO;
0318     }
0319 
0320     copy_size = obj->buffer.length < sizeof(struct tlmi_pwdcfg) ?
0321         obj->buffer.length : sizeof(struct tlmi_pwdcfg);
0322     memcpy(pwdcfg, obj->buffer.pointer, copy_size);
0323     kfree(obj);
0324 
0325     if (WARN_ON(pwdcfg->core.max_length >= TLMI_PWD_BUFSIZE))
0326         pwdcfg->core.max_length = TLMI_PWD_BUFSIZE - 1;
0327     return 0;
0328 }
0329 
0330 static int tlmi_save_bios_settings(const char *password)
0331 {
0332     return tlmi_simple_call(LENOVO_SAVE_BIOS_SETTINGS_GUID,
0333                 password);
0334 }
0335 
0336 static int tlmi_opcode_setting(char *setting, const char *value)
0337 {
0338     char *opcode_str;
0339     int ret;
0340 
0341     opcode_str = kasprintf(GFP_KERNEL, "%s:%s;", setting, value);
0342     if (!opcode_str)
0343         return -ENOMEM;
0344 
0345     ret = tlmi_simple_call(LENOVO_OPCODE_IF_GUID, opcode_str);
0346     kfree(opcode_str);
0347     return ret;
0348 }
0349 
0350 static int tlmi_setting(int item, char **value, const char *guid_string)
0351 {
0352     struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
0353     acpi_status status;
0354     int ret;
0355 
0356     status = wmi_query_block(guid_string, item, &output);
0357     if (ACPI_FAILURE(status)) {
0358         kfree(output.pointer);
0359         return -EIO;
0360     }
0361 
0362     ret = tlmi_extract_output_string(&output, value);
0363     kfree(output.pointer);
0364     return ret;
0365 }
0366 
0367 static int tlmi_get_bios_selections(const char *item, char **value)
0368 {
0369     const struct acpi_buffer input = { strlen(item), (char *)item };
0370     struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
0371     acpi_status status;
0372     int ret;
0373 
0374     status = wmi_evaluate_method(LENOVO_GET_BIOS_SELECTIONS_GUID,
0375                      0, 0, &input, &output);
0376 
0377     if (ACPI_FAILURE(status)) {
0378         kfree(output.pointer);
0379         return -EIO;
0380     }
0381 
0382     ret = tlmi_extract_output_string(&output, value);
0383     kfree(output.pointer);
0384     return ret;
0385 }
0386 
0387 /* ---- Authentication sysfs --------------------------------------------------------- */
0388 static ssize_t is_enabled_show(struct kobject *kobj, struct kobj_attribute *attr,
0389                       char *buf)
0390 {
0391     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0392 
0393     return sysfs_emit(buf, "%d\n", setting->valid);
0394 }
0395 
0396 static struct kobj_attribute auth_is_pass_set = __ATTR_RO(is_enabled);
0397 
0398 static ssize_t current_password_store(struct kobject *kobj,
0399                       struct kobj_attribute *attr,
0400                       const char *buf, size_t count)
0401 {
0402     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0403     size_t pwdlen;
0404 
0405     pwdlen = strlen(buf);
0406     /* pwdlen == 0 is allowed to clear the password */
0407     if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen)))
0408         return -EINVAL;
0409 
0410     strscpy(setting->password, buf, setting->maxlen);
0411     /* Strip out CR if one is present, setting password won't work if it is present */
0412     strip_cr(setting->password);
0413     return count;
0414 }
0415 
0416 static struct kobj_attribute auth_current_password = __ATTR_WO(current_password);
0417 
0418 static ssize_t new_password_store(struct kobject *kobj,
0419                   struct kobj_attribute *attr,
0420                   const char *buf, size_t count)
0421 {
0422     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0423     char *auth_str, *new_pwd;
0424     size_t pwdlen;
0425     int ret;
0426 
0427     if (!capable(CAP_SYS_ADMIN))
0428         return -EPERM;
0429 
0430     if (!tlmi_priv.can_set_bios_password)
0431         return -EOPNOTSUPP;
0432 
0433     new_pwd = kstrdup(buf, GFP_KERNEL);
0434     if (!new_pwd)
0435         return -ENOMEM;
0436 
0437     /* Strip out CR if one is present, setting password won't work if it is present */
0438     strip_cr(new_pwd);
0439 
0440     pwdlen = strlen(new_pwd);
0441     /* pwdlen == 0 is allowed to clear the password */
0442     if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) {
0443         ret = -EINVAL;
0444         goto out;
0445     }
0446 
0447     /* If opcode support is present use that interface */
0448     if (tlmi_priv.opcode_support) {
0449         char pwd_type[8];
0450 
0451         /* Special handling required for HDD and NVMe passwords */
0452         if (setting == tlmi_priv.pwd_hdd) {
0453             if (setting->level == TLMI_LEVEL_USER)
0454                 sprintf(pwd_type, "uhdp%d", setting->index);
0455             else
0456                 sprintf(pwd_type, "mhdp%d", setting->index);
0457         } else if (setting == tlmi_priv.pwd_nvme) {
0458             if (setting->level == TLMI_LEVEL_USER)
0459                 sprintf(pwd_type, "unvp%d", setting->index);
0460             else
0461                 sprintf(pwd_type, "mnvp%d", setting->index);
0462         } else {
0463             sprintf(pwd_type, "%s", setting->pwd_type);
0464         }
0465 
0466         ret = tlmi_opcode_setting("WmiOpcodePasswordType", pwd_type);
0467         if (ret)
0468             goto out;
0469 
0470         if (tlmi_priv.pwd_admin->valid) {
0471             ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
0472                     tlmi_priv.pwd_admin->password);
0473             if (ret)
0474                 goto out;
0475         }
0476         ret = tlmi_opcode_setting("WmiOpcodePasswordCurrent01", setting->password);
0477         if (ret)
0478             goto out;
0479         ret = tlmi_opcode_setting("WmiOpcodePasswordNew01", new_pwd);
0480         if (ret)
0481             goto out;
0482         ret = tlmi_simple_call(LENOVO_OPCODE_IF_GUID, "WmiOpcodePasswordSetUpdate;");
0483     } else {
0484         /* Format: 'PasswordType,CurrentPw,NewPw,Encoding,KbdLang;' */
0485         auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s,%s,%s;",
0486                 setting->pwd_type, setting->password, new_pwd,
0487                 encoding_options[setting->encoding], setting->kbdlang);
0488         if (!auth_str) {
0489             ret = -ENOMEM;
0490             goto out;
0491         }
0492         ret = tlmi_simple_call(LENOVO_SET_BIOS_PASSWORD_GUID, auth_str);
0493         kfree(auth_str);
0494     }
0495 out:
0496     kfree(new_pwd);
0497     return ret ?: count;
0498 }
0499 
0500 static struct kobj_attribute auth_new_password = __ATTR_WO(new_password);
0501 
0502 static ssize_t min_password_length_show(struct kobject *kobj, struct kobj_attribute *attr,
0503              char *buf)
0504 {
0505     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0506 
0507     return sysfs_emit(buf, "%d\n", setting->minlen);
0508 }
0509 
0510 static struct kobj_attribute auth_min_pass_length = __ATTR_RO(min_password_length);
0511 
0512 static ssize_t max_password_length_show(struct kobject *kobj, struct kobj_attribute *attr,
0513              char *buf)
0514 {
0515     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0516 
0517     return sysfs_emit(buf, "%d\n", setting->maxlen);
0518 }
0519 static struct kobj_attribute auth_max_pass_length = __ATTR_RO(max_password_length);
0520 
0521 static ssize_t mechanism_show(struct kobject *kobj, struct kobj_attribute *attr,
0522              char *buf)
0523 {
0524     return sysfs_emit(buf, "password\n");
0525 }
0526 static struct kobj_attribute auth_mechanism = __ATTR_RO(mechanism);
0527 
0528 static ssize_t encoding_show(struct kobject *kobj, struct kobj_attribute *attr,
0529              char *buf)
0530 {
0531     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0532 
0533     return sysfs_emit(buf, "%s\n", encoding_options[setting->encoding]);
0534 }
0535 
0536 static ssize_t encoding_store(struct kobject *kobj,
0537                   struct kobj_attribute *attr,
0538                   const char *buf, size_t count)
0539 {
0540     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0541     int i;
0542 
0543     /* Scan for a matching profile */
0544     i = sysfs_match_string(encoding_options, buf);
0545     if (i < 0)
0546         return -EINVAL;
0547 
0548     setting->encoding = i;
0549     return count;
0550 }
0551 
0552 static struct kobj_attribute auth_encoding = __ATTR_RW(encoding);
0553 
0554 static ssize_t kbdlang_show(struct kobject *kobj, struct kobj_attribute *attr,
0555              char *buf)
0556 {
0557     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0558 
0559     return sysfs_emit(buf, "%s\n", setting->kbdlang);
0560 }
0561 
0562 static ssize_t kbdlang_store(struct kobject *kobj,
0563                   struct kobj_attribute *attr,
0564                   const char *buf, size_t count)
0565 {
0566     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0567     int length;
0568 
0569     /* Calculate length till '\n' or terminating 0 */
0570     length = strchrnul(buf, '\n') - buf;
0571     if (!length || length >= TLMI_LANG_MAXLEN)
0572         return -EINVAL;
0573 
0574     memcpy(setting->kbdlang, buf, length);
0575     setting->kbdlang[length] = '\0';
0576     return count;
0577 }
0578 
0579 static struct kobj_attribute auth_kbdlang = __ATTR_RW(kbdlang);
0580 
0581 static ssize_t role_show(struct kobject *kobj, struct kobj_attribute *attr,
0582              char *buf)
0583 {
0584     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0585 
0586     return sysfs_emit(buf, "%s\n", setting->role);
0587 }
0588 static struct kobj_attribute auth_role = __ATTR_RO(role);
0589 
0590 static ssize_t index_show(struct kobject *kobj, struct kobj_attribute *attr,
0591              char *buf)
0592 {
0593     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0594 
0595     return sysfs_emit(buf, "%d\n", setting->index);
0596 }
0597 
0598 static ssize_t index_store(struct kobject *kobj,
0599                   struct kobj_attribute *attr,
0600                   const char *buf, size_t count)
0601 {
0602     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0603     int err, val;
0604 
0605     err = kstrtoint(buf, 10, &val);
0606     if (err < 0)
0607         return err;
0608 
0609     if (val < 0 || val > TLMI_INDEX_MAX)
0610         return -EINVAL;
0611 
0612     setting->index = val;
0613     return count;
0614 }
0615 
0616 static struct kobj_attribute auth_index = __ATTR_RW(index);
0617 
0618 static ssize_t level_show(struct kobject *kobj, struct kobj_attribute *attr,
0619              char *buf)
0620 {
0621     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0622 
0623     return sysfs_emit(buf, "%s\n", level_options[setting->level]);
0624 }
0625 
0626 static ssize_t level_store(struct kobject *kobj,
0627                   struct kobj_attribute *attr,
0628                   const char *buf, size_t count)
0629 {
0630     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0631     int i;
0632 
0633     /* Scan for a matching profile */
0634     i = sysfs_match_string(level_options, buf);
0635     if (i < 0)
0636         return -EINVAL;
0637 
0638     setting->level = i;
0639     return count;
0640 }
0641 
0642 static struct kobj_attribute auth_level = __ATTR_RW(level);
0643 
0644 static ssize_t cert_thumbprint(char *buf, const char *arg, int count)
0645 {
0646     const struct acpi_buffer input = { strlen(arg), (char *)arg };
0647     struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
0648     const union acpi_object *obj;
0649     acpi_status status;
0650 
0651     status = wmi_evaluate_method(LENOVO_CERT_THUMBPRINT_GUID, 0, 0, &input, &output);
0652     if (ACPI_FAILURE(status)) {
0653         kfree(output.pointer);
0654         return -EIO;
0655     }
0656     obj = output.pointer;
0657     if (!obj)
0658         return -ENOMEM;
0659     if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer) {
0660         kfree(output.pointer);
0661         return -EIO;
0662     }
0663     count += sysfs_emit_at(buf, count, "%s : %s\n", arg, (char *)obj->string.pointer);
0664     kfree(output.pointer);
0665 
0666     return count;
0667 }
0668 
0669 static ssize_t certificate_thumbprint_show(struct kobject *kobj, struct kobj_attribute *attr,
0670              char *buf)
0671 {
0672     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0673     int count = 0;
0674 
0675     if (!tlmi_priv.certificate_support || !setting->cert_installed)
0676         return -EOPNOTSUPP;
0677 
0678     count += cert_thumbprint(buf, "Md5", count);
0679     count += cert_thumbprint(buf, "Sha1", count);
0680     count += cert_thumbprint(buf, "Sha256", count);
0681     return count;
0682 }
0683 
0684 static struct kobj_attribute auth_cert_thumb = __ATTR_RO(certificate_thumbprint);
0685 
0686 static ssize_t cert_to_password_store(struct kobject *kobj,
0687                   struct kobj_attribute *attr,
0688                   const char *buf, size_t count)
0689 {
0690     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0691     char *auth_str, *passwd;
0692     int ret;
0693 
0694     if (!capable(CAP_SYS_ADMIN))
0695         return -EPERM;
0696 
0697     if (!tlmi_priv.certificate_support)
0698         return -EOPNOTSUPP;
0699 
0700     if (!setting->cert_installed)
0701         return -EINVAL;
0702 
0703     if (!setting->signature || !setting->signature[0])
0704         return -EACCES;
0705 
0706     passwd = kstrdup(buf, GFP_KERNEL);
0707     if (!passwd)
0708         return -ENOMEM;
0709 
0710     /* Strip out CR if one is present */
0711     strip_cr(passwd);
0712 
0713     /* Format: 'Password,Signature' */
0714     auth_str = kasprintf(GFP_KERNEL, "%s,%s", passwd, setting->signature);
0715     if (!auth_str) {
0716         kfree(passwd);
0717         return -ENOMEM;
0718     }
0719     ret = tlmi_simple_call(LENOVO_CERT_TO_PASSWORD_GUID, auth_str);
0720     kfree(auth_str);
0721     kfree(passwd);
0722 
0723     return ret ?: count;
0724 }
0725 
0726 static struct kobj_attribute auth_cert_to_password = __ATTR_WO(cert_to_password);
0727 
0728 static ssize_t certificate_store(struct kobject *kobj,
0729                   struct kobj_attribute *attr,
0730                   const char *buf, size_t count)
0731 {
0732     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0733     char *auth_str, *new_cert;
0734     char *guid;
0735     int ret;
0736 
0737     if (!capable(CAP_SYS_ADMIN))
0738         return -EPERM;
0739 
0740     if (!tlmi_priv.certificate_support)
0741         return -EOPNOTSUPP;
0742 
0743     /* If empty then clear installed certificate */
0744     if ((buf[0] == '\0') || (buf[0] == '\n')) { /* Clear installed certificate */
0745         /* Check that signature is set */
0746         if (!setting->signature || !setting->signature[0])
0747             return -EACCES;
0748 
0749         /* Format: 'serial#, signature' */
0750         auth_str = kasprintf(GFP_KERNEL, "%s,%s",
0751                 dmi_get_system_info(DMI_PRODUCT_SERIAL),
0752                 setting->signature);
0753         if (!auth_str)
0754             return -ENOMEM;
0755 
0756         ret = tlmi_simple_call(LENOVO_CLEAR_BIOS_CERT_GUID, auth_str);
0757         kfree(auth_str);
0758 
0759         return ret ?: count;
0760     }
0761 
0762     new_cert = kstrdup(buf, GFP_KERNEL);
0763     if (!new_cert)
0764         return -ENOMEM;
0765     /* Strip out CR if one is present */
0766     strip_cr(new_cert);
0767 
0768     if (setting->cert_installed) {
0769         /* Certificate is installed so this is an update */
0770         if (!setting->signature || !setting->signature[0]) {
0771             kfree(new_cert);
0772             return -EACCES;
0773         }
0774         guid = LENOVO_UPDATE_BIOS_CERT_GUID;
0775         /* Format: 'Certificate,Signature' */
0776         auth_str = kasprintf(GFP_KERNEL, "%s,%s",
0777                 new_cert, setting->signature);
0778     } else {
0779         /* This is a fresh install */
0780         if (!setting->valid || !setting->password[0]) {
0781             kfree(new_cert);
0782             return -EACCES;
0783         }
0784         guid = LENOVO_SET_BIOS_CERT_GUID;
0785         /* Format: 'Certificate,Admin-password' */
0786         auth_str = kasprintf(GFP_KERNEL, "%s,%s",
0787                 new_cert, setting->password);
0788     }
0789     kfree(new_cert);
0790     if (!auth_str)
0791         return -ENOMEM;
0792 
0793     ret = tlmi_simple_call(guid, auth_str);
0794     kfree(auth_str);
0795 
0796     return ret ?: count;
0797 }
0798 
0799 static struct kobj_attribute auth_certificate = __ATTR_WO(certificate);
0800 
0801 static ssize_t signature_store(struct kobject *kobj,
0802                   struct kobj_attribute *attr,
0803                   const char *buf, size_t count)
0804 {
0805     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0806     char *new_signature;
0807 
0808     if (!capable(CAP_SYS_ADMIN))
0809         return -EPERM;
0810 
0811     if (!tlmi_priv.certificate_support)
0812         return -EOPNOTSUPP;
0813 
0814     new_signature = kstrdup(buf, GFP_KERNEL);
0815     if (!new_signature)
0816         return -ENOMEM;
0817 
0818     /* Strip out CR if one is present */
0819     strip_cr(new_signature);
0820 
0821     /* Free any previous signature */
0822     kfree(setting->signature);
0823     setting->signature = new_signature;
0824 
0825     return count;
0826 }
0827 
0828 static struct kobj_attribute auth_signature = __ATTR_WO(signature);
0829 
0830 static ssize_t save_signature_store(struct kobject *kobj,
0831                   struct kobj_attribute *attr,
0832                   const char *buf, size_t count)
0833 {
0834     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0835     char *new_signature;
0836 
0837     if (!capable(CAP_SYS_ADMIN))
0838         return -EPERM;
0839 
0840     if (!tlmi_priv.certificate_support)
0841         return -EOPNOTSUPP;
0842 
0843     new_signature = kstrdup(buf, GFP_KERNEL);
0844     if (!new_signature)
0845         return -ENOMEM;
0846 
0847     /* Strip out CR if one is present */
0848     strip_cr(new_signature);
0849 
0850     /* Free any previous signature */
0851     kfree(setting->save_signature);
0852     setting->save_signature = new_signature;
0853 
0854     return count;
0855 }
0856 
0857 static struct kobj_attribute auth_save_signature = __ATTR_WO(save_signature);
0858 
0859 static umode_t auth_attr_is_visible(struct kobject *kobj,
0860                          struct attribute *attr, int n)
0861 {
0862     struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj);
0863 
0864     /* We only want to display level and index settings on HDD/NVMe */
0865     if ((attr == (struct attribute *)&auth_index) ||
0866             (attr == (struct attribute *)&auth_level)) {
0867         if ((setting == tlmi_priv.pwd_hdd) || (setting == tlmi_priv.pwd_nvme))
0868             return attr->mode;
0869         return 0;
0870     }
0871 
0872     /* We only display certificates on Admin account, if supported */
0873     if ((attr == (struct attribute *)&auth_certificate) ||
0874             (attr == (struct attribute *)&auth_signature) ||
0875             (attr == (struct attribute *)&auth_save_signature) ||
0876             (attr == (struct attribute *)&auth_cert_thumb) ||
0877             (attr == (struct attribute *)&auth_cert_to_password)) {
0878         if ((setting == tlmi_priv.pwd_admin) && tlmi_priv.certificate_support)
0879             return attr->mode;
0880         return 0;
0881     }
0882 
0883     return attr->mode;
0884 }
0885 
0886 static struct attribute *auth_attrs[] = {
0887     &auth_is_pass_set.attr,
0888     &auth_min_pass_length.attr,
0889     &auth_max_pass_length.attr,
0890     &auth_current_password.attr,
0891     &auth_new_password.attr,
0892     &auth_role.attr,
0893     &auth_mechanism.attr,
0894     &auth_encoding.attr,
0895     &auth_kbdlang.attr,
0896     &auth_index.attr,
0897     &auth_level.attr,
0898     &auth_certificate.attr,
0899     &auth_signature.attr,
0900     &auth_save_signature.attr,
0901     &auth_cert_thumb.attr,
0902     &auth_cert_to_password.attr,
0903     NULL
0904 };
0905 
0906 static const struct attribute_group auth_attr_group = {
0907     .is_visible = auth_attr_is_visible,
0908     .attrs = auth_attrs,
0909 };
0910 
0911 /* ---- Attributes sysfs --------------------------------------------------------- */
0912 static ssize_t display_name_show(struct kobject *kobj, struct kobj_attribute *attr,
0913         char *buf)
0914 {
0915     struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
0916 
0917     return sysfs_emit(buf, "%s\n", setting->display_name);
0918 }
0919 
0920 static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
0921 {
0922     struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
0923     char *item, *value;
0924     int ret;
0925 
0926     ret = tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID);
0927     if (ret)
0928         return ret;
0929 
0930     /* validate and split from `item,value` -> `value` */
0931     value = strpbrk(item, ",");
0932     if (!value || value == item || !strlen(value + 1))
0933         return -EINVAL;
0934 
0935     ret = sysfs_emit(buf, "%s\n", value + 1);
0936     kfree(item);
0937     return ret;
0938 }
0939 
0940 static ssize_t possible_values_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
0941 {
0942     struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
0943 
0944     if (!tlmi_priv.can_get_bios_selections)
0945         return -EOPNOTSUPP;
0946 
0947     return sysfs_emit(buf, "%s\n", setting->possible_values);
0948 }
0949 
0950 static ssize_t current_value_store(struct kobject *kobj,
0951         struct kobj_attribute *attr,
0952         const char *buf, size_t count)
0953 {
0954     struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
0955     char *set_str = NULL, *new_setting = NULL;
0956     char *auth_str = NULL;
0957     int ret;
0958 
0959     if (!tlmi_priv.can_set_bios_settings)
0960         return -EOPNOTSUPP;
0961 
0962     new_setting = kstrdup(buf, GFP_KERNEL);
0963     if (!new_setting)
0964         return -ENOMEM;
0965 
0966     /* Strip out CR if one is present */
0967     strip_cr(new_setting);
0968 
0969     /* Check if certificate authentication is enabled and active */
0970     if (tlmi_priv.certificate_support && tlmi_priv.pwd_admin->cert_installed) {
0971         if (!tlmi_priv.pwd_admin->signature || !tlmi_priv.pwd_admin->save_signature) {
0972             ret = -EINVAL;
0973             goto out;
0974         }
0975         set_str = kasprintf(GFP_KERNEL, "%s,%s,%s", setting->display_name,
0976                     new_setting, tlmi_priv.pwd_admin->signature);
0977         if (!set_str) {
0978             ret = -ENOMEM;
0979             goto out;
0980         }
0981 
0982         ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTING_CERT_GUID, set_str);
0983         if (ret)
0984             goto out;
0985         ret = tlmi_simple_call(LENOVO_SAVE_BIOS_SETTING_CERT_GUID,
0986                 tlmi_priv.pwd_admin->save_signature);
0987         if (ret)
0988             goto out;
0989     } else { /* Non certiifcate based authentication */
0990         if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
0991             auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
0992                     tlmi_priv.pwd_admin->password,
0993                     encoding_options[tlmi_priv.pwd_admin->encoding],
0994                     tlmi_priv.pwd_admin->kbdlang);
0995             if (!auth_str) {
0996                 ret = -ENOMEM;
0997                 goto out;
0998             }
0999         }
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     }
1026 out:
1027     kfree(auth_str);
1028     kfree(set_str);
1029     kfree(new_setting);
1030     return ret ?: count;
1031 }
1032 
1033 static struct kobj_attribute attr_displ_name = __ATTR_RO(display_name);
1034 
1035 static struct kobj_attribute attr_possible_values = __ATTR_RO(possible_values);
1036 
1037 static struct kobj_attribute attr_current_val = __ATTR_RW_MODE(current_value, 0600);
1038 
1039 static struct attribute *tlmi_attrs[] = {
1040     &attr_displ_name.attr,
1041     &attr_current_val.attr,
1042     &attr_possible_values.attr,
1043     NULL
1044 };
1045 
1046 static const struct attribute_group tlmi_attr_group = {
1047     .attrs = tlmi_attrs,
1048 };
1049 
1050 static 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 
1061 static 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 
1072 static const struct sysfs_ops tlmi_kobj_sysfs_ops = {
1073     .show   = tlmi_attr_show,
1074     .store  = tlmi_attr_store,
1075 };
1076 
1077 static 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 
1085 static 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 
1092 static struct kobj_type tlmi_attr_setting_ktype = {
1093     .release        = &tlmi_attr_setting_release,
1094     .sysfs_ops  = &tlmi_kobj_sysfs_ops,
1095 };
1096 
1097 static struct kobj_type tlmi_pwd_setting_ktype = {
1098     .release        = &tlmi_pwd_setting_release,
1099     .sysfs_ops  = &tlmi_kobj_sysfs_ops,
1100 };
1101 
1102 static 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 
1108 static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot);
1109 
1110 /* ---- Debug interface--------------------------------------------------------- */
1111 static 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     }
1157 out:
1158     kfree(auth_str);
1159     kfree(set_str);
1160     kfree(new_setting);
1161     return ret ?: count;
1162 }
1163 
1164 static struct kobj_attribute debug_cmd = __ATTR_WO(debug_cmd);
1165 
1166 /* ---- Initialisation --------------------------------------------------------- */
1167 static 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 
1206 static 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 
1322 fail_create_attr:
1323     tlmi_release_attr();
1324 fail_device_created:
1325     device_destroy(fw_attr_class, MKDEV(0, 0));
1326 fail_class_created:
1327     fw_attributes_class_put();
1328     return ret;
1329 }
1330 
1331 /* ---- Base Driver -------------------------------------------------------- */
1332 static 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 
1354 static 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 
1501 fail_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 
1516 static 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 
1523 static 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 
1534 static const struct wmi_device_id tlmi_id_table[] = {
1535     { .guid_string = LENOVO_BIOS_SETTING_GUID },
1536     { }
1537 };
1538 MODULE_DEVICE_TABLE(wmi, tlmi_id_table);
1539 
1540 static 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 
1549 MODULE_AUTHOR("Sugumaran L <slacshiminar@lenovo.com>");
1550 MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>");
1551 MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>");
1552 MODULE_DESCRIPTION("ThinkLMI Driver");
1553 MODULE_LICENSE("GPL");
1554 
1555 module_wmi_driver(tlmi_driver);