/* Convert BIOS WMI error string to suitable error code */ staticint tlmi_errstr_to_err(constchar *errstr)
{ int i;
for (i = 0; i < sizeof(tlmi_errs)/sizeof(struct tlmi_err_codes); i++) { if (!strcmp(tlmi_errs[i].err_str, errstr)) return tlmi_errs[i].err_code;
} return -EPERM;
}
pwdlen = strlen(buf); /* pwdlen == 0 is allowed to clear the password */ if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) return -EINVAL;
strscpy(setting->password, buf, setting->maxlen); /* Strip out CR if one is present, setting password won't work if it is present */
strreplace(setting->password, '\n', '\0'); return count;
}
if (!tlmi_priv.can_set_bios_password) return -EOPNOTSUPP;
/* Strip out CR if one is present, setting password won't work if it is present */
new_pwd = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL); if (!new_pwd) return -ENOMEM;
/* Use lock in case multiple WMI operations needed */
mutex_lock(&tlmi_mutex);
pwdlen = strlen(new_pwd); /* pwdlen == 0 is allowed to clear the password */ if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) {
ret = -EINVAL; goto out;
}
/* If opcode support is present use that interface */ if (tlmi_priv.opcode_support) { char pwd_type[8];
/* Special handling required for HDD and NVMe passwords */ if (setting == tlmi_priv.pwd_hdd) { if (setting->level == TLMI_LEVEL_USER)
sprintf(pwd_type, "uhdp%d", setting->index); else
sprintf(pwd_type, "mhdp%d", setting->index);
} elseif (setting == tlmi_priv.pwd_nvme) { if (setting->level == TLMI_LEVEL_USER)
sprintf(pwd_type, "udrp%d", setting->index); else
sprintf(pwd_type, "adrp%d", setting->index);
} else {
sprintf(pwd_type, "%s", setting->pwd_type);
}
ret = tlmi_opcode_setting("WmiOpcodePasswordType", pwd_type); if (ret) goto out;
/* *NoteadminpasswordisnotalwaysrequiredifSMPControlenabledinBIOS, *Soonlysetifit'sconfigured. *LetBIOSfigureitout-we'llgetanerrorifoperationisnotpermitted
*/ if (tlmi_priv.pwd_admin->pwd_enabled && strlen(tlmi_priv.pwd_admin->password)) {
ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
tlmi_priv.pwd_admin->password); if (ret) goto out;
}
ret = tlmi_opcode_setting("WmiOpcodePasswordCurrent01", setting->password); if (ret) goto out;
ret = tlmi_opcode_setting("WmiOpcodePasswordNew01", new_pwd); if (ret) goto out;
ret = tlmi_simple_call(LENOVO_OPCODE_IF_GUID, "WmiOpcodePasswordSetUpdate;");
} else { /* Format: 'PasswordType,CurrentPw,NewPw,Encoding,KbdLang;' */
auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s,%s,%s;",
setting->pwd_type, setting->password, new_pwd,
encoding_options[setting->encoding], setting->kbdlang); if (!auth_str) {
ret = -ENOMEM; goto out;
}
ret = tlmi_simple_call(LENOVO_SET_BIOS_PASSWORD_GUID, auth_str);
kfree(auth_str);
}
out:
mutex_unlock(&tlmi_mutex);
kfree(new_pwd); return ret ?: count;
}
if (!tlmi_priv.certificate_support) return -EOPNOTSUPP;
/* If empty then clear installed certificate */ if ((buf[0] == '\0') || (buf[0] == '\n')) { /* Clear installed certificate */ /* Check that signature is set */ if (!setting->signature || !setting->signature[0]) return -EACCES;
/* Format: 'serial#, signature' */
serial = dmi_get_system_info(DMI_PRODUCT_SERIAL); if (!serial) return -ENODEV;
auth_str = cert_command(setting, serial, setting->signature); if (!auth_str) return -ENOMEM;
ret = tlmi_simple_call(LENOVO_CLEAR_BIOS_CERT_GUID, auth_str);
kfree(auth_str);
return ret ?: count;
}
/* Strip out CR if one is present */
new_cert = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL); if (!new_cert) return -ENOMEM;
if (setting->cert_installed) { /* Certificate is installed so this is an update */
install_mode = TLMI_CERT_UPDATE; /* If admin account enabled - need to use its signature */ if (tlmi_priv.pwd_admin->pwd_enabled)
signature = tlmi_priv.pwd_admin->signature; else
signature = setting->signature;
} else { /* Cert install */ /* Check if SMC and SVC already installed */ if ((setting == tlmi_priv.pwd_system) && tlmi_priv.pwd_admin->cert_installed) { /* This gets treated as a cert update */
install_mode = TLMI_CERT_UPDATE;
signature = tlmi_priv.pwd_admin->signature;
} else { /* Regular cert install */
install_mode = TLMI_CERT_INSTALL;
signature = setting->signature;
}
}
if (install_mode == TLMI_CERT_UPDATE) { /* This is a certificate update */ if (!signature || !signature[0]) {
kfree(new_cert); return -EACCES;
}
guid = LENOVO_UPDATE_BIOS_CERT_GUID; /* Format: 'Certificate,Signature' */
auth_str = cert_command(setting, new_cert, signature);
} else { /* This is a fresh install */ /* To set admin cert, a password must be enabled */ if ((setting == tlmi_priv.pwd_admin) &&
(!setting->pwd_enabled || !setting->password[0])) {
kfree(new_cert); return -EACCES;
}
guid = LENOVO_SET_BIOS_CERT_GUID; /* Format: 'Certificate, password' */
auth_str = cert_command(setting, new_cert, setting->password);
}
kfree(new_cert); if (!auth_str) return -ENOMEM;
ret = tlmi_simple_call(guid, auth_str);
kfree(auth_str);
/* We only want to display level and index settings on HDD/NVMe */ if (attr == &auth_index.attr || attr == &auth_level.attr) { if ((setting == tlmi_priv.pwd_hdd) || (setting == tlmi_priv.pwd_nvme)) return attr->mode; return0;
}
/* We only display certificates, if supported */ if (attr == &auth_certificate.attr ||
attr == &auth_signature.attr ||
attr == &auth_save_signature.attr ||
attr == &auth_cert_thumb.attr ||
attr == &auth_cert_to_password.attr) { if (tlmi_priv.certificate_support) { if (setting == tlmi_priv.pwd_admin) return attr->mode; if ((tlmi_priv.pwdcfg.core.password_mode >= TLMI_PWDCFG_MODE_MULTICERT) &&
(setting == tlmi_priv.pwd_system)) return attr->mode;
} return0;
}
/* Don't display un-needed settings if opcode available */ if ((attr == &auth_encoding.attr || attr == &auth_kbdlang.attr) &&
tlmi_priv.opcode_support) return0;
ret = tlmi_setting(setting->wdev, setting->index, &item); if (ret) return ret;
/* validate and split from `item,value` -> `value` */
value = strpbrk(item, ","); if (!value || value == item || !strlen(value + 1))
ret = -EINVAL; else { /* On Workstations remove the Options part after the value */
strreplace(value, ';', '\0');
ret = sysfs_emit(buf, "%s\n", value + 1);
}
kfree(item);
if (setting->possible_values) { /* Figure out what setting type is as BIOS does not return this */ if (strchr(setting->possible_values, ';')) return sysfs_emit(buf, "enumeration\n");
} /* Anything else is going to be a string */ return sysfs_emit(buf, "string\n");
}
/* Strip out CR if one is present */
new_setting = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL); if (!new_setting) return -ENOMEM;
/* Use lock in case multiple WMI operations needed */
mutex_lock(&tlmi_mutex);
/* Check if certificate authentication is enabled and active */ if (tlmi_priv.certificate_support && tlmi_priv.pwd_admin->cert_installed) { if (!tlmi_priv.pwd_admin->signature || !tlmi_priv.pwd_admin->save_signature) {
ret = -EINVAL; goto out;
}
set_str = kasprintf(GFP_KERNEL, "%s,%s,%s", setting->name,
new_setting, tlmi_priv.pwd_admin->signature); if (!set_str) {
ret = -ENOMEM; goto out;
}
ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTING_CERT_GUID, set_str); if (ret) goto out; if (tlmi_priv.save_mode == TLMI_SAVE_BULK)
tlmi_priv.save_required = true; else
ret = tlmi_simple_call(LENOVO_SAVE_BIOS_SETTING_CERT_GUID,
tlmi_priv.pwd_admin->save_signature);
} elseif (tlmi_priv.opcode_support) { /* *Ifopcodesupportispresentusethatinterface. *Note-thissetsthevariableandthenthepasswordasseparate *WMIcalls.Functiontlmi_save_bios_settingswillerrorifthe *passwordisincorrect. *Workstation'srequiretheopcodetobesetbeforechangingthe *attribute.
*/ if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) {
ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
tlmi_priv.pwd_admin->password); if (ret) goto out;
}
set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->name,
new_setting); if (!set_str) {
ret = -ENOMEM; goto out;
}
ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str); if (ret) goto out;
if (tlmi_priv.save_mode == TLMI_SAVE_BULK)
tlmi_priv.save_required = true; else
ret = tlmi_save_bios_settings("");
} else { /* old non-opcode based authentication method (deprecated) */ if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) {
auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
tlmi_priv.pwd_admin->password,
encoding_options[tlmi_priv.pwd_admin->encoding],
tlmi_priv.pwd_admin->kbdlang); if (!auth_str) {
ret = -ENOMEM; goto out;
}
}
if (auth_str)
set_str = kasprintf(GFP_KERNEL, "%s,%s,%s", setting->name,
new_setting, auth_str); else
set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->name,
new_setting); if (!set_str) {
ret = -ENOMEM; goto out;
}
ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str); if (ret) goto out;
if (tlmi_priv.save_mode == TLMI_SAVE_BULK) {
tlmi_priv.save_required = true;
} else { if (auth_str)
ret = tlmi_save_bios_settings(auth_str); else
ret = tlmi_save_bios_settings("");
}
} if (!ret && !tlmi_priv.pending_changes) {
tlmi_priv.pending_changes = true; /* let userland know it may need to check reboot pending again */
kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE);
}
out:
mutex_unlock(&tlmi_mutex);
kfree(auth_str);
kfree(set_str);
kfree(new_setting); return ret ?: count;
}
/* We don't want to display possible_values attributes if not available */ if ((attr == &attr_possible_values.attr) && (!setting->possible_values)) return0;
static ssize_t save_settings_store(struct kobject *kobj, struct kobj_attribute *attr, constchar *buf, size_t count)
{ char *auth_str = NULL; int ret = 0; int cmd;
cmd = sysfs_match_string(save_mode_strings, buf); if (cmd < 0) return cmd;
/* Use lock in case multiple WMI operations needed */
mutex_lock(&tlmi_mutex);
switch (cmd) { case TLMI_SAVE_SINGLE: case TLMI_SAVE_BULK:
tlmi_priv.save_mode = cmd; goto out; case TLMI_SAVE_SAVE: /* Check if supported*/ if (!tlmi_priv.can_set_bios_settings ||
tlmi_priv.save_mode == TLMI_SAVE_SINGLE) {
ret = -EOPNOTSUPP; goto out;
} /* Check there is actually something to save */ if (!tlmi_priv.save_required) {
ret = -ENOENT; goto out;
} /* Check if certificate authentication is enabled and active */ if (tlmi_priv.certificate_support && tlmi_priv.pwd_admin->cert_installed) { if (!tlmi_priv.pwd_admin->signature ||
!tlmi_priv.pwd_admin->save_signature) {
ret = -EINVAL; goto out;
}
ret = tlmi_simple_call(LENOVO_SAVE_BIOS_SETTING_CERT_GUID,
tlmi_priv.pwd_admin->save_signature); if (ret) goto out;
} elseif (tlmi_priv.opcode_support) { if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) {
ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
tlmi_priv.pwd_admin->password); if (ret) goto out;
}
ret = tlmi_save_bios_settings("");
} else { /* old non-opcode based authentication method (deprecated) */ if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) {
auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
tlmi_priv.pwd_admin->password,
encoding_options[tlmi_priv.pwd_admin->encoding],
tlmi_priv.pwd_admin->kbdlang); if (!auth_str) {
ret = -ENOMEM; goto out;
}
}
if (auth_str)
ret = tlmi_save_bios_settings(auth_str); else
ret = tlmi_save_bios_settings("");
}
tlmi_priv.save_required = false;
tlmi_priv.reboot_required = true;
if (!ret && !tlmi_priv.pending_changes) {
tlmi_priv.pending_changes = true; /* let userland know it may need to check reboot pending again */
kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE);
} break;
}
out:
mutex_unlock(&tlmi_mutex);
kfree(auth_str); return ret ?: count;
}
/* Strip out CR if one is present */
new_setting = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL); if (!new_setting) return -ENOMEM;
if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) {
auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
tlmi_priv.pwd_admin->password,
encoding_options[tlmi_priv.pwd_admin->encoding],
tlmi_priv.pwd_admin->kbdlang); if (!auth_str) {
ret = -ENOMEM; goto out;
}
}
if (auth_str)
set_str = kasprintf(GFP_KERNEL, "%s,%s", new_setting, auth_str); else
set_str = kasprintf(GFP_KERNEL, "%s;", new_setting); if (!set_str) {
ret = -ENOMEM; goto out;
}
ret = tlmi_simple_call(LENOVO_DEBUG_CMD_GUID, set_str); if (ret) goto out;
if (!ret && !tlmi_priv.pending_changes) {
tlmi_priv.pending_changes = true; /* let userland know it may need to check reboot pending again */
kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE);
}
out:
kfree(auth_str);
kfree(set_str);
kfree(new_setting); return ret ?: count;
}
duplicate = kset_find_obj(attribute_kset, name); if (duplicate) {
pr_debug("Duplicate attribute name found - %s\n", name); /* kset_find_obj() returns a reference */
kobject_put(duplicate); return -EBUSY;
}
return0;
}
staticint tlmi_sysfs_init(void)
{ int i, ret;
tlmi_priv.class_dev = device_create(&firmware_attributes_class, NULL, MKDEV(0, 0),
NULL, "%s", "thinklmi"); if (IS_ERR(tlmi_priv.class_dev)) {
ret = PTR_ERR(tlmi_priv.class_dev); goto fail_class_created;
}
tlmi_priv.attribute_kset = kset_create_and_add("attributes", NULL,
&tlmi_priv.class_dev->kobj); if (!tlmi_priv.attribute_kset) {
ret = -ENOMEM; goto fail_device_created;
}
tlmi_priv.authentication_kset = kset_create_and_add("authentication", NULL,
&tlmi_priv.class_dev->kobj); if (!tlmi_priv.authentication_kset) {
kset_unregister(tlmi_priv.attribute_kset);
ret = -ENOMEM; goto fail_device_created;
}
for (i = 0; i < TLMI_SETTINGS_COUNT; i++) { /* Check if index is a valid setting - skip if it isn't */ if (!tlmi_priv.setting[i]) continue;
/* check for duplicate or reserved values */ if (tlmi_validate_setting_name(tlmi_priv.attribute_kset,
tlmi_priv.setting[i]->display_name) < 0) {
kfree(tlmi_priv.setting[i]->possible_values);
kfree(tlmi_priv.setting[i]);
tlmi_priv.setting[i] = NULL; continue;
}
/* Build attribute */
tlmi_priv.setting[i]->kobj.kset = tlmi_priv.attribute_kset;
ret = kobject_init_and_add(&tlmi_priv.setting[i]->kobj, &tlmi_attr_setting_ktype,
NULL, "%s", tlmi_priv.setting[i]->display_name); if (ret) goto fail_create_attr;
}
ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr); if (ret) goto fail_create_attr;
ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &save_settings.attr); if (ret) goto fail_create_attr;
if (tlmi_priv.can_debug_cmd && debug_support) {
ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr); if (ret) goto fail_create_attr;
}
/* Create authentication entries */
tlmi_priv.pwd_admin->kobj.kset = tlmi_priv.authentication_kset;
ret = kobject_init_and_add(&tlmi_priv.pwd_admin->kobj, &tlmi_pwd_setting_ktype,
NULL, "%s", "Admin"); if (ret) goto fail_create_attr;
tlmi_priv.pwd_power->kobj.kset = tlmi_priv.authentication_kset;
ret = kobject_init_and_add(&tlmi_priv.pwd_power->kobj, &tlmi_pwd_setting_ktype,
NULL, "%s", "Power-on"); if (ret) goto fail_create_attr;
if (tlmi_priv.opcode_support) {
tlmi_priv.pwd_system->kobj.kset = tlmi_priv.authentication_kset;
ret = kobject_init_and_add(&tlmi_priv.pwd_system->kobj, &tlmi_pwd_setting_ktype,
NULL, "%s", "System"); if (ret) goto fail_create_attr;
tlmi_priv.pwd_hdd->kobj.kset = tlmi_priv.authentication_kset;
ret = kobject_init_and_add(&tlmi_priv.pwd_hdd->kobj, &tlmi_pwd_setting_ktype,
NULL, "%s", "HDD"); if (ret) goto fail_create_attr;
tlmi_priv.pwd_nvme->kobj.kset = tlmi_priv.authentication_kset;
ret = kobject_init_and_add(&tlmi_priv.pwd_nvme->kobj, &tlmi_pwd_setting_ktype,
NULL, "%s", "NVMe"); if (ret) goto fail_create_attr;
}
staticint tlmi_analyze(struct wmi_device *wdev)
{ int i, ret;
if (wmi_has_guid(LENOVO_SET_BIOS_SETTINGS_GUID) &&
wmi_has_guid(LENOVO_SAVE_BIOS_SETTINGS_GUID))
tlmi_priv.can_set_bios_settings = true;
if (wmi_has_guid(LENOVO_GET_BIOS_SELECTIONS_GUID))
tlmi_priv.can_get_bios_selections = true;
if (wmi_has_guid(LENOVO_SET_BIOS_PASSWORD_GUID))
tlmi_priv.can_set_bios_password = true;
if (wmi_has_guid(LENOVO_BIOS_PASSWORD_SETTINGS_GUID))
tlmi_priv.can_get_password_settings = true;
if (wmi_has_guid(LENOVO_DEBUG_CMD_GUID))
tlmi_priv.can_debug_cmd = true;
if (wmi_has_guid(LENOVO_OPCODE_IF_GUID))
tlmi_priv.opcode_support = true;
if (wmi_has_guid(LENOVO_SET_BIOS_CERT_GUID) &&
wmi_has_guid(LENOVO_SET_BIOS_SETTING_CERT_GUID) &&
wmi_has_guid(LENOVO_SAVE_BIOS_SETTING_CERT_GUID))
tlmi_priv.certificate_support = true;
/* *Trytofindthenumberofvalidsettingsofthismachine *anduseittocreatesysfsattributes.
*/ for (i = 0; i < TLMI_SETTINGS_COUNT; ++i) { struct tlmi_attr_setting *setting; char *item = NULL;
tlmi_priv.setting[i] = NULL;
ret = tlmi_setting(wdev, i, &item); if (ret) break; if (!item) break; if (!*item) {
kfree(item); continue;
}
/* Remove the value part */
strreplace(item, ',', '\0');
/* Create a setting entry */
setting = kzalloc(sizeof(*setting), GFP_KERNEL); if (!setting) {
ret = -ENOMEM;
kfree(item); goto fail_clear_attr;
}
setting->wdev = wdev;
setting->index = i;
strscpy(setting->name, item); /* It is not allowed to have '/' for file name. Convert it into '\'. */
strreplace(item, '/', '\\');
strscpy(setting->display_name, item);
/* If BIOS selections supported, load those */ if (tlmi_priv.can_get_bios_selections) {
ret = tlmi_get_bios_selections(setting->name,
&setting->possible_values); if (ret || !setting->possible_values)
pr_info("Error retrieving possible values for %d : %s\n",
i, setting->display_name);
} else { /* *OlderThinkstationsdon'tsupportthebios_selectionsAPI. *Insteadtheystorethisasa[Optional:Option1,Option2]sectionofthe *namestring. *Tryandpullthatoutifit'savailable.
*/ char *optitem, *optstart, *optend;
/* Create password setting structure */
ret = tlmi_get_pwd_settings(&tlmi_priv.pwdcfg); if (ret) goto fail_clear_attr;
/* All failures below boil down to kmalloc failures */
ret = -ENOMEM;
tlmi_priv.pwd_admin = tlmi_create_auth("pap", "bios-admin"); if (!tlmi_priv.pwd_admin) goto fail_clear_attr;
if (tlmi_priv.pwdcfg.core.password_state & TLMI_PAP_PWD)
tlmi_priv.pwd_admin->pwd_enabled = true;
tlmi_priv.pwd_power = tlmi_create_auth("pop", "power-on"); if (!tlmi_priv.pwd_power) goto fail_clear_attr;
if (tlmi_priv.pwdcfg.core.password_state & TLMI_POP_PWD)
tlmi_priv.pwd_power->pwd_enabled = true;
if (tlmi_priv.opcode_support) {
tlmi_priv.pwd_system = tlmi_create_auth("smp", "system"); if (!tlmi_priv.pwd_system) goto fail_clear_attr;
if (tlmi_priv.pwdcfg.core.password_state & TLMI_SMP_PWD)
tlmi_priv.pwd_system->pwd_enabled = true;
tlmi_priv.pwd_hdd = tlmi_create_auth("hdd", "hdd"); if (!tlmi_priv.pwd_hdd) goto fail_clear_attr;
tlmi_priv.pwd_nvme = tlmi_create_auth("nvm", "nvme"); if (!tlmi_priv.pwd_nvme) goto fail_clear_attr;
/* Set default hdd/nvme index to 1 as there is no device 0 */
tlmi_priv.pwd_hdd->index = 1;
tlmi_priv.pwd_nvme->index = 1;
if (tlmi_priv.pwdcfg.core.password_state & TLMI_HDD_PWD) { /* Check if PWD is configured and set index to first drive found */ if (tlmi_priv.pwdcfg.ext.hdd_user_password ||
tlmi_priv.pwdcfg.ext.hdd_master_password) {
tlmi_priv.pwd_hdd->pwd_enabled = true; if (tlmi_priv.pwdcfg.ext.hdd_master_password)
tlmi_priv.pwd_hdd->index =
ffs(tlmi_priv.pwdcfg.ext.hdd_master_password) - 1; else
tlmi_priv.pwd_hdd->index =
ffs(tlmi_priv.pwdcfg.ext.hdd_user_password) - 1;
} if (tlmi_priv.pwdcfg.ext.nvme_user_password ||
tlmi_priv.pwdcfg.ext.nvme_master_password) {
tlmi_priv.pwd_nvme->pwd_enabled = true; if (tlmi_priv.pwdcfg.ext.nvme_master_password)
tlmi_priv.pwd_nvme->index =
ffs(tlmi_priv.pwdcfg.ext.nvme_master_password) - 1; else
tlmi_priv.pwd_nvme->index =
ffs(tlmi_priv.pwdcfg.ext.nvme_user_password) - 1;
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.