162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Functions corresponding to integer type attributes under 462306a36Sopenharmony_ci * BIOS Enumeration GUID for use with hp-bioscfg driver. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (c) 2022 Hewlett-Packard Inc. 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "bioscfg.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ciGET_INSTANCE_ID(integer); 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci int instance_id = get_integer_instance_id(kobj); 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci if (instance_id < 0) 1862306a36Sopenharmony_ci return -EIO; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", 2162306a36Sopenharmony_ci bioscfg_drv.integer_data[instance_id].current_value); 2262306a36Sopenharmony_ci} 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/** 2562306a36Sopenharmony_ci * validate_integer_input() - 2662306a36Sopenharmony_ci * Validate input of current_value against lower and upper bound 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * @instance_id: The instance on which input is validated 2962306a36Sopenharmony_ci * @buf: Input value 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_cistatic int validate_integer_input(int instance_id, char *buf) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci int in_val; 3462306a36Sopenharmony_ci int ret; 3562306a36Sopenharmony_ci struct integer_data *integer_data = &bioscfg_drv.integer_data[instance_id]; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci /* BIOS treats it as a read only attribute */ 3862306a36Sopenharmony_ci if (integer_data->common.is_readonly) 3962306a36Sopenharmony_ci return -EIO; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci ret = kstrtoint(buf, 10, &in_val); 4262306a36Sopenharmony_ci if (ret < 0) 4362306a36Sopenharmony_ci return ret; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci if (in_val < integer_data->lower_bound || 4662306a36Sopenharmony_ci in_val > integer_data->upper_bound) 4762306a36Sopenharmony_ci return -ERANGE; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci return 0; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic void update_integer_value(int instance_id, char *attr_value) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci int in_val; 5562306a36Sopenharmony_ci int ret; 5662306a36Sopenharmony_ci struct integer_data *integer_data = &bioscfg_drv.integer_data[instance_id]; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci ret = kstrtoint(attr_value, 10, &in_val); 5962306a36Sopenharmony_ci if (ret == 0) 6062306a36Sopenharmony_ci integer_data->current_value = in_val; 6162306a36Sopenharmony_ci else 6262306a36Sopenharmony_ci pr_warn("Invalid integer value found: %s\n", attr_value); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ciATTRIBUTE_S_COMMON_PROPERTY_SHOW(display_name, integer); 6662306a36Sopenharmony_cistatic struct kobj_attribute integer_display_name = 6762306a36Sopenharmony_ci __ATTR_RO(display_name); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciATTRIBUTE_PROPERTY_STORE(current_value, integer); 7062306a36Sopenharmony_cistatic struct kobj_attribute integer_current_val = 7162306a36Sopenharmony_ci __ATTR_RW_MODE(current_value, 0644); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciATTRIBUTE_N_PROPERTY_SHOW(lower_bound, integer); 7462306a36Sopenharmony_cistatic struct kobj_attribute integer_lower_bound = 7562306a36Sopenharmony_ci __ATTR_RO(lower_bound); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ciATTRIBUTE_N_PROPERTY_SHOW(upper_bound, integer); 7862306a36Sopenharmony_cistatic struct kobj_attribute integer_upper_bound = 7962306a36Sopenharmony_ci __ATTR_RO(upper_bound); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciATTRIBUTE_N_PROPERTY_SHOW(scalar_increment, integer); 8262306a36Sopenharmony_cistatic struct kobj_attribute integer_scalar_increment = 8362306a36Sopenharmony_ci __ATTR_RO(scalar_increment); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr, 8662306a36Sopenharmony_ci char *buf) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci return sysfs_emit(buf, "integer\n"); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic struct kobj_attribute integer_type = 9262306a36Sopenharmony_ci __ATTR_RO(type); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic struct attribute *integer_attrs[] = { 9562306a36Sopenharmony_ci &common_display_langcode.attr, 9662306a36Sopenharmony_ci &integer_display_name.attr, 9762306a36Sopenharmony_ci &integer_current_val.attr, 9862306a36Sopenharmony_ci &integer_lower_bound.attr, 9962306a36Sopenharmony_ci &integer_upper_bound.attr, 10062306a36Sopenharmony_ci &integer_scalar_increment.attr, 10162306a36Sopenharmony_ci &integer_type.attr, 10262306a36Sopenharmony_ci NULL 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic const struct attribute_group integer_attr_group = { 10662306a36Sopenharmony_ci .attrs = integer_attrs, 10762306a36Sopenharmony_ci}; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciint hp_alloc_integer_data(void) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci bioscfg_drv.integer_instances_count = hp_get_instance_count(HP_WMI_BIOS_INTEGER_GUID); 11262306a36Sopenharmony_ci bioscfg_drv.integer_data = kcalloc(bioscfg_drv.integer_instances_count, 11362306a36Sopenharmony_ci sizeof(*bioscfg_drv.integer_data), GFP_KERNEL); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci if (!bioscfg_drv.integer_data) { 11662306a36Sopenharmony_ci bioscfg_drv.integer_instances_count = 0; 11762306a36Sopenharmony_ci return -ENOMEM; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci return 0; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci/* Expected Values types associated with each element */ 12362306a36Sopenharmony_cistatic const acpi_object_type expected_integer_types[] = { 12462306a36Sopenharmony_ci [NAME] = ACPI_TYPE_STRING, 12562306a36Sopenharmony_ci [VALUE] = ACPI_TYPE_STRING, 12662306a36Sopenharmony_ci [PATH] = ACPI_TYPE_STRING, 12762306a36Sopenharmony_ci [IS_READONLY] = ACPI_TYPE_INTEGER, 12862306a36Sopenharmony_ci [DISPLAY_IN_UI] = ACPI_TYPE_INTEGER, 12962306a36Sopenharmony_ci [REQUIRES_PHYSICAL_PRESENCE] = ACPI_TYPE_INTEGER, 13062306a36Sopenharmony_ci [SEQUENCE] = ACPI_TYPE_INTEGER, 13162306a36Sopenharmony_ci [PREREQUISITES_SIZE] = ACPI_TYPE_INTEGER, 13262306a36Sopenharmony_ci [PREREQUISITES] = ACPI_TYPE_STRING, 13362306a36Sopenharmony_ci [SECURITY_LEVEL] = ACPI_TYPE_INTEGER, 13462306a36Sopenharmony_ci [INT_LOWER_BOUND] = ACPI_TYPE_INTEGER, 13562306a36Sopenharmony_ci [INT_UPPER_BOUND] = ACPI_TYPE_INTEGER, 13662306a36Sopenharmony_ci [INT_SCALAR_INCREMENT] = ACPI_TYPE_INTEGER, 13762306a36Sopenharmony_ci}; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic int hp_populate_integer_elements_from_package(union acpi_object *integer_obj, 14062306a36Sopenharmony_ci int integer_obj_count, 14162306a36Sopenharmony_ci int instance_id) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci char *str_value = NULL; 14462306a36Sopenharmony_ci int value_len; 14562306a36Sopenharmony_ci int ret; 14662306a36Sopenharmony_ci u32 int_value = 0; 14762306a36Sopenharmony_ci int elem; 14862306a36Sopenharmony_ci int reqs; 14962306a36Sopenharmony_ci int eloc; 15062306a36Sopenharmony_ci int size; 15162306a36Sopenharmony_ci struct integer_data *integer_data = &bioscfg_drv.integer_data[instance_id]; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (!integer_obj) 15462306a36Sopenharmony_ci return -EINVAL; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci for (elem = 1, eloc = 1; elem < integer_obj_count; elem++, eloc++) { 15762306a36Sopenharmony_ci /* ONLY look at the first INTEGER_ELEM_CNT elements */ 15862306a36Sopenharmony_ci if (eloc == INT_ELEM_CNT) 15962306a36Sopenharmony_ci goto exit_integer_package; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci switch (integer_obj[elem].type) { 16262306a36Sopenharmony_ci case ACPI_TYPE_STRING: 16362306a36Sopenharmony_ci if (elem != PREREQUISITES) { 16462306a36Sopenharmony_ci ret = hp_convert_hexstr_to_str(integer_obj[elem].string.pointer, 16562306a36Sopenharmony_ci integer_obj[elem].string.length, 16662306a36Sopenharmony_ci &str_value, &value_len); 16762306a36Sopenharmony_ci if (ret) 16862306a36Sopenharmony_ci continue; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 17262306a36Sopenharmony_ci int_value = (u32)integer_obj[elem].integer.value; 17362306a36Sopenharmony_ci break; 17462306a36Sopenharmony_ci default: 17562306a36Sopenharmony_ci pr_warn("Unsupported object type [%d]\n", integer_obj[elem].type); 17662306a36Sopenharmony_ci continue; 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci /* Check that both expected and read object type match */ 17962306a36Sopenharmony_ci if (expected_integer_types[eloc] != integer_obj[elem].type) { 18062306a36Sopenharmony_ci pr_err("Error expected type %d for elem %d, but got type %d instead\n", 18162306a36Sopenharmony_ci expected_integer_types[eloc], elem, integer_obj[elem].type); 18262306a36Sopenharmony_ci kfree(str_value); 18362306a36Sopenharmony_ci return -EIO; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci /* Assign appropriate element value to corresponding field*/ 18662306a36Sopenharmony_ci switch (eloc) { 18762306a36Sopenharmony_ci case VALUE: 18862306a36Sopenharmony_ci ret = kstrtoint(str_value, 10, &int_value); 18962306a36Sopenharmony_ci if (ret) 19062306a36Sopenharmony_ci continue; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci integer_data->current_value = int_value; 19362306a36Sopenharmony_ci break; 19462306a36Sopenharmony_ci case PATH: 19562306a36Sopenharmony_ci strscpy(integer_data->common.path, str_value, 19662306a36Sopenharmony_ci sizeof(integer_data->common.path)); 19762306a36Sopenharmony_ci break; 19862306a36Sopenharmony_ci case IS_READONLY: 19962306a36Sopenharmony_ci integer_data->common.is_readonly = int_value; 20062306a36Sopenharmony_ci break; 20162306a36Sopenharmony_ci case DISPLAY_IN_UI: 20262306a36Sopenharmony_ci integer_data->common.display_in_ui = int_value; 20362306a36Sopenharmony_ci break; 20462306a36Sopenharmony_ci case REQUIRES_PHYSICAL_PRESENCE: 20562306a36Sopenharmony_ci integer_data->common.requires_physical_presence = int_value; 20662306a36Sopenharmony_ci break; 20762306a36Sopenharmony_ci case SEQUENCE: 20862306a36Sopenharmony_ci integer_data->common.sequence = int_value; 20962306a36Sopenharmony_ci break; 21062306a36Sopenharmony_ci case PREREQUISITES_SIZE: 21162306a36Sopenharmony_ci if (int_value > MAX_PREREQUISITES_SIZE) { 21262306a36Sopenharmony_ci pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n"); 21362306a36Sopenharmony_ci int_value = MAX_PREREQUISITES_SIZE; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci integer_data->common.prerequisites_size = int_value; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* 21862306a36Sopenharmony_ci * This step is needed to keep the expected 21962306a36Sopenharmony_ci * element list pointing to the right obj[elem].type 22062306a36Sopenharmony_ci * when the size is zero. PREREQUISITES 22162306a36Sopenharmony_ci * object is omitted by BIOS when the size is 22262306a36Sopenharmony_ci * zero. 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_ci if (integer_data->common.prerequisites_size == 0) 22562306a36Sopenharmony_ci eloc++; 22662306a36Sopenharmony_ci break; 22762306a36Sopenharmony_ci case PREREQUISITES: 22862306a36Sopenharmony_ci size = min_t(u32, integer_data->common.prerequisites_size, MAX_PREREQUISITES_SIZE); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci for (reqs = 0; reqs < size; reqs++) { 23162306a36Sopenharmony_ci if (elem >= integer_obj_count) { 23262306a36Sopenharmony_ci pr_err("Error elem-objects package is too small\n"); 23362306a36Sopenharmony_ci return -EINVAL; 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci ret = hp_convert_hexstr_to_str(integer_obj[elem + reqs].string.pointer, 23762306a36Sopenharmony_ci integer_obj[elem + reqs].string.length, 23862306a36Sopenharmony_ci &str_value, &value_len); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if (ret) 24162306a36Sopenharmony_ci continue; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci strscpy(integer_data->common.prerequisites[reqs], 24462306a36Sopenharmony_ci str_value, 24562306a36Sopenharmony_ci sizeof(integer_data->common.prerequisites[reqs])); 24662306a36Sopenharmony_ci kfree(str_value); 24762306a36Sopenharmony_ci str_value = NULL; 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci case SECURITY_LEVEL: 25262306a36Sopenharmony_ci integer_data->common.security_level = int_value; 25362306a36Sopenharmony_ci break; 25462306a36Sopenharmony_ci case INT_LOWER_BOUND: 25562306a36Sopenharmony_ci integer_data->lower_bound = int_value; 25662306a36Sopenharmony_ci break; 25762306a36Sopenharmony_ci case INT_UPPER_BOUND: 25862306a36Sopenharmony_ci integer_data->upper_bound = int_value; 25962306a36Sopenharmony_ci break; 26062306a36Sopenharmony_ci case INT_SCALAR_INCREMENT: 26162306a36Sopenharmony_ci integer_data->scalar_increment = int_value; 26262306a36Sopenharmony_ci break; 26362306a36Sopenharmony_ci default: 26462306a36Sopenharmony_ci pr_warn("Invalid element: %d found in Integer attribute or data may be malformed\n", elem); 26562306a36Sopenharmony_ci break; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci kfree(str_value); 26962306a36Sopenharmony_ci str_value = NULL; 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ciexit_integer_package: 27262306a36Sopenharmony_ci kfree(str_value); 27362306a36Sopenharmony_ci return 0; 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci/** 27762306a36Sopenharmony_ci * hp_populate_integer_package_data() - 27862306a36Sopenharmony_ci * Populate all properties of an instance under integer attribute 27962306a36Sopenharmony_ci * 28062306a36Sopenharmony_ci * @integer_obj: ACPI object with integer data 28162306a36Sopenharmony_ci * @instance_id: The instance to enumerate 28262306a36Sopenharmony_ci * @attr_name_kobj: The parent kernel object 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_ciint hp_populate_integer_package_data(union acpi_object *integer_obj, 28562306a36Sopenharmony_ci int instance_id, 28662306a36Sopenharmony_ci struct kobject *attr_name_kobj) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci struct integer_data *integer_data = &bioscfg_drv.integer_data[instance_id]; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci integer_data->attr_name_kobj = attr_name_kobj; 29162306a36Sopenharmony_ci hp_populate_integer_elements_from_package(integer_obj, 29262306a36Sopenharmony_ci integer_obj->package.count, 29362306a36Sopenharmony_ci instance_id); 29462306a36Sopenharmony_ci hp_update_attribute_permissions(integer_data->common.is_readonly, 29562306a36Sopenharmony_ci &integer_current_val); 29662306a36Sopenharmony_ci hp_friendly_user_name_update(integer_data->common.path, 29762306a36Sopenharmony_ci attr_name_kobj->name, 29862306a36Sopenharmony_ci integer_data->common.display_name, 29962306a36Sopenharmony_ci sizeof(integer_data->common.display_name)); 30062306a36Sopenharmony_ci return sysfs_create_group(attr_name_kobj, &integer_attr_group); 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic int hp_populate_integer_elements_from_buffer(u8 *buffer_ptr, u32 *buffer_size, 30462306a36Sopenharmony_ci int instance_id) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci char *dst = NULL; 30762306a36Sopenharmony_ci int dst_size = *buffer_size / sizeof(u16); 30862306a36Sopenharmony_ci struct integer_data *integer_data = &bioscfg_drv.integer_data[instance_id]; 30962306a36Sopenharmony_ci int ret = 0; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci dst = kcalloc(dst_size, sizeof(char), GFP_KERNEL); 31262306a36Sopenharmony_ci if (!dst) 31362306a36Sopenharmony_ci return -ENOMEM; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* 31662306a36Sopenharmony_ci * Only data relevant to this driver and its functionality is 31762306a36Sopenharmony_ci * read. BIOS defines the order in which each * element is 31862306a36Sopenharmony_ci * read. Element 0 data is not relevant to this 31962306a36Sopenharmony_ci * driver hence it is ignored. For clarity, all element names 32062306a36Sopenharmony_ci * (DISPLAY_IN_UI) which defines the order in which is read 32162306a36Sopenharmony_ci * and the name matches the variable where the data is stored. 32262306a36Sopenharmony_ci * 32362306a36Sopenharmony_ci * In earlier implementation, reported errors were ignored 32462306a36Sopenharmony_ci * causing the data to remain uninitialized. It is not 32562306a36Sopenharmony_ci * possible to determine if data read from BIOS is valid or 32662306a36Sopenharmony_ci * not. It is for this reason functions may return a error 32762306a36Sopenharmony_ci * without validating the data itself. 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci // VALUE: 33162306a36Sopenharmony_ci integer_data->current_value = 0; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci hp_get_string_from_buffer(&buffer_ptr, buffer_size, dst, dst_size); 33462306a36Sopenharmony_ci ret = kstrtoint(dst, 10, &integer_data->current_value); 33562306a36Sopenharmony_ci if (ret) 33662306a36Sopenharmony_ci pr_warn("Unable to convert string to integer: %s\n", dst); 33762306a36Sopenharmony_ci kfree(dst); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci // COMMON: 34062306a36Sopenharmony_ci ret = hp_get_common_data_from_buffer(&buffer_ptr, buffer_size, &integer_data->common); 34162306a36Sopenharmony_ci if (ret < 0) 34262306a36Sopenharmony_ci goto buffer_exit; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci // INT_LOWER_BOUND: 34562306a36Sopenharmony_ci ret = hp_get_integer_from_buffer(&buffer_ptr, buffer_size, 34662306a36Sopenharmony_ci &integer_data->lower_bound); 34762306a36Sopenharmony_ci if (ret < 0) 34862306a36Sopenharmony_ci goto buffer_exit; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci // INT_UPPER_BOUND: 35162306a36Sopenharmony_ci ret = hp_get_integer_from_buffer(&buffer_ptr, buffer_size, 35262306a36Sopenharmony_ci &integer_data->upper_bound); 35362306a36Sopenharmony_ci if (ret < 0) 35462306a36Sopenharmony_ci goto buffer_exit; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci // INT_SCALAR_INCREMENT: 35762306a36Sopenharmony_ci ret = hp_get_integer_from_buffer(&buffer_ptr, buffer_size, 35862306a36Sopenharmony_ci &integer_data->scalar_increment); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cibuffer_exit: 36162306a36Sopenharmony_ci return ret; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci/** 36562306a36Sopenharmony_ci * hp_populate_integer_buffer_data() - 36662306a36Sopenharmony_ci * Populate all properties of an instance under integer attribute 36762306a36Sopenharmony_ci * 36862306a36Sopenharmony_ci * @buffer_ptr: Buffer pointer 36962306a36Sopenharmony_ci * @buffer_size: Buffer size 37062306a36Sopenharmony_ci * @instance_id: The instance to enumerate 37162306a36Sopenharmony_ci * @attr_name_kobj: The parent kernel object 37262306a36Sopenharmony_ci */ 37362306a36Sopenharmony_ciint hp_populate_integer_buffer_data(u8 *buffer_ptr, u32 *buffer_size, int instance_id, 37462306a36Sopenharmony_ci struct kobject *attr_name_kobj) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci struct integer_data *integer_data = &bioscfg_drv.integer_data[instance_id]; 37762306a36Sopenharmony_ci int ret = 0; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci integer_data->attr_name_kobj = attr_name_kobj; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci /* Populate integer elements */ 38262306a36Sopenharmony_ci ret = hp_populate_integer_elements_from_buffer(buffer_ptr, buffer_size, 38362306a36Sopenharmony_ci instance_id); 38462306a36Sopenharmony_ci if (ret < 0) 38562306a36Sopenharmony_ci return ret; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci hp_update_attribute_permissions(integer_data->common.is_readonly, 38862306a36Sopenharmony_ci &integer_current_val); 38962306a36Sopenharmony_ci hp_friendly_user_name_update(integer_data->common.path, 39062306a36Sopenharmony_ci attr_name_kobj->name, 39162306a36Sopenharmony_ci integer_data->common.display_name, 39262306a36Sopenharmony_ci sizeof(integer_data->common.display_name)); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci return sysfs_create_group(attr_name_kobj, &integer_attr_group); 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci/** 39862306a36Sopenharmony_ci * hp_exit_integer_attributes() - Clear all attribute data 39962306a36Sopenharmony_ci * 40062306a36Sopenharmony_ci * Clears all data allocated for this group of attributes 40162306a36Sopenharmony_ci */ 40262306a36Sopenharmony_civoid hp_exit_integer_attributes(void) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci int instance_id; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci for (instance_id = 0; instance_id < bioscfg_drv.integer_instances_count; 40762306a36Sopenharmony_ci instance_id++) { 40862306a36Sopenharmony_ci struct kobject *attr_name_kobj = 40962306a36Sopenharmony_ci bioscfg_drv.integer_data[instance_id].attr_name_kobj; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (attr_name_kobj) 41262306a36Sopenharmony_ci sysfs_remove_group(attr_name_kobj, &integer_attr_group); 41362306a36Sopenharmony_ci } 41462306a36Sopenharmony_ci bioscfg_drv.integer_instances_count = 0; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci kfree(bioscfg_drv.integer_data); 41762306a36Sopenharmony_ci bioscfg_drv.integer_data = NULL; 41862306a36Sopenharmony_ci} 419