16b2770bfSJorge Lopez // SPDX-License-Identifier: GPL-2.0
26b2770bfSJorge Lopez /*
36b2770bfSJorge Lopez * Functions corresponding to enumeration type attributes under
46b2770bfSJorge Lopez * BIOS Enumeration GUID for use with hp-bioscfg driver.
56b2770bfSJorge Lopez *
66b2770bfSJorge Lopez * Copyright (c) 2022 HP Development Company, L.P.
76b2770bfSJorge Lopez */
86b2770bfSJorge Lopez
96b2770bfSJorge Lopez #include "bioscfg.h"
106b2770bfSJorge Lopez
116b2770bfSJorge Lopez GET_INSTANCE_ID(enumeration);
126b2770bfSJorge Lopez
current_value_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)136b2770bfSJorge Lopez static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
146b2770bfSJorge Lopez {
156b2770bfSJorge Lopez int instance_id = get_enumeration_instance_id(kobj);
166b2770bfSJorge Lopez
176b2770bfSJorge Lopez if (instance_id < 0)
186b2770bfSJorge Lopez return -EIO;
196b2770bfSJorge Lopez
206b2770bfSJorge Lopez return sysfs_emit(buf, "%s\n",
216b2770bfSJorge Lopez bioscfg_drv.enumeration_data[instance_id].current_value);
226b2770bfSJorge Lopez }
236b2770bfSJorge Lopez
246b2770bfSJorge Lopez /**
256b2770bfSJorge Lopez * validate_enumeration_input() -
266b2770bfSJorge Lopez * Validate input of current_value against possible values
276b2770bfSJorge Lopez *
286b2770bfSJorge Lopez * @instance_id: The instance on which input is validated
296b2770bfSJorge Lopez * @buf: Input value
306b2770bfSJorge Lopez */
validate_enumeration_input(int instance_id,const char * buf)316b2770bfSJorge Lopez static int validate_enumeration_input(int instance_id, const char *buf)
326b2770bfSJorge Lopez {
336b2770bfSJorge Lopez int i;
346b2770bfSJorge Lopez int found = 0;
356b2770bfSJorge Lopez struct enumeration_data *enum_data = &bioscfg_drv.enumeration_data[instance_id];
366b2770bfSJorge Lopez
376b2770bfSJorge Lopez /* Is it a read only attribute */
386b2770bfSJorge Lopez if (enum_data->common.is_readonly)
396b2770bfSJorge Lopez return -EIO;
406b2770bfSJorge Lopez
416b2770bfSJorge Lopez for (i = 0; i < enum_data->possible_values_size && !found; i++)
426b2770bfSJorge Lopez if (!strcmp(enum_data->possible_values[i], buf))
436b2770bfSJorge Lopez found = 1;
446b2770bfSJorge Lopez
456b2770bfSJorge Lopez if (!found)
466b2770bfSJorge Lopez return -EINVAL;
476b2770bfSJorge Lopez
486b2770bfSJorge Lopez return 0;
496b2770bfSJorge Lopez }
506b2770bfSJorge Lopez
update_enumeration_value(int instance_id,char * attr_value)516b2770bfSJorge Lopez static void update_enumeration_value(int instance_id, char *attr_value)
526b2770bfSJorge Lopez {
536b2770bfSJorge Lopez struct enumeration_data *enum_data = &bioscfg_drv.enumeration_data[instance_id];
546b2770bfSJorge Lopez
556b2770bfSJorge Lopez strscpy(enum_data->current_value,
566b2770bfSJorge Lopez attr_value,
576b2770bfSJorge Lopez sizeof(enum_data->current_value));
586b2770bfSJorge Lopez }
596b2770bfSJorge Lopez
606b2770bfSJorge Lopez ATTRIBUTE_S_COMMON_PROPERTY_SHOW(display_name, enumeration);
616b2770bfSJorge Lopez static struct kobj_attribute enumeration_display_name =
626b2770bfSJorge Lopez __ATTR_RO(display_name);
636b2770bfSJorge Lopez
646b2770bfSJorge Lopez ATTRIBUTE_PROPERTY_STORE(current_value, enumeration);
656b2770bfSJorge Lopez static struct kobj_attribute enumeration_current_val =
666b2770bfSJorge Lopez __ATTR_RW(current_value);
676b2770bfSJorge Lopez
686b2770bfSJorge Lopez ATTRIBUTE_VALUES_PROPERTY_SHOW(possible_values, enumeration, SEMICOLON_SEP);
696b2770bfSJorge Lopez static struct kobj_attribute enumeration_poss_val =
706b2770bfSJorge Lopez __ATTR_RO(possible_values);
716b2770bfSJorge Lopez
type_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)726b2770bfSJorge Lopez static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
736b2770bfSJorge Lopez char *buf)
746b2770bfSJorge Lopez {
756b2770bfSJorge Lopez return sysfs_emit(buf, "enumeration\n");
766b2770bfSJorge Lopez }
776b2770bfSJorge Lopez
786b2770bfSJorge Lopez static struct kobj_attribute enumeration_type =
796b2770bfSJorge Lopez __ATTR_RO(type);
806b2770bfSJorge Lopez
816b2770bfSJorge Lopez static struct attribute *enumeration_attrs[] = {
826b2770bfSJorge Lopez &common_display_langcode.attr,
836b2770bfSJorge Lopez &enumeration_display_name.attr,
846b2770bfSJorge Lopez &enumeration_current_val.attr,
856b2770bfSJorge Lopez &enumeration_poss_val.attr,
866b2770bfSJorge Lopez &enumeration_type.attr,
876b2770bfSJorge Lopez NULL
886b2770bfSJorge Lopez };
896b2770bfSJorge Lopez
906b2770bfSJorge Lopez static const struct attribute_group enumeration_attr_group = {
916b2770bfSJorge Lopez .attrs = enumeration_attrs,
926b2770bfSJorge Lopez };
936b2770bfSJorge Lopez
hp_alloc_enumeration_data(void)946b2770bfSJorge Lopez int hp_alloc_enumeration_data(void)
956b2770bfSJorge Lopez {
966b2770bfSJorge Lopez bioscfg_drv.enumeration_instances_count =
976b2770bfSJorge Lopez hp_get_instance_count(HP_WMI_BIOS_ENUMERATION_GUID);
986b2770bfSJorge Lopez
996b2770bfSJorge Lopez bioscfg_drv.enumeration_data = kcalloc(bioscfg_drv.enumeration_instances_count,
1006b2770bfSJorge Lopez sizeof(*bioscfg_drv.enumeration_data), GFP_KERNEL);
1016b2770bfSJorge Lopez if (!bioscfg_drv.enumeration_data) {
1026b2770bfSJorge Lopez bioscfg_drv.enumeration_instances_count = 0;
1036b2770bfSJorge Lopez return -ENOMEM;
1046b2770bfSJorge Lopez }
1056b2770bfSJorge Lopez return 0;
1066b2770bfSJorge Lopez }
1076b2770bfSJorge Lopez
1086b2770bfSJorge Lopez /* Expected Values types associated with each element */
1096b2770bfSJorge Lopez static const acpi_object_type expected_enum_types[] = {
1106b2770bfSJorge Lopez [NAME] = ACPI_TYPE_STRING,
1116b2770bfSJorge Lopez [VALUE] = ACPI_TYPE_STRING,
1126b2770bfSJorge Lopez [PATH] = ACPI_TYPE_STRING,
1136b2770bfSJorge Lopez [IS_READONLY] = ACPI_TYPE_INTEGER,
1146b2770bfSJorge Lopez [DISPLAY_IN_UI] = ACPI_TYPE_INTEGER,
1156b2770bfSJorge Lopez [REQUIRES_PHYSICAL_PRESENCE] = ACPI_TYPE_INTEGER,
1166b2770bfSJorge Lopez [SEQUENCE] = ACPI_TYPE_INTEGER,
1176b2770bfSJorge Lopez [PREREQUISITES_SIZE] = ACPI_TYPE_INTEGER,
1186b2770bfSJorge Lopez [PREREQUISITES] = ACPI_TYPE_STRING,
1196b2770bfSJorge Lopez [SECURITY_LEVEL] = ACPI_TYPE_INTEGER,
1206b2770bfSJorge Lopez [ENUM_CURRENT_VALUE] = ACPI_TYPE_STRING,
1216b2770bfSJorge Lopez [ENUM_SIZE] = ACPI_TYPE_INTEGER,
1226b2770bfSJorge Lopez [ENUM_POSSIBLE_VALUES] = ACPI_TYPE_STRING,
1236b2770bfSJorge Lopez };
1246b2770bfSJorge Lopez
hp_populate_enumeration_elements_from_package(union acpi_object * enum_obj,int enum_obj_count,int instance_id)1256b2770bfSJorge Lopez static int hp_populate_enumeration_elements_from_package(union acpi_object *enum_obj,
1266b2770bfSJorge Lopez int enum_obj_count,
1276b2770bfSJorge Lopez int instance_id)
1286b2770bfSJorge Lopez {
1296b2770bfSJorge Lopez char *str_value = NULL;
1306b2770bfSJorge Lopez int value_len;
1316b2770bfSJorge Lopez u32 size = 0;
13280d7ba30SJorge Lopez u32 int_value = 0;
1336b2770bfSJorge Lopez int elem = 0;
1346b2770bfSJorge Lopez int reqs;
1356b2770bfSJorge Lopez int pos_values;
1366b2770bfSJorge Lopez int ret;
1376b2770bfSJorge Lopez int eloc;
1386b2770bfSJorge Lopez struct enumeration_data *enum_data = &bioscfg_drv.enumeration_data[instance_id];
1396b2770bfSJorge Lopez
1406b2770bfSJorge Lopez for (elem = 1, eloc = 1; elem < enum_obj_count; elem++, eloc++) {
1416b2770bfSJorge Lopez /* ONLY look at the first ENUM_ELEM_CNT elements */
1426b2770bfSJorge Lopez if (eloc == ENUM_ELEM_CNT)
1436b2770bfSJorge Lopez goto exit_enumeration_package;
1446b2770bfSJorge Lopez
1456b2770bfSJorge Lopez switch (enum_obj[elem].type) {
1466b2770bfSJorge Lopez case ACPI_TYPE_STRING:
1476b2770bfSJorge Lopez if (PREREQUISITES != elem && ENUM_POSSIBLE_VALUES != elem) {
1486b2770bfSJorge Lopez ret = hp_convert_hexstr_to_str(enum_obj[elem].string.pointer,
1496b2770bfSJorge Lopez enum_obj[elem].string.length,
1506b2770bfSJorge Lopez &str_value, &value_len);
1516b2770bfSJorge Lopez if (ret)
1526b2770bfSJorge Lopez return -EINVAL;
1536b2770bfSJorge Lopez }
1546b2770bfSJorge Lopez break;
1556b2770bfSJorge Lopez case ACPI_TYPE_INTEGER:
1566b2770bfSJorge Lopez int_value = (u32)enum_obj[elem].integer.value;
1576b2770bfSJorge Lopez break;
1586b2770bfSJorge Lopez default:
1596b2770bfSJorge Lopez pr_warn("Unsupported object type [%d]\n", enum_obj[elem].type);
1606b2770bfSJorge Lopez continue;
1616b2770bfSJorge Lopez }
1626b2770bfSJorge Lopez
1636b2770bfSJorge Lopez /* Check that both expected and read object type match */
1646b2770bfSJorge Lopez if (expected_enum_types[eloc] != enum_obj[elem].type) {
1656b2770bfSJorge Lopez pr_err("Error expected type %d for elem %d, but got type %d instead\n",
1666b2770bfSJorge Lopez expected_enum_types[eloc], elem, enum_obj[elem].type);
167467d4163SJorge Lopez kfree(str_value);
1686b2770bfSJorge Lopez return -EIO;
1696b2770bfSJorge Lopez }
1706b2770bfSJorge Lopez
1716b2770bfSJorge Lopez /* Assign appropriate element value to corresponding field */
1726b2770bfSJorge Lopez switch (eloc) {
1736b2770bfSJorge Lopez case NAME:
1746b2770bfSJorge Lopez case VALUE:
1756b2770bfSJorge Lopez break;
1766b2770bfSJorge Lopez case PATH:
1776b2770bfSJorge Lopez strscpy(enum_data->common.path, str_value,
1786b2770bfSJorge Lopez sizeof(enum_data->common.path));
1796b2770bfSJorge Lopez break;
1806b2770bfSJorge Lopez case IS_READONLY:
1816b2770bfSJorge Lopez enum_data->common.is_readonly = int_value;
1826b2770bfSJorge Lopez break;
1836b2770bfSJorge Lopez case DISPLAY_IN_UI:
1846b2770bfSJorge Lopez enum_data->common.display_in_ui = int_value;
1856b2770bfSJorge Lopez break;
1866b2770bfSJorge Lopez case REQUIRES_PHYSICAL_PRESENCE:
1876b2770bfSJorge Lopez enum_data->common.requires_physical_presence = int_value;
1886b2770bfSJorge Lopez break;
1896b2770bfSJorge Lopez case SEQUENCE:
1906b2770bfSJorge Lopez enum_data->common.sequence = int_value;
1916b2770bfSJorge Lopez break;
1926b2770bfSJorge Lopez case PREREQUISITES_SIZE:
19308f1f212SJorge Lopez if (int_value > MAX_PREREQUISITES_SIZE) {
1946b2770bfSJorge Lopez pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n");
19508f1f212SJorge Lopez int_value = MAX_PREREQUISITES_SIZE;
19608f1f212SJorge Lopez }
19708f1f212SJorge Lopez enum_data->common.prerequisites_size = int_value;
1986b2770bfSJorge Lopez
1996b2770bfSJorge Lopez /*
200a585400bSJorge Lopez * This step is needed to keep the expected
2016b2770bfSJorge Lopez * element list pointing to the right obj[elem].type
2026b2770bfSJorge Lopez * when the size is zero. PREREQUISITES
2036b2770bfSJorge Lopez * object is omitted by BIOS when the size is
2046b2770bfSJorge Lopez * zero.
2056b2770bfSJorge Lopez */
2066b2770bfSJorge Lopez if (int_value == 0)
2076b2770bfSJorge Lopez eloc++;
2086b2770bfSJorge Lopez break;
2096b2770bfSJorge Lopez
2106b2770bfSJorge Lopez case PREREQUISITES:
2116b2770bfSJorge Lopez size = min_t(u32, enum_data->common.prerequisites_size, MAX_PREREQUISITES_SIZE);
2126b2770bfSJorge Lopez for (reqs = 0; reqs < size; reqs++) {
2136b2770bfSJorge Lopez if (elem >= enum_obj_count) {
2146b2770bfSJorge Lopez pr_err("Error enum-objects package is too small\n");
2156b2770bfSJorge Lopez return -EINVAL;
2166b2770bfSJorge Lopez }
2176b2770bfSJorge Lopez
2186b2770bfSJorge Lopez ret = hp_convert_hexstr_to_str(enum_obj[elem + reqs].string.pointer,
2196b2770bfSJorge Lopez enum_obj[elem + reqs].string.length,
2206b2770bfSJorge Lopez &str_value, &value_len);
2216b2770bfSJorge Lopez
2226b2770bfSJorge Lopez if (ret)
2236b2770bfSJorge Lopez return -EINVAL;
2246b2770bfSJorge Lopez
2256b2770bfSJorge Lopez strscpy(enum_data->common.prerequisites[reqs],
2266b2770bfSJorge Lopez str_value,
2276b2770bfSJorge Lopez sizeof(enum_data->common.prerequisites[reqs]));
2286b2770bfSJorge Lopez
2296b2770bfSJorge Lopez kfree(str_value);
230467d4163SJorge Lopez str_value = NULL;
2316b2770bfSJorge Lopez }
2326b2770bfSJorge Lopez break;
2336b2770bfSJorge Lopez
2346b2770bfSJorge Lopez case SECURITY_LEVEL:
2356b2770bfSJorge Lopez enum_data->common.security_level = int_value;
2366b2770bfSJorge Lopez break;
2376b2770bfSJorge Lopez
2386b2770bfSJorge Lopez case ENUM_CURRENT_VALUE:
2396b2770bfSJorge Lopez strscpy(enum_data->current_value,
2406b2770bfSJorge Lopez str_value, sizeof(enum_data->current_value));
2416b2770bfSJorge Lopez break;
2426b2770bfSJorge Lopez case ENUM_SIZE:
243*42efc9e6SJorge Lopez if (int_value > MAX_VALUES_SIZE) {
2446b2770bfSJorge Lopez pr_warn("Possible number values size value exceeded the maximum number of elements supported or data may be malformed\n");
245*42efc9e6SJorge Lopez int_value = MAX_VALUES_SIZE;
246*42efc9e6SJorge Lopez }
247*42efc9e6SJorge Lopez enum_data->possible_values_size = int_value;
2486b2770bfSJorge Lopez
2496b2770bfSJorge Lopez /*
250a585400bSJorge Lopez * This step is needed to keep the expected
2516b2770bfSJorge Lopez * element list pointing to the right obj[elem].type
2526b2770bfSJorge Lopez * when the size is zero. POSSIBLE_VALUES
2536b2770bfSJorge Lopez * object is omitted by BIOS when the size is zero.
2546b2770bfSJorge Lopez */
2556b2770bfSJorge Lopez if (int_value == 0)
2566b2770bfSJorge Lopez eloc++;
2576b2770bfSJorge Lopez break;
2586b2770bfSJorge Lopez
2596b2770bfSJorge Lopez case ENUM_POSSIBLE_VALUES:
2606b2770bfSJorge Lopez size = enum_data->possible_values_size;
2616b2770bfSJorge Lopez
2626b2770bfSJorge Lopez for (pos_values = 0; pos_values < size && pos_values < MAX_VALUES_SIZE;
2636b2770bfSJorge Lopez pos_values++) {
2646b2770bfSJorge Lopez if (elem >= enum_obj_count) {
2656b2770bfSJorge Lopez pr_err("Error enum-objects package is too small\n");
2666b2770bfSJorge Lopez return -EINVAL;
2676b2770bfSJorge Lopez }
2686b2770bfSJorge Lopez
2696b2770bfSJorge Lopez ret = hp_convert_hexstr_to_str(enum_obj[elem + pos_values].string.pointer,
2706b2770bfSJorge Lopez enum_obj[elem + pos_values].string.length,
2716b2770bfSJorge Lopez &str_value, &value_len);
2726b2770bfSJorge Lopez
2736b2770bfSJorge Lopez if (ret)
2746b2770bfSJorge Lopez return -EINVAL;
2756b2770bfSJorge Lopez
2766b2770bfSJorge Lopez /*
2776b2770bfSJorge Lopez * ignore strings when possible values size
2786b2770bfSJorge Lopez * is greater than MAX_VALUES_SIZE
2796b2770bfSJorge Lopez */
2806b2770bfSJorge Lopez if (size < MAX_VALUES_SIZE)
2816b2770bfSJorge Lopez strscpy(enum_data->possible_values[pos_values],
2826b2770bfSJorge Lopez str_value,
2836b2770bfSJorge Lopez sizeof(enum_data->possible_values[pos_values]));
284467d4163SJorge Lopez
285467d4163SJorge Lopez kfree(str_value);
286467d4163SJorge Lopez str_value = NULL;
2876b2770bfSJorge Lopez }
2886b2770bfSJorge Lopez break;
2896b2770bfSJorge Lopez default:
2906b2770bfSJorge Lopez pr_warn("Invalid element: %d found in Enumeration attribute or data may be malformed\n", elem);
2916b2770bfSJorge Lopez break;
2926b2770bfSJorge Lopez }
2936b2770bfSJorge Lopez
2946b2770bfSJorge Lopez kfree(str_value);
295467d4163SJorge Lopez str_value = NULL;
2966b2770bfSJorge Lopez }
2976b2770bfSJorge Lopez
2986b2770bfSJorge Lopez exit_enumeration_package:
2996b2770bfSJorge Lopez kfree(str_value);
3006b2770bfSJorge Lopez return 0;
3016b2770bfSJorge Lopez }
3026b2770bfSJorge Lopez
3036b2770bfSJorge Lopez /**
3046b2770bfSJorge Lopez * hp_populate_enumeration_package_data() -
3056b2770bfSJorge Lopez * Populate all properties of an instance under enumeration attribute
3066b2770bfSJorge Lopez *
3076b2770bfSJorge Lopez * @enum_obj: ACPI object with enumeration data
3086b2770bfSJorge Lopez * @instance_id: The instance to enumerate
3096b2770bfSJorge Lopez * @attr_name_kobj: The parent kernel object
3106b2770bfSJorge Lopez */
hp_populate_enumeration_package_data(union acpi_object * enum_obj,int instance_id,struct kobject * attr_name_kobj)3116b2770bfSJorge Lopez int hp_populate_enumeration_package_data(union acpi_object *enum_obj,
3126b2770bfSJorge Lopez int instance_id,
3136b2770bfSJorge Lopez struct kobject *attr_name_kobj)
3146b2770bfSJorge Lopez {
3156b2770bfSJorge Lopez struct enumeration_data *enum_data = &bioscfg_drv.enumeration_data[instance_id];
3166b2770bfSJorge Lopez
3176b2770bfSJorge Lopez enum_data->attr_name_kobj = attr_name_kobj;
3186b2770bfSJorge Lopez
3196b2770bfSJorge Lopez hp_populate_enumeration_elements_from_package(enum_obj,
3206b2770bfSJorge Lopez enum_obj->package.count,
3216b2770bfSJorge Lopez instance_id);
3226b2770bfSJorge Lopez hp_update_attribute_permissions(enum_data->common.is_readonly,
3236b2770bfSJorge Lopez &enumeration_current_val);
3246b2770bfSJorge Lopez /*
3256b2770bfSJorge Lopez * Several attributes have names such "MONDAY". Friendly
3266b2770bfSJorge Lopez * user nane is generated to make the name more descriptive
3276b2770bfSJorge Lopez */
3286b2770bfSJorge Lopez hp_friendly_user_name_update(enum_data->common.path,
3296b2770bfSJorge Lopez attr_name_kobj->name,
3306b2770bfSJorge Lopez enum_data->common.display_name,
3316b2770bfSJorge Lopez sizeof(enum_data->common.display_name));
3326b2770bfSJorge Lopez return sysfs_create_group(attr_name_kobj, &enumeration_attr_group);
3336b2770bfSJorge Lopez }
3346b2770bfSJorge Lopez
hp_populate_enumeration_elements_from_buffer(u8 * buffer_ptr,u32 * buffer_size,int instance_id)3356b2770bfSJorge Lopez static int hp_populate_enumeration_elements_from_buffer(u8 *buffer_ptr, u32 *buffer_size,
3366b2770bfSJorge Lopez int instance_id)
3376b2770bfSJorge Lopez {
3386b2770bfSJorge Lopez int values;
3396b2770bfSJorge Lopez struct enumeration_data *enum_data = &bioscfg_drv.enumeration_data[instance_id];
3406b2770bfSJorge Lopez int ret = 0;
3416b2770bfSJorge Lopez
3426b2770bfSJorge Lopez /*
3436b2770bfSJorge Lopez * Only data relevant to this driver and its functionality is
3446b2770bfSJorge Lopez * read. BIOS defines the order in which each * element is
3456b2770bfSJorge Lopez * read. Element 0 data is not relevant to this
3466b2770bfSJorge Lopez * driver hence it is ignored. For clarity, all element names
3476b2770bfSJorge Lopez * (DISPLAY_IN_UI) which defines the order in which is read
3486b2770bfSJorge Lopez * and the name matches the variable where the data is stored.
3496b2770bfSJorge Lopez *
3506b2770bfSJorge Lopez * In earlier implementation, reported errors were ignored
3516b2770bfSJorge Lopez * causing the data to remain uninitialized. It is not
3526b2770bfSJorge Lopez * possible to determine if data read from BIOS is valid or
3536b2770bfSJorge Lopez * not. It is for this reason functions may return a error
3546b2770bfSJorge Lopez * without validating the data itself.
3556b2770bfSJorge Lopez */
3566b2770bfSJorge Lopez
3576b2770bfSJorge Lopez // VALUE:
3586b2770bfSJorge Lopez ret = hp_get_string_from_buffer(&buffer_ptr, buffer_size, enum_data->current_value,
3596b2770bfSJorge Lopez sizeof(enum_data->current_value));
3606b2770bfSJorge Lopez if (ret < 0)
3616b2770bfSJorge Lopez goto buffer_exit;
3626b2770bfSJorge Lopez
3636b2770bfSJorge Lopez // COMMON:
3646b2770bfSJorge Lopez ret = hp_get_common_data_from_buffer(&buffer_ptr, buffer_size, &enum_data->common);
3656b2770bfSJorge Lopez if (ret < 0)
3666b2770bfSJorge Lopez goto buffer_exit;
3676b2770bfSJorge Lopez
3686b2770bfSJorge Lopez // ENUM_CURRENT_VALUE:
3696b2770bfSJorge Lopez ret = hp_get_string_from_buffer(&buffer_ptr, buffer_size,
3706b2770bfSJorge Lopez enum_data->current_value,
3716b2770bfSJorge Lopez sizeof(enum_data->current_value));
3726b2770bfSJorge Lopez if (ret < 0)
3736b2770bfSJorge Lopez goto buffer_exit;
3746b2770bfSJorge Lopez
3756b2770bfSJorge Lopez // ENUM_SIZE:
3766b2770bfSJorge Lopez ret = hp_get_integer_from_buffer(&buffer_ptr, buffer_size,
3776b2770bfSJorge Lopez &enum_data->possible_values_size);
3786b2770bfSJorge Lopez
3796b2770bfSJorge Lopez if (enum_data->possible_values_size > MAX_VALUES_SIZE) {
3806b2770bfSJorge Lopez /* Report a message and limit possible values size to maximum value */
3816b2770bfSJorge Lopez pr_warn("Enum Possible size value exceeded the maximum number of elements supported or data may be malformed\n");
3826b2770bfSJorge Lopez enum_data->possible_values_size = MAX_VALUES_SIZE;
3836b2770bfSJorge Lopez }
3846b2770bfSJorge Lopez
3856b2770bfSJorge Lopez // ENUM_POSSIBLE_VALUES:
3866b2770bfSJorge Lopez for (values = 0; values < enum_data->possible_values_size; values++) {
3876b2770bfSJorge Lopez ret = hp_get_string_from_buffer(&buffer_ptr, buffer_size,
3886b2770bfSJorge Lopez enum_data->possible_values[values],
3896b2770bfSJorge Lopez sizeof(enum_data->possible_values[values]));
3906b2770bfSJorge Lopez if (ret < 0)
3916b2770bfSJorge Lopez break;
3926b2770bfSJorge Lopez }
3936b2770bfSJorge Lopez
3946b2770bfSJorge Lopez buffer_exit:
3956b2770bfSJorge Lopez return ret;
3966b2770bfSJorge Lopez }
3976b2770bfSJorge Lopez
3986b2770bfSJorge Lopez /**
3996b2770bfSJorge Lopez * hp_populate_enumeration_buffer_data() -
4006b2770bfSJorge Lopez * Populate all properties of an instance under enumeration attribute
4016b2770bfSJorge Lopez *
4026b2770bfSJorge Lopez * @buffer_ptr: Buffer pointer
4036b2770bfSJorge Lopez * @buffer_size: Buffer size
4046b2770bfSJorge Lopez * @instance_id: The instance to enumerate
4056b2770bfSJorge Lopez * @attr_name_kobj: The parent kernel object
4066b2770bfSJorge Lopez */
hp_populate_enumeration_buffer_data(u8 * buffer_ptr,u32 * buffer_size,int instance_id,struct kobject * attr_name_kobj)4076b2770bfSJorge Lopez int hp_populate_enumeration_buffer_data(u8 *buffer_ptr, u32 *buffer_size,
4086b2770bfSJorge Lopez int instance_id,
4096b2770bfSJorge Lopez struct kobject *attr_name_kobj)
4106b2770bfSJorge Lopez {
4116b2770bfSJorge Lopez struct enumeration_data *enum_data = &bioscfg_drv.enumeration_data[instance_id];
4126b2770bfSJorge Lopez int ret = 0;
4136b2770bfSJorge Lopez
4146b2770bfSJorge Lopez enum_data->attr_name_kobj = attr_name_kobj;
4156b2770bfSJorge Lopez
4166b2770bfSJorge Lopez /* Populate enumeration elements */
4176b2770bfSJorge Lopez ret = hp_populate_enumeration_elements_from_buffer(buffer_ptr, buffer_size,
4186b2770bfSJorge Lopez instance_id);
4196b2770bfSJorge Lopez if (ret < 0)
4206b2770bfSJorge Lopez return ret;
4216b2770bfSJorge Lopez
4226b2770bfSJorge Lopez hp_update_attribute_permissions(enum_data->common.is_readonly,
4236b2770bfSJorge Lopez &enumeration_current_val);
4246b2770bfSJorge Lopez /*
4256b2770bfSJorge Lopez * Several attributes have names such "MONDAY". A Friendlier
4266b2770bfSJorge Lopez * user nane is generated to make the name more descriptive
4276b2770bfSJorge Lopez */
4286b2770bfSJorge Lopez hp_friendly_user_name_update(enum_data->common.path,
4296b2770bfSJorge Lopez attr_name_kobj->name,
4306b2770bfSJorge Lopez enum_data->common.display_name,
4316b2770bfSJorge Lopez sizeof(enum_data->common.display_name));
4326b2770bfSJorge Lopez
4336b2770bfSJorge Lopez return sysfs_create_group(attr_name_kobj, &enumeration_attr_group);
4346b2770bfSJorge Lopez }
4356b2770bfSJorge Lopez
4366b2770bfSJorge Lopez /**
4376b2770bfSJorge Lopez * hp_exit_enumeration_attributes() - Clear all attribute data
4386b2770bfSJorge Lopez *
4396b2770bfSJorge Lopez * Clears all data allocated for this group of attributes
4406b2770bfSJorge Lopez */
hp_exit_enumeration_attributes(void)4416b2770bfSJorge Lopez void hp_exit_enumeration_attributes(void)
4426b2770bfSJorge Lopez {
4436b2770bfSJorge Lopez int instance_id;
4446b2770bfSJorge Lopez
4456b2770bfSJorge Lopez for (instance_id = 0; instance_id < bioscfg_drv.enumeration_instances_count;
4466b2770bfSJorge Lopez instance_id++) {
4476b2770bfSJorge Lopez struct enumeration_data *enum_data = &bioscfg_drv.enumeration_data[instance_id];
4486b2770bfSJorge Lopez struct kobject *attr_name_kobj = enum_data->attr_name_kobj;
4496b2770bfSJorge Lopez
4506b2770bfSJorge Lopez if (attr_name_kobj)
4516b2770bfSJorge Lopez sysfs_remove_group(attr_name_kobj, &enumeration_attr_group);
4526b2770bfSJorge Lopez }
4536b2770bfSJorge Lopez bioscfg_drv.enumeration_instances_count = 0;
4546b2770bfSJorge Lopez
4556b2770bfSJorge Lopez kfree(bioscfg_drv.enumeration_data);
4566b2770bfSJorge Lopez bioscfg_drv.enumeration_data = NULL;
4576b2770bfSJorge Lopez }
458