162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Functions corresponding to password object type attributes under 462306a36Sopenharmony_ci * BIOS PASSWORD for use with hp-bioscfg driver. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (c) 2022 HP Development Company, L.P. 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "bioscfg.h" 1062306a36Sopenharmony_ci#include <asm-generic/posix_types.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciGET_INSTANCE_ID(password); 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci * Clear all passwords copied to memory for a particular 1562306a36Sopenharmony_ci * authentication instance 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_cistatic int clear_passwords(const int instance) 1862306a36Sopenharmony_ci{ 1962306a36Sopenharmony_ci struct password_data *password_data = &bioscfg_drv.password_data[instance]; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci if (!password_data->is_enabled) 2262306a36Sopenharmony_ci return 0; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci memset(password_data->current_password, 2562306a36Sopenharmony_ci 0, sizeof(password_data->current_password)); 2662306a36Sopenharmony_ci memset(password_data->new_password, 2762306a36Sopenharmony_ci 0, sizeof(password_data->new_password)); 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci return 0; 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * Clear all credentials copied to memory for both Power-ON and Setup 3462306a36Sopenharmony_ci * BIOS instances 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ciint hp_clear_all_credentials(void) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci int count = bioscfg_drv.password_instances_count; 3962306a36Sopenharmony_ci int instance; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci /* clear all passwords */ 4262306a36Sopenharmony_ci for (instance = 0; instance < count; instance++) 4362306a36Sopenharmony_ci clear_passwords(instance); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* clear auth_token */ 4662306a36Sopenharmony_ci kfree(bioscfg_drv.spm_data.auth_token); 4762306a36Sopenharmony_ci bioscfg_drv.spm_data.auth_token = NULL; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci return 0; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciint hp_get_password_instance_for_type(const char *name) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci int count = bioscfg_drv.password_instances_count; 5562306a36Sopenharmony_ci int instance; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci for (instance = 0; instance < count; instance++) 5862306a36Sopenharmony_ci if (!strcmp(bioscfg_drv.password_data[instance].common.display_name, name)) 5962306a36Sopenharmony_ci return instance; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return -EINVAL; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic int validate_password_input(int instance_id, const char *buf) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci int length; 6762306a36Sopenharmony_ci struct password_data *password_data = &bioscfg_drv.password_data[instance_id]; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci length = strlen(buf); 7062306a36Sopenharmony_ci if (buf[length - 1] == '\n') 7162306a36Sopenharmony_ci length--; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci if (length > MAX_PASSWD_SIZE) 7462306a36Sopenharmony_ci return INVALID_BIOS_AUTH; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (password_data->min_password_length > length || 7762306a36Sopenharmony_ci password_data->max_password_length < length) 7862306a36Sopenharmony_ci return INVALID_BIOS_AUTH; 7962306a36Sopenharmony_ci return SUCCESS; 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ciATTRIBUTE_N_PROPERTY_SHOW(is_enabled, password); 8362306a36Sopenharmony_cistatic struct kobj_attribute password_is_password_set = __ATTR_RO(is_enabled); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic int store_password_instance(struct kobject *kobj, const char *buf, 8662306a36Sopenharmony_ci size_t count, bool is_current) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci char *buf_cp; 8962306a36Sopenharmony_ci int id, ret = 0; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci buf_cp = kstrdup(buf, GFP_KERNEL); 9262306a36Sopenharmony_ci if (!buf_cp) 9362306a36Sopenharmony_ci return -ENOMEM; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci ret = hp_enforce_single_line_input(buf_cp, count); 9662306a36Sopenharmony_ci if (!ret) { 9762306a36Sopenharmony_ci id = get_password_instance_id(kobj); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci if (id >= 0) 10062306a36Sopenharmony_ci ret = validate_password_input(id, buf_cp); 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci if (!ret) { 10462306a36Sopenharmony_ci if (is_current) 10562306a36Sopenharmony_ci strscpy(bioscfg_drv.password_data[id].current_password, 10662306a36Sopenharmony_ci buf_cp, 10762306a36Sopenharmony_ci sizeof(bioscfg_drv.password_data[id].current_password)); 10862306a36Sopenharmony_ci else 10962306a36Sopenharmony_ci strscpy(bioscfg_drv.password_data[id].new_password, 11062306a36Sopenharmony_ci buf_cp, 11162306a36Sopenharmony_ci sizeof(bioscfg_drv.password_data[id].new_password)); 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci kfree(buf_cp); 11562306a36Sopenharmony_ci return ret < 0 ? ret : count; 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistatic ssize_t current_password_store(struct kobject *kobj, 11962306a36Sopenharmony_ci struct kobj_attribute *attr, 12062306a36Sopenharmony_ci const char *buf, size_t count) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci return store_password_instance(kobj, buf, count, true); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic struct kobj_attribute password_current_password = __ATTR_WO(current_password); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic ssize_t new_password_store(struct kobject *kobj, 12862306a36Sopenharmony_ci struct kobj_attribute *attr, 12962306a36Sopenharmony_ci const char *buf, size_t count) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci return store_password_instance(kobj, buf, count, true); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic struct kobj_attribute password_new_password = __ATTR_WO(new_password); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ciATTRIBUTE_N_PROPERTY_SHOW(min_password_length, password); 13762306a36Sopenharmony_cistatic struct kobj_attribute password_min_password_length = __ATTR_RO(min_password_length); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ciATTRIBUTE_N_PROPERTY_SHOW(max_password_length, password); 14062306a36Sopenharmony_cistatic struct kobj_attribute password_max_password_length = __ATTR_RO(max_password_length); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic ssize_t role_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci if (!strcmp(kobj->name, SETUP_PASSWD)) 14562306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", BIOS_ADMIN); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if (!strcmp(kobj->name, POWER_ON_PASSWD)) 14862306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", POWER_ON); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return -EIO; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic struct kobj_attribute password_role = __ATTR_RO(role); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic ssize_t mechanism_show(struct kobject *kobj, struct kobj_attribute *attr, 15662306a36Sopenharmony_ci char *buf) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci int i = get_password_instance_id(kobj); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci if (i < 0) 16162306a36Sopenharmony_ci return i; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci if (bioscfg_drv.password_data[i].mechanism != PASSWORD) 16462306a36Sopenharmony_ci return -EINVAL; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", PASSWD_MECHANISM_TYPES); 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic struct kobj_attribute password_mechanism = __ATTR_RO(mechanism); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ciATTRIBUTE_VALUES_PROPERTY_SHOW(encodings, password, SEMICOLON_SEP); 17262306a36Sopenharmony_cistatic struct kobj_attribute password_encodings_val = __ATTR_RO(encodings); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic struct attribute *password_attrs[] = { 17562306a36Sopenharmony_ci &password_is_password_set.attr, 17662306a36Sopenharmony_ci &password_min_password_length.attr, 17762306a36Sopenharmony_ci &password_max_password_length.attr, 17862306a36Sopenharmony_ci &password_current_password.attr, 17962306a36Sopenharmony_ci &password_new_password.attr, 18062306a36Sopenharmony_ci &password_role.attr, 18162306a36Sopenharmony_ci &password_mechanism.attr, 18262306a36Sopenharmony_ci &password_encodings_val.attr, 18362306a36Sopenharmony_ci NULL 18462306a36Sopenharmony_ci}; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_cistatic const struct attribute_group password_attr_group = { 18762306a36Sopenharmony_ci .attrs = password_attrs 18862306a36Sopenharmony_ci}; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ciint hp_alloc_password_data(void) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci bioscfg_drv.password_instances_count = hp_get_instance_count(HP_WMI_BIOS_PASSWORD_GUID); 19362306a36Sopenharmony_ci bioscfg_drv.password_data = kcalloc(bioscfg_drv.password_instances_count, 19462306a36Sopenharmony_ci sizeof(*bioscfg_drv.password_data), GFP_KERNEL); 19562306a36Sopenharmony_ci if (!bioscfg_drv.password_data) { 19662306a36Sopenharmony_ci bioscfg_drv.password_instances_count = 0; 19762306a36Sopenharmony_ci return -ENOMEM; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci return 0; 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci/* Expected Values types associated with each element */ 20462306a36Sopenharmony_cistatic const acpi_object_type expected_password_types[] = { 20562306a36Sopenharmony_ci [NAME] = ACPI_TYPE_STRING, 20662306a36Sopenharmony_ci [VALUE] = ACPI_TYPE_STRING, 20762306a36Sopenharmony_ci [PATH] = ACPI_TYPE_STRING, 20862306a36Sopenharmony_ci [IS_READONLY] = ACPI_TYPE_INTEGER, 20962306a36Sopenharmony_ci [DISPLAY_IN_UI] = ACPI_TYPE_INTEGER, 21062306a36Sopenharmony_ci [REQUIRES_PHYSICAL_PRESENCE] = ACPI_TYPE_INTEGER, 21162306a36Sopenharmony_ci [SEQUENCE] = ACPI_TYPE_INTEGER, 21262306a36Sopenharmony_ci [PREREQUISITES_SIZE] = ACPI_TYPE_INTEGER, 21362306a36Sopenharmony_ci [PREREQUISITES] = ACPI_TYPE_STRING, 21462306a36Sopenharmony_ci [SECURITY_LEVEL] = ACPI_TYPE_INTEGER, 21562306a36Sopenharmony_ci [PSWD_MIN_LENGTH] = ACPI_TYPE_INTEGER, 21662306a36Sopenharmony_ci [PSWD_MAX_LENGTH] = ACPI_TYPE_INTEGER, 21762306a36Sopenharmony_ci [PSWD_SIZE] = ACPI_TYPE_INTEGER, 21862306a36Sopenharmony_ci [PSWD_ENCODINGS] = ACPI_TYPE_STRING, 21962306a36Sopenharmony_ci [PSWD_IS_SET] = ACPI_TYPE_INTEGER, 22062306a36Sopenharmony_ci}; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic int hp_populate_password_elements_from_package(union acpi_object *password_obj, 22362306a36Sopenharmony_ci int password_obj_count, 22462306a36Sopenharmony_ci int instance_id) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci char *str_value = NULL; 22762306a36Sopenharmony_ci int value_len; 22862306a36Sopenharmony_ci int ret; 22962306a36Sopenharmony_ci u32 size; 23062306a36Sopenharmony_ci u32 int_value = 0; 23162306a36Sopenharmony_ci int elem; 23262306a36Sopenharmony_ci int reqs; 23362306a36Sopenharmony_ci int eloc; 23462306a36Sopenharmony_ci int pos_values; 23562306a36Sopenharmony_ci struct password_data *password_data = &bioscfg_drv.password_data[instance_id]; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci if (!password_obj) 23862306a36Sopenharmony_ci return -EINVAL; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci for (elem = 1, eloc = 1; elem < password_obj_count; elem++, eloc++) { 24162306a36Sopenharmony_ci /* ONLY look at the first PASSWORD_ELEM_CNT elements */ 24262306a36Sopenharmony_ci if (eloc == PSWD_ELEM_CNT) 24362306a36Sopenharmony_ci goto exit_package; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci switch (password_obj[elem].type) { 24662306a36Sopenharmony_ci case ACPI_TYPE_STRING: 24762306a36Sopenharmony_ci if (PREREQUISITES != elem && PSWD_ENCODINGS != elem) { 24862306a36Sopenharmony_ci ret = hp_convert_hexstr_to_str(password_obj[elem].string.pointer, 24962306a36Sopenharmony_ci password_obj[elem].string.length, 25062306a36Sopenharmony_ci &str_value, &value_len); 25162306a36Sopenharmony_ci if (ret) 25262306a36Sopenharmony_ci continue; 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci break; 25562306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 25662306a36Sopenharmony_ci int_value = (u32)password_obj[elem].integer.value; 25762306a36Sopenharmony_ci break; 25862306a36Sopenharmony_ci default: 25962306a36Sopenharmony_ci pr_warn("Unsupported object type [%d]\n", password_obj[elem].type); 26062306a36Sopenharmony_ci continue; 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* Check that both expected and read object type match */ 26462306a36Sopenharmony_ci if (expected_password_types[eloc] != password_obj[elem].type) { 26562306a36Sopenharmony_ci pr_err("Error expected type %d for elem %d, but got type %d instead\n", 26662306a36Sopenharmony_ci expected_password_types[eloc], elem, password_obj[elem].type); 26762306a36Sopenharmony_ci kfree(str_value); 26862306a36Sopenharmony_ci return -EIO; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* Assign appropriate element value to corresponding field*/ 27262306a36Sopenharmony_ci switch (eloc) { 27362306a36Sopenharmony_ci case VALUE: 27462306a36Sopenharmony_ci break; 27562306a36Sopenharmony_ci case PATH: 27662306a36Sopenharmony_ci strscpy(password_data->common.path, str_value, 27762306a36Sopenharmony_ci sizeof(password_data->common.path)); 27862306a36Sopenharmony_ci break; 27962306a36Sopenharmony_ci case IS_READONLY: 28062306a36Sopenharmony_ci password_data->common.is_readonly = int_value; 28162306a36Sopenharmony_ci break; 28262306a36Sopenharmony_ci case DISPLAY_IN_UI: 28362306a36Sopenharmony_ci password_data->common.display_in_ui = int_value; 28462306a36Sopenharmony_ci break; 28562306a36Sopenharmony_ci case REQUIRES_PHYSICAL_PRESENCE: 28662306a36Sopenharmony_ci password_data->common.requires_physical_presence = int_value; 28762306a36Sopenharmony_ci break; 28862306a36Sopenharmony_ci case SEQUENCE: 28962306a36Sopenharmony_ci password_data->common.sequence = int_value; 29062306a36Sopenharmony_ci break; 29162306a36Sopenharmony_ci case PREREQUISITES_SIZE: 29262306a36Sopenharmony_ci if (int_value > MAX_PREREQUISITES_SIZE) { 29362306a36Sopenharmony_ci pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n"); 29462306a36Sopenharmony_ci int_value = MAX_PREREQUISITES_SIZE; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci password_data->common.prerequisites_size = int_value; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* This step is needed to keep the expected 29962306a36Sopenharmony_ci * element list pointing to the right obj[elem].type 30062306a36Sopenharmony_ci * when the size is zero. PREREQUISITES 30162306a36Sopenharmony_ci * object is omitted by BIOS when the size is 30262306a36Sopenharmony_ci * zero. 30362306a36Sopenharmony_ci */ 30462306a36Sopenharmony_ci if (int_value == 0) 30562306a36Sopenharmony_ci eloc++; 30662306a36Sopenharmony_ci break; 30762306a36Sopenharmony_ci case PREREQUISITES: 30862306a36Sopenharmony_ci size = min_t(u32, password_data->common.prerequisites_size, 30962306a36Sopenharmony_ci MAX_PREREQUISITES_SIZE); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci for (reqs = 0; reqs < size; reqs++) { 31262306a36Sopenharmony_ci ret = hp_convert_hexstr_to_str(password_obj[elem + reqs].string.pointer, 31362306a36Sopenharmony_ci password_obj[elem + reqs].string.length, 31462306a36Sopenharmony_ci &str_value, &value_len); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (ret) 31762306a36Sopenharmony_ci break; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci strscpy(password_data->common.prerequisites[reqs], 32062306a36Sopenharmony_ci str_value, 32162306a36Sopenharmony_ci sizeof(password_data->common.prerequisites[reqs])); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci kfree(str_value); 32462306a36Sopenharmony_ci str_value = NULL; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci break; 32862306a36Sopenharmony_ci case SECURITY_LEVEL: 32962306a36Sopenharmony_ci password_data->common.security_level = int_value; 33062306a36Sopenharmony_ci break; 33162306a36Sopenharmony_ci case PSWD_MIN_LENGTH: 33262306a36Sopenharmony_ci password_data->min_password_length = int_value; 33362306a36Sopenharmony_ci break; 33462306a36Sopenharmony_ci case PSWD_MAX_LENGTH: 33562306a36Sopenharmony_ci password_data->max_password_length = int_value; 33662306a36Sopenharmony_ci break; 33762306a36Sopenharmony_ci case PSWD_SIZE: 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci if (int_value > MAX_ENCODINGS_SIZE) { 34062306a36Sopenharmony_ci pr_warn("Password Encoding size value exceeded the maximum number of elements supported or data may be malformed\n"); 34162306a36Sopenharmony_ci int_value = MAX_ENCODINGS_SIZE; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci password_data->encodings_size = int_value; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* This step is needed to keep the expected 34662306a36Sopenharmony_ci * element list pointing to the right obj[elem].type 34762306a36Sopenharmony_ci * when the size is zero. PSWD_ENCODINGS 34862306a36Sopenharmony_ci * object is omitted by BIOS when the size is 34962306a36Sopenharmony_ci * zero. 35062306a36Sopenharmony_ci */ 35162306a36Sopenharmony_ci if (int_value == 0) 35262306a36Sopenharmony_ci eloc++; 35362306a36Sopenharmony_ci break; 35462306a36Sopenharmony_ci case PSWD_ENCODINGS: 35562306a36Sopenharmony_ci size = min_t(u32, password_data->encodings_size, MAX_ENCODINGS_SIZE); 35662306a36Sopenharmony_ci for (pos_values = 0; pos_values < size; pos_values++) { 35762306a36Sopenharmony_ci ret = hp_convert_hexstr_to_str(password_obj[elem + pos_values].string.pointer, 35862306a36Sopenharmony_ci password_obj[elem + pos_values].string.length, 35962306a36Sopenharmony_ci &str_value, &value_len); 36062306a36Sopenharmony_ci if (ret) 36162306a36Sopenharmony_ci break; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci strscpy(password_data->encodings[pos_values], 36462306a36Sopenharmony_ci str_value, 36562306a36Sopenharmony_ci sizeof(password_data->encodings[pos_values])); 36662306a36Sopenharmony_ci kfree(str_value); 36762306a36Sopenharmony_ci str_value = NULL; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci break; 37162306a36Sopenharmony_ci case PSWD_IS_SET: 37262306a36Sopenharmony_ci password_data->is_enabled = int_value; 37362306a36Sopenharmony_ci break; 37462306a36Sopenharmony_ci default: 37562306a36Sopenharmony_ci pr_warn("Invalid element: %d found in Password attribute or data may be malformed\n", elem); 37662306a36Sopenharmony_ci break; 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci kfree(str_value); 38062306a36Sopenharmony_ci str_value = NULL; 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ciexit_package: 38462306a36Sopenharmony_ci kfree(str_value); 38562306a36Sopenharmony_ci return 0; 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci/** 38962306a36Sopenharmony_ci * hp_populate_password_package_data() 39062306a36Sopenharmony_ci * Populate all properties for an instance under password attribute 39162306a36Sopenharmony_ci * 39262306a36Sopenharmony_ci * @password_obj: ACPI object with password data 39362306a36Sopenharmony_ci * @instance_id: The instance to enumerate 39462306a36Sopenharmony_ci * @attr_name_kobj: The parent kernel object 39562306a36Sopenharmony_ci */ 39662306a36Sopenharmony_ciint hp_populate_password_package_data(union acpi_object *password_obj, int instance_id, 39762306a36Sopenharmony_ci struct kobject *attr_name_kobj) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci struct password_data *password_data = &bioscfg_drv.password_data[instance_id]; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci password_data->attr_name_kobj = attr_name_kobj; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci hp_populate_password_elements_from_package(password_obj, 40462306a36Sopenharmony_ci password_obj->package.count, 40562306a36Sopenharmony_ci instance_id); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci hp_friendly_user_name_update(password_data->common.path, 40862306a36Sopenharmony_ci attr_name_kobj->name, 40962306a36Sopenharmony_ci password_data->common.display_name, 41062306a36Sopenharmony_ci sizeof(password_data->common.display_name)); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci if (!strcmp(attr_name_kobj->name, SETUP_PASSWD)) 41362306a36Sopenharmony_ci return sysfs_create_group(attr_name_kobj, &password_attr_group); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci return sysfs_create_group(attr_name_kobj, &password_attr_group); 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic int hp_populate_password_elements_from_buffer(u8 *buffer_ptr, u32 *buffer_size, 41962306a36Sopenharmony_ci int instance_id) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci int values; 42262306a36Sopenharmony_ci int isreadonly; 42362306a36Sopenharmony_ci struct password_data *password_data = &bioscfg_drv.password_data[instance_id]; 42462306a36Sopenharmony_ci int ret = 0; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci /* 42762306a36Sopenharmony_ci * Only data relevant to this driver and its functionality is 42862306a36Sopenharmony_ci * read. BIOS defines the order in which each * element is 42962306a36Sopenharmony_ci * read. Element 0 data is not relevant to this 43062306a36Sopenharmony_ci * driver hence it is ignored. For clarity, all element names 43162306a36Sopenharmony_ci * (DISPLAY_IN_UI) which defines the order in which is read 43262306a36Sopenharmony_ci * and the name matches the variable where the data is stored. 43362306a36Sopenharmony_ci * 43462306a36Sopenharmony_ci * In earlier implementation, reported errors were ignored 43562306a36Sopenharmony_ci * causing the data to remain uninitialized. It is not 43662306a36Sopenharmony_ci * possible to determine if data read from BIOS is valid or 43762306a36Sopenharmony_ci * not. It is for this reason functions may return a error 43862306a36Sopenharmony_ci * without validating the data itself. 43962306a36Sopenharmony_ci */ 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci // VALUE: 44262306a36Sopenharmony_ci ret = hp_get_string_from_buffer(&buffer_ptr, buffer_size, password_data->current_password, 44362306a36Sopenharmony_ci sizeof(password_data->current_password)); 44462306a36Sopenharmony_ci if (ret < 0) 44562306a36Sopenharmony_ci goto buffer_exit; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci // COMMON: 44862306a36Sopenharmony_ci ret = hp_get_common_data_from_buffer(&buffer_ptr, buffer_size, 44962306a36Sopenharmony_ci &password_data->common); 45062306a36Sopenharmony_ci if (ret < 0) 45162306a36Sopenharmony_ci goto buffer_exit; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci // PSWD_MIN_LENGTH: 45462306a36Sopenharmony_ci ret = hp_get_integer_from_buffer(&buffer_ptr, buffer_size, 45562306a36Sopenharmony_ci &password_data->min_password_length); 45662306a36Sopenharmony_ci if (ret < 0) 45762306a36Sopenharmony_ci goto buffer_exit; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci // PSWD_MAX_LENGTH: 46062306a36Sopenharmony_ci ret = hp_get_integer_from_buffer(&buffer_ptr, buffer_size, 46162306a36Sopenharmony_ci &password_data->max_password_length); 46262306a36Sopenharmony_ci if (ret < 0) 46362306a36Sopenharmony_ci goto buffer_exit; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci // PSWD_SIZE: 46662306a36Sopenharmony_ci ret = hp_get_integer_from_buffer(&buffer_ptr, buffer_size, 46762306a36Sopenharmony_ci &password_data->encodings_size); 46862306a36Sopenharmony_ci if (ret < 0) 46962306a36Sopenharmony_ci goto buffer_exit; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci if (password_data->encodings_size > MAX_ENCODINGS_SIZE) { 47262306a36Sopenharmony_ci /* Report a message and limit possible values size to maximum value */ 47362306a36Sopenharmony_ci pr_warn("Password Encoding size value exceeded the maximum number of elements supported or data may be malformed\n"); 47462306a36Sopenharmony_ci password_data->encodings_size = MAX_ENCODINGS_SIZE; 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci // PSWD_ENCODINGS: 47862306a36Sopenharmony_ci for (values = 0; values < password_data->encodings_size; values++) { 47962306a36Sopenharmony_ci ret = hp_get_string_from_buffer(&buffer_ptr, buffer_size, 48062306a36Sopenharmony_ci password_data->encodings[values], 48162306a36Sopenharmony_ci sizeof(password_data->encodings[values])); 48262306a36Sopenharmony_ci if (ret < 0) 48362306a36Sopenharmony_ci break; 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci // PSWD_IS_SET: 48762306a36Sopenharmony_ci ret = hp_get_integer_from_buffer(&buffer_ptr, buffer_size, &isreadonly); 48862306a36Sopenharmony_ci if (ret < 0) 48962306a36Sopenharmony_ci goto buffer_exit; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci password_data->is_enabled = isreadonly ? true : false; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_cibuffer_exit: 49462306a36Sopenharmony_ci return ret; 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci/** 49862306a36Sopenharmony_ci * hp_populate_password_buffer_data() 49962306a36Sopenharmony_ci * Populate all properties for an instance under password object attribute 50062306a36Sopenharmony_ci * 50162306a36Sopenharmony_ci * @buffer_ptr: Buffer pointer 50262306a36Sopenharmony_ci * @buffer_size: Buffer size 50362306a36Sopenharmony_ci * @instance_id: The instance to enumerate 50462306a36Sopenharmony_ci * @attr_name_kobj: The parent kernel object 50562306a36Sopenharmony_ci */ 50662306a36Sopenharmony_ciint hp_populate_password_buffer_data(u8 *buffer_ptr, u32 *buffer_size, int instance_id, 50762306a36Sopenharmony_ci struct kobject *attr_name_kobj) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci struct password_data *password_data = &bioscfg_drv.password_data[instance_id]; 51062306a36Sopenharmony_ci int ret = 0; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci password_data->attr_name_kobj = attr_name_kobj; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci /* Populate Password attributes */ 51562306a36Sopenharmony_ci ret = hp_populate_password_elements_from_buffer(buffer_ptr, buffer_size, 51662306a36Sopenharmony_ci instance_id); 51762306a36Sopenharmony_ci if (ret < 0) 51862306a36Sopenharmony_ci return ret; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci hp_friendly_user_name_update(password_data->common.path, 52162306a36Sopenharmony_ci attr_name_kobj->name, 52262306a36Sopenharmony_ci password_data->common.display_name, 52362306a36Sopenharmony_ci sizeof(password_data->common.display_name)); 52462306a36Sopenharmony_ci if (!strcmp(attr_name_kobj->name, SETUP_PASSWD)) 52562306a36Sopenharmony_ci return sysfs_create_group(attr_name_kobj, &password_attr_group); 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci return sysfs_create_group(attr_name_kobj, &password_attr_group); 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci/** 53162306a36Sopenharmony_ci * hp_exit_password_attributes() - Clear all attribute data 53262306a36Sopenharmony_ci * 53362306a36Sopenharmony_ci * Clears all data allocated for this group of attributes 53462306a36Sopenharmony_ci */ 53562306a36Sopenharmony_civoid hp_exit_password_attributes(void) 53662306a36Sopenharmony_ci{ 53762306a36Sopenharmony_ci int instance_id; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci for (instance_id = 0; instance_id < bioscfg_drv.password_instances_count; 54062306a36Sopenharmony_ci instance_id++) { 54162306a36Sopenharmony_ci struct kobject *attr_name_kobj = 54262306a36Sopenharmony_ci bioscfg_drv.password_data[instance_id].attr_name_kobj; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci if (attr_name_kobj) { 54562306a36Sopenharmony_ci if (!strcmp(attr_name_kobj->name, SETUP_PASSWD)) 54662306a36Sopenharmony_ci sysfs_remove_group(attr_name_kobj, 54762306a36Sopenharmony_ci &password_attr_group); 54862306a36Sopenharmony_ci else 54962306a36Sopenharmony_ci sysfs_remove_group(attr_name_kobj, 55062306a36Sopenharmony_ci &password_attr_group); 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci bioscfg_drv.password_instances_count = 0; 55462306a36Sopenharmony_ci kfree(bioscfg_drv.password_data); 55562306a36Sopenharmony_ci bioscfg_drv.password_data = NULL; 55662306a36Sopenharmony_ci} 557