File Index
Files and directories
Sign in
FILE

enum-attributes.c

File preview with syntax highlighting.

linux-6.19.14/drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Functions corresponding to enumeration type attributes under
  4 * BIOS Enumeration GUID for use with dell-wmi-sysman
  5 *
  6 *  Copyright (c) 2020 Dell Inc.
  7 */
  8
  9#include "dell-wmi-sysman.h"
 10
 11get_instance_id(enumeration);
 12
 13static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 14{
 15	int instance_id = get_enumeration_instance_id(kobj);
 16	union acpi_object *obj;
 17	ssize_t ret;
 18
 19	if (instance_id < 0)
 20		return instance_id;
 21
 22	/* need to use specific instance_id and guid combination to get right data */
 23	obj = get_wmiobj_pointer(instance_id, DELL_WMI_BIOS_ENUMERATION_ATTRIBUTE_GUID);
 24	if (!obj)
 25		return -EIO;
 26	if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count < ENUM_MIN_ELEMENTS ||
 27	    obj->package.elements[CURRENT_VAL].type != ACPI_TYPE_STRING) {
 28		kfree(obj);
 29		return -EIO;
 30	}
 31	ret = snprintf(buf, PAGE_SIZE, "%s\n", obj->package.elements[CURRENT_VAL].string.pointer);
 32	kfree(obj);
 33	return ret;
 34}
 35
 36/**
 37 * validate_enumeration_input() - Validate input of current_value against possible values
 38 * @instance_id: The instance on which input is validated
 39 * @buf: Input value
 40 */
 41static int validate_enumeration_input(int instance_id, const char *buf)
 42{
 43	char *options, *tmp, *p;
 44	int ret = -EINVAL;
 45
 46	options = tmp = kstrdup(wmi_priv.enumeration_data[instance_id].possible_values,
 47				 GFP_KERNEL);
 48	if (!options)
 49		return -ENOMEM;
 50
 51	while ((p = strsep(&options, ";")) != NULL) {
 52		if (!*p)
 53			continue;
 54		if (!strcasecmp(p, buf)) {
 55			ret = 0;
 56			break;
 57		}
 58	}
 59
 60	kfree(tmp);
 61	return ret;
 62}
 63
 64attribute_s_property_show(display_name_language_code, enumeration);
 65static struct kobj_attribute displ_langcode =
 66		__ATTR_RO(display_name_language_code);
 67
 68attribute_s_property_show(display_name, enumeration);
 69static struct kobj_attribute displ_name =
 70		__ATTR_RO(display_name);
 71
 72attribute_s_property_show(default_value, enumeration);
 73static struct kobj_attribute default_val =
 74		__ATTR_RO(default_value);
 75
 76attribute_property_store(current_value, enumeration);
 77static struct kobj_attribute current_val =
 78		__ATTR_RW_MODE(current_value, 0600);
 79
 80attribute_s_property_show(dell_modifier, enumeration);
 81static struct kobj_attribute modifier =
 82		__ATTR_RO(dell_modifier);
 83
 84attribute_s_property_show(dell_value_modifier, enumeration);
 85static struct kobj_attribute value_modfr =
 86		__ATTR_RO(dell_value_modifier);
 87
 88attribute_s_property_show(possible_values, enumeration);
 89static struct kobj_attribute poss_val =
 90		__ATTR_RO(possible_values);
 91
 92static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
 93			 char *buf)
 94{
 95	return sprintf(buf, "enumeration\n");
 96}
 97static struct kobj_attribute type =
 98		__ATTR_RO(type);
 99
100static struct attribute *enumeration_attrs[] = {
101	&displ_langcode.attr,
102	&displ_name.attr,
103	&default_val.attr,
104	&current_val.attr,
105	&modifier.attr,
106	&value_modfr.attr,
107	&poss_val.attr,
108	&type.attr,
109	NULL,
110};
111
112static const struct attribute_group enumeration_attr_group = {
113	.attrs = enumeration_attrs,
114};
115
116int alloc_enum_data(void)
117{
118	int ret = 0;
119
120	wmi_priv.enumeration_instances_count =
121		get_instance_count(DELL_WMI_BIOS_ENUMERATION_ATTRIBUTE_GUID);
122	wmi_priv.enumeration_data = kcalloc(wmi_priv.enumeration_instances_count,
123					sizeof(struct enumeration_data), GFP_KERNEL);
124	if (!wmi_priv.enumeration_data) {
125		wmi_priv.enumeration_instances_count = 0;
126		ret = -ENOMEM;
127	}
128	return ret;
129}
130
131/**
132 * populate_enum_data() - Populate all properties of an instance under enumeration attribute
133 * @enumeration_obj: ACPI object with enumeration data
134 * @instance_id: The instance to enumerate
135 * @attr_name_kobj: The parent kernel object
136 * @enum_property_count: Total properties count under enumeration type
137 */
138int populate_enum_data(union acpi_object *enumeration_obj, int instance_id,
139			struct kobject *attr_name_kobj, u32 enum_property_count)
140{
141	int i, next_obj, value_modifier_count, possible_values_count;
142
143	wmi_priv.enumeration_data[instance_id].attr_name_kobj = attr_name_kobj;
144	if (check_property_type(enumeration, ATTR_NAME, ACPI_TYPE_STRING))
145		return -EINVAL;
146	strlcpy_attr(wmi_priv.enumeration_data[instance_id].attribute_name,
147		enumeration_obj[ATTR_NAME].string.pointer);
148	if (check_property_type(enumeration, DISPL_NAME_LANG_CODE, ACPI_TYPE_STRING))
149		return -EINVAL;
150	strlcpy_attr(wmi_priv.enumeration_data[instance_id].display_name_language_code,
151		enumeration_obj[DISPL_NAME_LANG_CODE].string.pointer);
152	if (check_property_type(enumeration, DISPLAY_NAME, ACPI_TYPE_STRING))
153		return -EINVAL;
154	strlcpy_attr(wmi_priv.enumeration_data[instance_id].display_name,
155		enumeration_obj[DISPLAY_NAME].string.pointer);
156	if (check_property_type(enumeration, DEFAULT_VAL, ACPI_TYPE_STRING))
157		return -EINVAL;
158	strlcpy_attr(wmi_priv.enumeration_data[instance_id].default_value,
159		enumeration_obj[DEFAULT_VAL].string.pointer);
160	if (check_property_type(enumeration, MODIFIER, ACPI_TYPE_STRING))
161		return -EINVAL;
162	strlcpy_attr(wmi_priv.enumeration_data[instance_id].dell_modifier,
163		enumeration_obj[MODIFIER].string.pointer);
164
165	next_obj = MODIFIER + 1;
166
167	if (next_obj >= enum_property_count)
168		return -EINVAL;
169
170	if (check_property_type(enumeration, next_obj, ACPI_TYPE_INTEGER))
171		return -EINVAL;
172	value_modifier_count = (uintptr_t)enumeration_obj[next_obj++].string.pointer;
173
174	for (i = 0; i < value_modifier_count; i++) {
175		if (next_obj >= enum_property_count)
176			return -EINVAL;
177		if (check_property_type(enumeration, next_obj, ACPI_TYPE_STRING))
178			return -EINVAL;
179		strcat(wmi_priv.enumeration_data[instance_id].dell_value_modifier,
180			enumeration_obj[next_obj++].string.pointer);
181		strcat(wmi_priv.enumeration_data[instance_id].dell_value_modifier, ";");
182	}
183
184	if (next_obj >= enum_property_count)
185		return -EINVAL;
186
187	if (check_property_type(enumeration, next_obj, ACPI_TYPE_INTEGER))
188		return -EINVAL;
189	possible_values_count = (uintptr_t) enumeration_obj[next_obj++].string.pointer;
190
191	for (i = 0; i < possible_values_count; i++) {
192		if (next_obj >= enum_property_count)
193			return -EINVAL;
194		if (check_property_type(enumeration, next_obj, ACPI_TYPE_STRING))
195			return -EINVAL;
196		strcat(wmi_priv.enumeration_data[instance_id].possible_values,
197			enumeration_obj[next_obj++].string.pointer);
198		strcat(wmi_priv.enumeration_data[instance_id].possible_values, ";");
199	}
200
201	return sysfs_create_group(attr_name_kobj, &enumeration_attr_group);
202}
203
204/**
205 * exit_enum_attributes() - Clear all attribute data
206 *
207 * Clears all data allocated for this group of attributes
208 */
209void exit_enum_attributes(void)
210{
211	int instance_id;
212
213	for (instance_id = 0; instance_id < wmi_priv.enumeration_instances_count; instance_id++) {
214		if (wmi_priv.enumeration_data[instance_id].attr_name_kobj)
215			sysfs_remove_group(wmi_priv.enumeration_data[instance_id].attr_name_kobj,
216								&enumeration_attr_group);
217	}
218	wmi_priv.enumeration_instances_count = 0;
219
220	kfree(wmi_priv.enumeration_data);
221	wmi_priv.enumeration_data = NULL;
222}
~/ Read-only file preview.