cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

int-attributes.c (6169B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Functions corresponding to integer type attributes under BIOS Integer GUID for use with
      4 * dell-wmi-sysman
      5 *
      6 *  Copyright (c) 2020 Dell Inc.
      7 */
      8
      9#include "dell-wmi-sysman.h"
     10
     11enum int_properties {MIN_VALUE = 6, MAX_VALUE, SCALAR_INCR};
     12
     13get_instance_id(integer);
     14
     15static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
     16{
     17	int instance_id = get_integer_instance_id(kobj);
     18	union acpi_object *obj;
     19	ssize_t ret;
     20
     21	if (instance_id < 0)
     22		return instance_id;
     23
     24	/* need to use specific instance_id and guid combination to get right data */
     25	obj = get_wmiobj_pointer(instance_id, DELL_WMI_BIOS_INTEGER_ATTRIBUTE_GUID);
     26	if (!obj)
     27		return -EIO;
     28	if (obj->package.elements[CURRENT_VAL].type != ACPI_TYPE_INTEGER) {
     29		kfree(obj);
     30		return -EINVAL;
     31	}
     32	ret = snprintf(buf, PAGE_SIZE, "%lld\n", obj->package.elements[CURRENT_VAL].integer.value);
     33	kfree(obj);
     34	return ret;
     35}
     36
     37/**
     38 * validate_integer_input() - Validate input of current_value against lower and upper bound
     39 * @instance_id: The instance on which input is validated
     40 * @buf: Input value
     41 */
     42static int validate_integer_input(int instance_id, char *buf)
     43{
     44	int in_val;
     45	int ret;
     46
     47	ret = kstrtoint(buf, 0, &in_val);
     48	if (ret)
     49		return ret;
     50	if (in_val < wmi_priv.integer_data[instance_id].min_value ||
     51			in_val > wmi_priv.integer_data[instance_id].max_value)
     52		return -EINVAL;
     53
     54	/* workaround for BIOS error.
     55	 * validate input to avoid setting 0 when integer input passed with + sign
     56	 */
     57	if (*buf == '+')
     58		memmove(buf, (buf + 1), strlen(buf + 1) + 1);
     59
     60	return ret;
     61}
     62
     63attribute_s_property_show(display_name_language_code, integer);
     64static struct kobj_attribute integer_displ_langcode =
     65	__ATTR_RO(display_name_language_code);
     66
     67attribute_s_property_show(display_name, integer);
     68static struct kobj_attribute integer_displ_name =
     69	__ATTR_RO(display_name);
     70
     71attribute_n_property_show(default_value, integer);
     72static struct kobj_attribute integer_default_val =
     73	__ATTR_RO(default_value);
     74
     75attribute_property_store(current_value, integer);
     76static struct kobj_attribute integer_current_val =
     77	__ATTR_RW_MODE(current_value, 0600);
     78
     79attribute_s_property_show(dell_modifier, integer);
     80static struct kobj_attribute integer_modifier =
     81	__ATTR_RO(dell_modifier);
     82
     83attribute_n_property_show(min_value, integer);
     84static struct kobj_attribute integer_lower_bound =
     85	__ATTR_RO(min_value);
     86
     87attribute_n_property_show(max_value, integer);
     88static struct kobj_attribute integer_upper_bound =
     89	__ATTR_RO(max_value);
     90
     91attribute_n_property_show(scalar_increment, integer);
     92static struct kobj_attribute integer_scalar_increment =
     93	__ATTR_RO(scalar_increment);
     94
     95static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
     96			 char *buf)
     97{
     98	return sprintf(buf, "integer\n");
     99}
    100static struct kobj_attribute integer_type =
    101	__ATTR_RO(type);
    102
    103static struct attribute *integer_attrs[] = {
    104	&integer_displ_langcode.attr,
    105	&integer_displ_name.attr,
    106	&integer_default_val.attr,
    107	&integer_current_val.attr,
    108	&integer_modifier.attr,
    109	&integer_lower_bound.attr,
    110	&integer_upper_bound.attr,
    111	&integer_scalar_increment.attr,
    112	&integer_type.attr,
    113	NULL,
    114};
    115
    116static const struct attribute_group integer_attr_group = {
    117	.attrs = integer_attrs,
    118};
    119
    120int alloc_int_data(void)
    121{
    122	int ret = 0;
    123
    124	wmi_priv.integer_instances_count = get_instance_count(DELL_WMI_BIOS_INTEGER_ATTRIBUTE_GUID);
    125	wmi_priv.integer_data = kcalloc(wmi_priv.integer_instances_count,
    126					sizeof(struct integer_data), GFP_KERNEL);
    127	if (!wmi_priv.integer_data) {
    128		wmi_priv.integer_instances_count = 0;
    129		ret = -ENOMEM;
    130	}
    131	return ret;
    132}
    133
    134/**
    135 * populate_int_data() - Populate all properties of an instance under integer attribute
    136 * @integer_obj: ACPI object with integer data
    137 * @instance_id: The instance to enumerate
    138 * @attr_name_kobj: The parent kernel object
    139 */
    140int populate_int_data(union acpi_object *integer_obj, int instance_id,
    141			struct kobject *attr_name_kobj)
    142{
    143	wmi_priv.integer_data[instance_id].attr_name_kobj = attr_name_kobj;
    144	if (check_property_type(integer, ATTR_NAME, ACPI_TYPE_STRING))
    145		return -EINVAL;
    146	strlcpy_attr(wmi_priv.integer_data[instance_id].attribute_name,
    147		integer_obj[ATTR_NAME].string.pointer);
    148	if (check_property_type(integer, DISPL_NAME_LANG_CODE, ACPI_TYPE_STRING))
    149		return -EINVAL;
    150	strlcpy_attr(wmi_priv.integer_data[instance_id].display_name_language_code,
    151		integer_obj[DISPL_NAME_LANG_CODE].string.pointer);
    152	if (check_property_type(integer, DISPLAY_NAME, ACPI_TYPE_STRING))
    153		return -EINVAL;
    154	strlcpy_attr(wmi_priv.integer_data[instance_id].display_name,
    155		integer_obj[DISPLAY_NAME].string.pointer);
    156	if (check_property_type(integer, DEFAULT_VAL, ACPI_TYPE_INTEGER))
    157		return -EINVAL;
    158	wmi_priv.integer_data[instance_id].default_value =
    159		(uintptr_t)integer_obj[DEFAULT_VAL].string.pointer;
    160	if (check_property_type(integer, MODIFIER, ACPI_TYPE_STRING))
    161		return -EINVAL;
    162	strlcpy_attr(wmi_priv.integer_data[instance_id].dell_modifier,
    163		integer_obj[MODIFIER].string.pointer);
    164	if (check_property_type(integer, MIN_VALUE, ACPI_TYPE_INTEGER))
    165		return -EINVAL;
    166	wmi_priv.integer_data[instance_id].min_value =
    167		(uintptr_t)integer_obj[MIN_VALUE].string.pointer;
    168	if (check_property_type(integer, MAX_VALUE, ACPI_TYPE_INTEGER))
    169		return -EINVAL;
    170	wmi_priv.integer_data[instance_id].max_value =
    171		(uintptr_t)integer_obj[MAX_VALUE].string.pointer;
    172	if (check_property_type(integer, SCALAR_INCR, ACPI_TYPE_INTEGER))
    173		return -EINVAL;
    174	wmi_priv.integer_data[instance_id].scalar_increment =
    175		(uintptr_t)integer_obj[SCALAR_INCR].string.pointer;
    176
    177	return sysfs_create_group(attr_name_kobj, &integer_attr_group);
    178}
    179
    180/**
    181 * exit_int_attributes() - Clear all attribute data
    182 *
    183 * Clears all data allocated for this group of attributes
    184 */
    185void exit_int_attributes(void)
    186{
    187	int instance_id;
    188
    189	for (instance_id = 0; instance_id < wmi_priv.integer_instances_count; instance_id++) {
    190		if (wmi_priv.integer_data[instance_id].attr_name_kobj)
    191			sysfs_remove_group(wmi_priv.integer_data[instance_id].attr_name_kobj,
    192								&integer_attr_group);
    193	}
    194	wmi_priv.integer_instances_count = 0;
    195
    196	kfree(wmi_priv.integer_data);
    197	wmi_priv.integer_data = NULL;
    198}