14b2672ecSJorge Lopez // SPDX-License-Identifier: GPL-2.0
24b2672ecSJorge Lopez /*
34b2672ecSJorge Lopez * Functions corresponding to ordered list type attributes under
44b2672ecSJorge Lopez * BIOS ORDERED LIST GUID for use with hp-bioscfg driver.
54b2672ecSJorge Lopez *
64b2672ecSJorge Lopez * Copyright (c) 2022 HP Development Company, L.P.
74b2672ecSJorge Lopez */
84b2672ecSJorge Lopez
94b2672ecSJorge Lopez #include "bioscfg.h"
104b2672ecSJorge Lopez
114b2672ecSJorge Lopez GET_INSTANCE_ID(ordered_list);
124b2672ecSJorge Lopez
current_value_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)134b2672ecSJorge Lopez static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
144b2672ecSJorge Lopez {
154b2672ecSJorge Lopez int instance_id = get_ordered_list_instance_id(kobj);
164b2672ecSJorge Lopez
174b2672ecSJorge Lopez if (instance_id < 0)
184b2672ecSJorge Lopez return -EIO;
194b2672ecSJorge Lopez
204b2672ecSJorge Lopez return sysfs_emit(buf, "%s\n",
214b2672ecSJorge Lopez bioscfg_drv.ordered_list_data[instance_id].current_value);
224b2672ecSJorge Lopez }
234b2672ecSJorge Lopez
replace_char_str(u8 * buffer,char * repl_char,char * repl_with)244b2672ecSJorge Lopez static int replace_char_str(u8 *buffer, char *repl_char, char *repl_with)
254b2672ecSJorge Lopez {
264b2672ecSJorge Lopez char *src = buffer;
274b2672ecSJorge Lopez int buflen = strlen(buffer);
284b2672ecSJorge Lopez int item;
294b2672ecSJorge Lopez
304b2672ecSJorge Lopez if (buflen < 1)
314b2672ecSJorge Lopez return -EINVAL;
324b2672ecSJorge Lopez
334b2672ecSJorge Lopez for (item = 0; item < buflen; item++)
344b2672ecSJorge Lopez if (src[item] == *repl_char)
354b2672ecSJorge Lopez src[item] = *repl_with;
364b2672ecSJorge Lopez
374b2672ecSJorge Lopez return 0;
384b2672ecSJorge Lopez }
394b2672ecSJorge Lopez
404b2672ecSJorge Lopez /**
414b2672ecSJorge Lopez * validate_ordered_list_input() -
424b2672ecSJorge Lopez * Validate input of current_value against possible values
434b2672ecSJorge Lopez *
444b2672ecSJorge Lopez * @instance: The instance on which input is validated
454b2672ecSJorge Lopez * @buf: Input value
464b2672ecSJorge Lopez */
validate_ordered_list_input(int instance,char * buf)474b2672ecSJorge Lopez static int validate_ordered_list_input(int instance, char *buf)
484b2672ecSJorge Lopez {
494b2672ecSJorge Lopez /* validation is done by BIOS. This validation function will
504b2672ecSJorge Lopez * convert semicolon to commas. BIOS uses commas as
514b2672ecSJorge Lopez * separators when reporting ordered-list values.
524b2672ecSJorge Lopez */
534b2672ecSJorge Lopez return replace_char_str(buf, SEMICOLON_SEP, COMMA_SEP);
544b2672ecSJorge Lopez }
554b2672ecSJorge Lopez
update_ordered_list_value(int instance,char * attr_value)564b2672ecSJorge Lopez static void update_ordered_list_value(int instance, char *attr_value)
574b2672ecSJorge Lopez {
584b2672ecSJorge Lopez struct ordered_list_data *ordered_list_data = &bioscfg_drv.ordered_list_data[instance];
594b2672ecSJorge Lopez
604b2672ecSJorge Lopez strscpy(ordered_list_data->current_value,
614b2672ecSJorge Lopez attr_value,
624b2672ecSJorge Lopez sizeof(ordered_list_data->current_value));
634b2672ecSJorge Lopez }
644b2672ecSJorge Lopez
654b2672ecSJorge Lopez ATTRIBUTE_S_COMMON_PROPERTY_SHOW(display_name, ordered_list);
664b2672ecSJorge Lopez static struct kobj_attribute ordered_list_display_name =
674b2672ecSJorge Lopez __ATTR_RO(display_name);
684b2672ecSJorge Lopez
694b2672ecSJorge Lopez ATTRIBUTE_PROPERTY_STORE(current_value, ordered_list);
704b2672ecSJorge Lopez static struct kobj_attribute ordered_list_current_val =
714b2672ecSJorge Lopez __ATTR_RW_MODE(current_value, 0644);
724b2672ecSJorge Lopez
734b2672ecSJorge Lopez ATTRIBUTE_VALUES_PROPERTY_SHOW(elements, ordered_list, SEMICOLON_SEP);
744b2672ecSJorge Lopez static struct kobj_attribute ordered_list_elements_val =
754b2672ecSJorge Lopez __ATTR_RO(elements);
764b2672ecSJorge Lopez
type_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)774b2672ecSJorge Lopez static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
784b2672ecSJorge Lopez char *buf)
794b2672ecSJorge Lopez {
804b2672ecSJorge Lopez return sysfs_emit(buf, "ordered-list\n");
814b2672ecSJorge Lopez }
824b2672ecSJorge Lopez
834b2672ecSJorge Lopez static struct kobj_attribute ordered_list_type =
844b2672ecSJorge Lopez __ATTR_RO(type);
854b2672ecSJorge Lopez
864b2672ecSJorge Lopez static struct attribute *ordered_list_attrs[] = {
874b2672ecSJorge Lopez &common_display_langcode.attr,
884b2672ecSJorge Lopez &ordered_list_display_name.attr,
894b2672ecSJorge Lopez &ordered_list_current_val.attr,
904b2672ecSJorge Lopez &ordered_list_elements_val.attr,
914b2672ecSJorge Lopez &ordered_list_type.attr,
924b2672ecSJorge Lopez NULL
934b2672ecSJorge Lopez };
944b2672ecSJorge Lopez
954b2672ecSJorge Lopez static const struct attribute_group ordered_list_attr_group = {
964b2672ecSJorge Lopez .attrs = ordered_list_attrs,
974b2672ecSJorge Lopez };
984b2672ecSJorge Lopez
hp_alloc_ordered_list_data(void)994b2672ecSJorge Lopez int hp_alloc_ordered_list_data(void)
1004b2672ecSJorge Lopez {
1014b2672ecSJorge Lopez bioscfg_drv.ordered_list_instances_count =
1024b2672ecSJorge Lopez hp_get_instance_count(HP_WMI_BIOS_ORDERED_LIST_GUID);
1034b2672ecSJorge Lopez bioscfg_drv.ordered_list_data = kcalloc(bioscfg_drv.ordered_list_instances_count,
1044b2672ecSJorge Lopez sizeof(*bioscfg_drv.ordered_list_data),
1054b2672ecSJorge Lopez GFP_KERNEL);
1064b2672ecSJorge Lopez if (!bioscfg_drv.ordered_list_data) {
1074b2672ecSJorge Lopez bioscfg_drv.ordered_list_instances_count = 0;
1084b2672ecSJorge Lopez return -ENOMEM;
1094b2672ecSJorge Lopez }
1104b2672ecSJorge Lopez return 0;
1114b2672ecSJorge Lopez }
1124b2672ecSJorge Lopez
1134b2672ecSJorge Lopez /* Expected Values types associated with each element */
1144b2672ecSJorge Lopez static const acpi_object_type expected_order_types[] = {
1154b2672ecSJorge Lopez [NAME] = ACPI_TYPE_STRING,
1164b2672ecSJorge Lopez [VALUE] = ACPI_TYPE_STRING,
1174b2672ecSJorge Lopez [PATH] = ACPI_TYPE_STRING,
1184b2672ecSJorge Lopez [IS_READONLY] = ACPI_TYPE_INTEGER,
1194b2672ecSJorge Lopez [DISPLAY_IN_UI] = ACPI_TYPE_INTEGER,
1204b2672ecSJorge Lopez [REQUIRES_PHYSICAL_PRESENCE] = ACPI_TYPE_INTEGER,
1214b2672ecSJorge Lopez [SEQUENCE] = ACPI_TYPE_INTEGER,
1224b2672ecSJorge Lopez [PREREQUISITES_SIZE] = ACPI_TYPE_INTEGER,
1234b2672ecSJorge Lopez [PREREQUISITES] = ACPI_TYPE_STRING,
1244b2672ecSJorge Lopez [SECURITY_LEVEL] = ACPI_TYPE_INTEGER,
1254b2672ecSJorge Lopez [ORD_LIST_SIZE] = ACPI_TYPE_INTEGER,
1264b2672ecSJorge Lopez [ORD_LIST_ELEMENTS] = ACPI_TYPE_STRING,
1274b2672ecSJorge Lopez };
1284b2672ecSJorge Lopez
hp_populate_ordered_list_elements_from_package(union acpi_object * order_obj,int order_obj_count,int instance_id)1294b2672ecSJorge Lopez static int hp_populate_ordered_list_elements_from_package(union acpi_object *order_obj,
1304b2672ecSJorge Lopez int order_obj_count,
1314b2672ecSJorge Lopez int instance_id)
1324b2672ecSJorge Lopez {
1334b2672ecSJorge Lopez char *str_value = NULL;
13480d7ba30SJorge Lopez int value_len = 0;
1354b2672ecSJorge Lopez int ret;
1364b2672ecSJorge Lopez u32 size;
13780d7ba30SJorge Lopez u32 int_value = 0;
1384b2672ecSJorge Lopez int elem;
139bfecbcb5SJorge Lopez int olist_elem;
1404b2672ecSJorge Lopez int reqs;
1414b2672ecSJorge Lopez int eloc;
1424b2672ecSJorge Lopez char *tmpstr = NULL;
1434b2672ecSJorge Lopez char *part_tmp = NULL;
1444b2672ecSJorge Lopez int tmp_len = 0;
1454b2672ecSJorge Lopez char *part = NULL;
1464b2672ecSJorge Lopez struct ordered_list_data *ordered_list_data = &bioscfg_drv.ordered_list_data[instance_id];
1474b2672ecSJorge Lopez
1484b2672ecSJorge Lopez if (!order_obj)
1494b2672ecSJorge Lopez return -EINVAL;
1504b2672ecSJorge Lopez
151bfecbcb5SJorge Lopez for (elem = 1, eloc = 1; eloc < ORD_ELEM_CNT; elem++, eloc++) {
1524b2672ecSJorge Lopez
1534b2672ecSJorge Lopez switch (order_obj[elem].type) {
1544b2672ecSJorge Lopez case ACPI_TYPE_STRING:
1554b2672ecSJorge Lopez if (elem != PREREQUISITES && elem != ORD_LIST_ELEMENTS) {
1564b2672ecSJorge Lopez ret = hp_convert_hexstr_to_str(order_obj[elem].string.pointer,
1574b2672ecSJorge Lopez order_obj[elem].string.length,
1584b2672ecSJorge Lopez &str_value, &value_len);
1594b2672ecSJorge Lopez if (ret)
1604b2672ecSJorge Lopez continue;
1614b2672ecSJorge Lopez }
1624b2672ecSJorge Lopez break;
1634b2672ecSJorge Lopez case ACPI_TYPE_INTEGER:
1644b2672ecSJorge Lopez int_value = (u32)order_obj[elem].integer.value;
1654b2672ecSJorge Lopez break;
1664b2672ecSJorge Lopez default:
1674b2672ecSJorge Lopez pr_warn("Unsupported object type [%d]\n", order_obj[elem].type);
1684b2672ecSJorge Lopez continue;
1694b2672ecSJorge Lopez }
1704b2672ecSJorge Lopez
1714b2672ecSJorge Lopez /* Check that both expected and read object type match */
1724b2672ecSJorge Lopez if (expected_order_types[eloc] != order_obj[elem].type) {
1734b2672ecSJorge Lopez pr_err("Error expected type %d for elem %d, but got type %d instead\n",
1744b2672ecSJorge Lopez expected_order_types[eloc], elem, order_obj[elem].type);
175467d4163SJorge Lopez kfree(str_value);
1764b2672ecSJorge Lopez return -EIO;
1774b2672ecSJorge Lopez }
1784b2672ecSJorge Lopez
1794b2672ecSJorge Lopez /* Assign appropriate element value to corresponding field*/
1804b2672ecSJorge Lopez switch (eloc) {
1814b2672ecSJorge Lopez case VALUE:
1824b2672ecSJorge Lopez strscpy(ordered_list_data->current_value,
1834b2672ecSJorge Lopez str_value, sizeof(ordered_list_data->current_value));
1844b2672ecSJorge Lopez replace_char_str(ordered_list_data->current_value, COMMA_SEP, SEMICOLON_SEP);
1854b2672ecSJorge Lopez break;
1864b2672ecSJorge Lopez case PATH:
1874b2672ecSJorge Lopez strscpy(ordered_list_data->common.path, str_value,
1884b2672ecSJorge Lopez sizeof(ordered_list_data->common.path));
1894b2672ecSJorge Lopez break;
1904b2672ecSJorge Lopez case IS_READONLY:
1914b2672ecSJorge Lopez ordered_list_data->common.is_readonly = int_value;
1924b2672ecSJorge Lopez break;
1934b2672ecSJorge Lopez case DISPLAY_IN_UI:
1944b2672ecSJorge Lopez ordered_list_data->common.display_in_ui = int_value;
1954b2672ecSJorge Lopez break;
1964b2672ecSJorge Lopez case REQUIRES_PHYSICAL_PRESENCE:
1974b2672ecSJorge Lopez ordered_list_data->common.requires_physical_presence = int_value;
1984b2672ecSJorge Lopez break;
1994b2672ecSJorge Lopez case SEQUENCE:
2004b2672ecSJorge Lopez ordered_list_data->common.sequence = int_value;
2014b2672ecSJorge Lopez break;
2024b2672ecSJorge Lopez case PREREQUISITES_SIZE:
20308f1f212SJorge Lopez if (int_value > MAX_PREREQUISITES_SIZE) {
2044b2672ecSJorge Lopez pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n");
20508f1f212SJorge Lopez int_value = MAX_PREREQUISITES_SIZE;
20608f1f212SJorge Lopez }
20708f1f212SJorge Lopez ordered_list_data->common.prerequisites_size = int_value;
2084b2672ecSJorge Lopez
2094b2672ecSJorge Lopez /*
210a585400bSJorge Lopez * This step is needed to keep the expected
2114b2672ecSJorge Lopez * element list pointing to the right obj[elem].type
2124b2672ecSJorge Lopez * when the size is zero. PREREQUISITES
2134b2672ecSJorge Lopez * object is omitted by BIOS when the size is
2144b2672ecSJorge Lopez * zero.
2154b2672ecSJorge Lopez */
2164b2672ecSJorge Lopez if (int_value == 0)
2174b2672ecSJorge Lopez eloc++;
2184b2672ecSJorge Lopez break;
2194b2672ecSJorge Lopez case PREREQUISITES:
2204b2672ecSJorge Lopez size = min_t(u32, ordered_list_data->common.prerequisites_size,
2214b2672ecSJorge Lopez MAX_PREREQUISITES_SIZE);
2224b2672ecSJorge Lopez for (reqs = 0; reqs < size; reqs++) {
2234b2672ecSJorge Lopez ret = hp_convert_hexstr_to_str(order_obj[elem + reqs].string.pointer,
2244b2672ecSJorge Lopez order_obj[elem + reqs].string.length,
2254b2672ecSJorge Lopez &str_value, &value_len);
2264b2672ecSJorge Lopez
2274b2672ecSJorge Lopez if (ret)
2284b2672ecSJorge Lopez continue;
2294b2672ecSJorge Lopez
2304b2672ecSJorge Lopez strscpy(ordered_list_data->common.prerequisites[reqs],
2314b2672ecSJorge Lopez str_value,
2324b2672ecSJorge Lopez sizeof(ordered_list_data->common.prerequisites[reqs]));
2334b2672ecSJorge Lopez
2344b2672ecSJorge Lopez kfree(str_value);
235467d4163SJorge Lopez str_value = NULL;
2364b2672ecSJorge Lopez }
2374b2672ecSJorge Lopez break;
2384b2672ecSJorge Lopez
2394b2672ecSJorge Lopez case SECURITY_LEVEL:
2404b2672ecSJorge Lopez ordered_list_data->common.security_level = int_value;
2414b2672ecSJorge Lopez break;
2424b2672ecSJorge Lopez
2434b2672ecSJorge Lopez case ORD_LIST_SIZE:
24424652a8cSJorge Lopez if (int_value > MAX_ELEMENTS_SIZE) {
24524652a8cSJorge Lopez pr_warn("Order List size value exceeded the maximum number of elements supported or data may be malformed\n");
24624652a8cSJorge Lopez int_value = MAX_ELEMENTS_SIZE;
24724652a8cSJorge Lopez }
2484b2672ecSJorge Lopez ordered_list_data->elements_size = int_value;
24924652a8cSJorge Lopez
2504b2672ecSJorge Lopez /*
251a585400bSJorge Lopez * This step is needed to keep the expected
2524b2672ecSJorge Lopez * element list pointing to the right obj[elem].type
2534b2672ecSJorge Lopez * when the size is zero. ORD_LIST_ELEMENTS
2544b2672ecSJorge Lopez * object is omitted by BIOS when the size is
2554b2672ecSJorge Lopez * zero.
2564b2672ecSJorge Lopez */
2574b2672ecSJorge Lopez if (int_value == 0)
2584b2672ecSJorge Lopez eloc++;
2594b2672ecSJorge Lopez break;
2604b2672ecSJorge Lopez case ORD_LIST_ELEMENTS:
2614b2672ecSJorge Lopez
2624b2672ecSJorge Lopez /*
2634b2672ecSJorge Lopez * Ordered list data is stored in hex and comma separated format
2644b2672ecSJorge Lopez * Convert the data and split it to show each element
2654b2672ecSJorge Lopez */
2664b2672ecSJorge Lopez ret = hp_convert_hexstr_to_str(str_value, value_len, &tmpstr, &tmp_len);
2674b2672ecSJorge Lopez if (ret)
2684b2672ecSJorge Lopez goto exit_list;
2694b2672ecSJorge Lopez
2704b2672ecSJorge Lopez part_tmp = tmpstr;
2714b2672ecSJorge Lopez part = strsep(&part_tmp, COMMA_SEP);
2724b2672ecSJorge Lopez
273*559eed77SJorge Lopez for (olist_elem = 0; olist_elem < MAX_ELEMENTS_SIZE && part; olist_elem++) {
274bfecbcb5SJorge Lopez strscpy(ordered_list_data->elements[olist_elem],
2754b2672ecSJorge Lopez part,
276bfecbcb5SJorge Lopez sizeof(ordered_list_data->elements[olist_elem]));
277*559eed77SJorge Lopez part = strsep(&part_tmp, COMMA_SEP);
2784b2672ecSJorge Lopez }
279*559eed77SJorge Lopez ordered_list_data->elements_size = olist_elem;
2804b2672ecSJorge Lopez
281467d4163SJorge Lopez kfree(str_value);
282467d4163SJorge Lopez str_value = NULL;
2834b2672ecSJorge Lopez break;
2844b2672ecSJorge Lopez default:
2854b2672ecSJorge Lopez pr_warn("Invalid element: %d found in Ordered_List attribute or data may be malformed\n", elem);
2864b2672ecSJorge Lopez break;
2874b2672ecSJorge Lopez }
2884b2672ecSJorge Lopez kfree(tmpstr);
289467d4163SJorge Lopez tmpstr = NULL;
2904b2672ecSJorge Lopez kfree(str_value);
291467d4163SJorge Lopez str_value = NULL;
2924b2672ecSJorge Lopez }
2934b2672ecSJorge Lopez
2944b2672ecSJorge Lopez exit_list:
2954b2672ecSJorge Lopez kfree(tmpstr);
2964b2672ecSJorge Lopez kfree(str_value);
2974b2672ecSJorge Lopez return 0;
2984b2672ecSJorge Lopez }
2994b2672ecSJorge Lopez
3004b2672ecSJorge Lopez /**
3014b2672ecSJorge Lopez * hp_populate_ordered_list_package_data() -
3024b2672ecSJorge Lopez * Populate all properties of an instance under ordered_list attribute
3034b2672ecSJorge Lopez *
3044b2672ecSJorge Lopez * @order_obj: ACPI object with ordered_list data
3054b2672ecSJorge Lopez * @instance_id: The instance to enumerate
3064b2672ecSJorge Lopez * @attr_name_kobj: The parent kernel object
3074b2672ecSJorge Lopez */
hp_populate_ordered_list_package_data(union acpi_object * order_obj,int instance_id,struct kobject * attr_name_kobj)3084b2672ecSJorge Lopez int hp_populate_ordered_list_package_data(union acpi_object *order_obj, int instance_id,
3094b2672ecSJorge Lopez struct kobject *attr_name_kobj)
3104b2672ecSJorge Lopez {
3114b2672ecSJorge Lopez struct ordered_list_data *ordered_list_data = &bioscfg_drv.ordered_list_data[instance_id];
3124b2672ecSJorge Lopez
3134b2672ecSJorge Lopez ordered_list_data->attr_name_kobj = attr_name_kobj;
3144b2672ecSJorge Lopez
3154b2672ecSJorge Lopez hp_populate_ordered_list_elements_from_package(order_obj,
3164b2672ecSJorge Lopez order_obj->package.count,
3174b2672ecSJorge Lopez instance_id);
3184b2672ecSJorge Lopez hp_update_attribute_permissions(ordered_list_data->common.is_readonly,
3194b2672ecSJorge Lopez &ordered_list_current_val);
3204b2672ecSJorge Lopez hp_friendly_user_name_update(ordered_list_data->common.path,
3214b2672ecSJorge Lopez attr_name_kobj->name,
3224b2672ecSJorge Lopez ordered_list_data->common.display_name,
3234b2672ecSJorge Lopez sizeof(ordered_list_data->common.display_name));
3244b2672ecSJorge Lopez return sysfs_create_group(attr_name_kobj, &ordered_list_attr_group);
3254b2672ecSJorge Lopez }
3264b2672ecSJorge Lopez
hp_populate_ordered_list_elements_from_buffer(u8 * buffer_ptr,u32 * buffer_size,int instance_id)3274b2672ecSJorge Lopez static int hp_populate_ordered_list_elements_from_buffer(u8 *buffer_ptr, u32 *buffer_size,
3284b2672ecSJorge Lopez int instance_id)
3294b2672ecSJorge Lopez {
3304b2672ecSJorge Lopez int values;
3314b2672ecSJorge Lopez struct ordered_list_data *ordered_list_data = &bioscfg_drv.ordered_list_data[instance_id];
3324b2672ecSJorge Lopez int ret = 0;
3334b2672ecSJorge Lopez
3344b2672ecSJorge Lopez /*
3354b2672ecSJorge Lopez * Only data relevant to this driver and its functionality is
3364b2672ecSJorge Lopez * read. BIOS defines the order in which each * element is
3374b2672ecSJorge Lopez * read. Element 0 data is not relevant to this
3384b2672ecSJorge Lopez * driver hence it is ignored. For clarity, all element names
3394b2672ecSJorge Lopez * (DISPLAY_IN_UI) which defines the order in which is read
3404b2672ecSJorge Lopez * and the name matches the variable where the data is stored.
3414b2672ecSJorge Lopez *
3424b2672ecSJorge Lopez * In earlier implementation, reported errors were ignored
3434b2672ecSJorge Lopez * causing the data to remain uninitialized. It is not
3444b2672ecSJorge Lopez * possible to determine if data read from BIOS is valid or
3454b2672ecSJorge Lopez * not. It is for this reason functions may return a error
3464b2672ecSJorge Lopez * without validating the data itself.
3474b2672ecSJorge Lopez */
3484b2672ecSJorge Lopez
3494b2672ecSJorge Lopez // VALUE:
3504b2672ecSJorge Lopez ret = hp_get_string_from_buffer(&buffer_ptr, buffer_size, ordered_list_data->current_value,
3514b2672ecSJorge Lopez sizeof(ordered_list_data->current_value));
3524b2672ecSJorge Lopez if (ret < 0)
3534b2672ecSJorge Lopez goto buffer_exit;
3544b2672ecSJorge Lopez
3554b2672ecSJorge Lopez replace_char_str(ordered_list_data->current_value, COMMA_SEP, SEMICOLON_SEP);
3564b2672ecSJorge Lopez
3574b2672ecSJorge Lopez // COMMON:
3584b2672ecSJorge Lopez ret = hp_get_common_data_from_buffer(&buffer_ptr, buffer_size,
3594b2672ecSJorge Lopez &ordered_list_data->common);
3604b2672ecSJorge Lopez if (ret < 0)
3614b2672ecSJorge Lopez goto buffer_exit;
3624b2672ecSJorge Lopez
3634b2672ecSJorge Lopez // ORD_LIST_SIZE:
3644b2672ecSJorge Lopez ret = hp_get_integer_from_buffer(&buffer_ptr, buffer_size,
3654b2672ecSJorge Lopez &ordered_list_data->elements_size);
3664b2672ecSJorge Lopez
3674b2672ecSJorge Lopez if (ordered_list_data->elements_size > MAX_ELEMENTS_SIZE) {
3684b2672ecSJorge Lopez /* Report a message and limit elements size to maximum value */
3694b2672ecSJorge Lopez pr_warn("Ordered List size value exceeded the maximum number of elements supported or data may be malformed\n");
3704b2672ecSJorge Lopez ordered_list_data->elements_size = MAX_ELEMENTS_SIZE;
3714b2672ecSJorge Lopez }
3724b2672ecSJorge Lopez
3734b2672ecSJorge Lopez // ORD_LIST_ELEMENTS:
3744b2672ecSJorge Lopez for (values = 0; values < ordered_list_data->elements_size; values++) {
3754b2672ecSJorge Lopez ret = hp_get_string_from_buffer(&buffer_ptr, buffer_size,
3764b2672ecSJorge Lopez ordered_list_data->elements[values],
3774b2672ecSJorge Lopez sizeof(ordered_list_data->elements[values]));
3784b2672ecSJorge Lopez if (ret < 0)
3794b2672ecSJorge Lopez break;
3804b2672ecSJorge Lopez }
3814b2672ecSJorge Lopez
3824b2672ecSJorge Lopez buffer_exit:
3834b2672ecSJorge Lopez return ret;
3844b2672ecSJorge Lopez }
3854b2672ecSJorge Lopez
3864b2672ecSJorge Lopez /**
3874b2672ecSJorge Lopez * hp_populate_ordered_list_buffer_data() - Populate all properties of an
3884b2672ecSJorge Lopez * instance under ordered list attribute
3894b2672ecSJorge Lopez *
3904b2672ecSJorge Lopez * @buffer_ptr: Buffer pointer
3914b2672ecSJorge Lopez * @buffer_size: Buffer size
3924b2672ecSJorge Lopez * @instance_id: The instance to enumerate
3934b2672ecSJorge Lopez * @attr_name_kobj: The parent kernel object
3944b2672ecSJorge Lopez */
hp_populate_ordered_list_buffer_data(u8 * buffer_ptr,u32 * buffer_size,int instance_id,struct kobject * attr_name_kobj)3954b2672ecSJorge Lopez int hp_populate_ordered_list_buffer_data(u8 *buffer_ptr, u32 *buffer_size, int instance_id,
3964b2672ecSJorge Lopez struct kobject *attr_name_kobj)
3974b2672ecSJorge Lopez {
3984b2672ecSJorge Lopez struct ordered_list_data *ordered_list_data = &bioscfg_drv.ordered_list_data[instance_id];
3994b2672ecSJorge Lopez int ret = 0;
4004b2672ecSJorge Lopez
4014b2672ecSJorge Lopez ordered_list_data->attr_name_kobj = attr_name_kobj;
4024b2672ecSJorge Lopez
4034b2672ecSJorge Lopez /* Populate ordered list elements */
4044b2672ecSJorge Lopez ret = hp_populate_ordered_list_elements_from_buffer(buffer_ptr, buffer_size,
4054b2672ecSJorge Lopez instance_id);
4064b2672ecSJorge Lopez if (ret < 0)
4074b2672ecSJorge Lopez return ret;
4084b2672ecSJorge Lopez
4094b2672ecSJorge Lopez hp_update_attribute_permissions(ordered_list_data->common.is_readonly,
4104b2672ecSJorge Lopez &ordered_list_current_val);
4114b2672ecSJorge Lopez hp_friendly_user_name_update(ordered_list_data->common.path,
4124b2672ecSJorge Lopez attr_name_kobj->name,
4134b2672ecSJorge Lopez ordered_list_data->common.display_name,
4144b2672ecSJorge Lopez sizeof(ordered_list_data->common.display_name));
4154b2672ecSJorge Lopez
4164b2672ecSJorge Lopez return sysfs_create_group(attr_name_kobj, &ordered_list_attr_group);
4174b2672ecSJorge Lopez }
4184b2672ecSJorge Lopez
4194b2672ecSJorge Lopez /**
4204b2672ecSJorge Lopez * hp_exit_ordered_list_attributes() - Clear all attribute data
4214b2672ecSJorge Lopez *
4224b2672ecSJorge Lopez * Clears all data allocated for this group of attributes
4234b2672ecSJorge Lopez */
hp_exit_ordered_list_attributes(void)4244b2672ecSJorge Lopez void hp_exit_ordered_list_attributes(void)
4254b2672ecSJorge Lopez {
4264b2672ecSJorge Lopez int instance_id;
4274b2672ecSJorge Lopez
4284b2672ecSJorge Lopez for (instance_id = 0; instance_id < bioscfg_drv.ordered_list_instances_count;
4294b2672ecSJorge Lopez instance_id++) {
4304b2672ecSJorge Lopez struct kobject *attr_name_kobj =
4314b2672ecSJorge Lopez bioscfg_drv.ordered_list_data[instance_id].attr_name_kobj;
4324b2672ecSJorge Lopez
4334b2672ecSJorge Lopez if (attr_name_kobj)
4344b2672ecSJorge Lopez sysfs_remove_group(attr_name_kobj,
4354b2672ecSJorge Lopez &ordered_list_attr_group);
4364b2672ecSJorge Lopez }
4374b2672ecSJorge Lopez bioscfg_drv.ordered_list_instances_count = 0;
4384b2672ecSJorge Lopez
4394b2672ecSJorge Lopez kfree(bioscfg_drv.ordered_list_data);
4404b2672ecSJorge Lopez bioscfg_drv.ordered_list_data = NULL;
4414b2672ecSJorge Lopez }
442