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

biosattr-interface.c (4891B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Functions corresponding to SET methods under BIOS attributes interface GUID for use
      4 * with dell-wmi-sysman
      5 *
      6 *  Copyright (c) 2020 Dell Inc.
      7 */
      8
      9#include <linux/wmi.h>
     10#include "dell-wmi-sysman.h"
     11
     12#define SETDEFAULTVALUES_METHOD_ID					0x02
     13#define SETBIOSDEFAULTS_METHOD_ID					0x03
     14#define SETATTRIBUTE_METHOD_ID						0x04
     15
     16static int call_biosattributes_interface(struct wmi_device *wdev, char *in_args, size_t size,
     17					int method_id)
     18{
     19	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
     20	struct acpi_buffer input;
     21	union acpi_object *obj;
     22	acpi_status status;
     23	int ret = -EIO;
     24
     25	input.length =  (acpi_size) size;
     26	input.pointer = in_args;
     27	status = wmidev_evaluate_method(wdev, 0, method_id, &input, &output);
     28	if (ACPI_FAILURE(status))
     29		return -EIO;
     30	obj = (union acpi_object *)output.pointer;
     31	if (obj->type == ACPI_TYPE_INTEGER)
     32		ret = obj->integer.value;
     33
     34	if (wmi_priv.pending_changes == 0) {
     35		wmi_priv.pending_changes = 1;
     36		/* let userland know it may need to check reboot pending again */
     37		kobject_uevent(&wmi_priv.class_dev->kobj, KOBJ_CHANGE);
     38	}
     39	kfree(output.pointer);
     40	return map_wmi_error(ret);
     41}
     42
     43/**
     44 * set_attribute() - Update an attribute value
     45 * @a_name: The attribute name
     46 * @a_value: The attribute value
     47 *
     48 * Sets an attribute to new value
     49 */
     50int set_attribute(const char *a_name, const char *a_value)
     51{
     52	size_t security_area_size, buffer_size;
     53	size_t a_name_size, a_value_size;
     54	char *buffer = NULL, *start;
     55	int ret;
     56
     57	mutex_lock(&wmi_priv.mutex);
     58	if (!wmi_priv.bios_attr_wdev) {
     59		ret = -ENODEV;
     60		goto out;
     61	}
     62
     63	/* build/calculate buffer */
     64	security_area_size = calculate_security_buffer(wmi_priv.current_admin_password);
     65	a_name_size = calculate_string_buffer(a_name);
     66	a_value_size = calculate_string_buffer(a_value);
     67	buffer_size = security_area_size + a_name_size + a_value_size;
     68	buffer = kzalloc(buffer_size, GFP_KERNEL);
     69	if (!buffer) {
     70		ret = -ENOMEM;
     71		goto out;
     72	}
     73
     74	/* build security area */
     75	populate_security_buffer(buffer, wmi_priv.current_admin_password);
     76
     77	/* build variables to set */
     78	start = buffer + security_area_size;
     79	ret = populate_string_buffer(start, a_name_size, a_name);
     80	if (ret < 0)
     81		goto out;
     82	start += ret;
     83	ret = populate_string_buffer(start, a_value_size, a_value);
     84	if (ret < 0)
     85		goto out;
     86
     87	print_hex_dump_bytes("set attribute data: ", DUMP_PREFIX_NONE, buffer, buffer_size);
     88	ret = call_biosattributes_interface(wmi_priv.bios_attr_wdev,
     89					    buffer, buffer_size,
     90					    SETATTRIBUTE_METHOD_ID);
     91	if (ret == -EOPNOTSUPP)
     92		dev_err(&wmi_priv.bios_attr_wdev->dev, "admin password must be configured\n");
     93	else if (ret == -EACCES)
     94		dev_err(&wmi_priv.bios_attr_wdev->dev, "invalid password\n");
     95
     96out:
     97	kfree(buffer);
     98	mutex_unlock(&wmi_priv.mutex);
     99	return ret;
    100}
    101
    102/**
    103 * set_bios_defaults() - Resets BIOS defaults
    104 * @deftype: the type of BIOS value reset to issue.
    105 *
    106 * Resets BIOS defaults
    107 */
    108int set_bios_defaults(u8 deftype)
    109{
    110	size_t security_area_size, buffer_size;
    111	size_t integer_area_size = sizeof(u8);
    112	char *buffer = NULL;
    113	u8 *defaultType;
    114	int ret;
    115
    116	mutex_lock(&wmi_priv.mutex);
    117	if (!wmi_priv.bios_attr_wdev) {
    118		ret = -ENODEV;
    119		goto out;
    120	}
    121
    122	security_area_size = calculate_security_buffer(wmi_priv.current_admin_password);
    123	buffer_size = security_area_size + integer_area_size;
    124	buffer = kzalloc(buffer_size, GFP_KERNEL);
    125	if (!buffer) {
    126		ret = -ENOMEM;
    127		goto out;
    128	}
    129
    130	/* build security area */
    131	populate_security_buffer(buffer, wmi_priv.current_admin_password);
    132
    133	defaultType = buffer + security_area_size;
    134	*defaultType = deftype;
    135
    136	ret = call_biosattributes_interface(wmi_priv.bios_attr_wdev, buffer, buffer_size,
    137					    SETBIOSDEFAULTS_METHOD_ID);
    138	if (ret)
    139		dev_err(&wmi_priv.bios_attr_wdev->dev, "reset BIOS defaults failed: %d\n", ret);
    140
    141	kfree(buffer);
    142out:
    143	mutex_unlock(&wmi_priv.mutex);
    144	return ret;
    145}
    146
    147static int bios_attr_set_interface_probe(struct wmi_device *wdev, const void *context)
    148{
    149	mutex_lock(&wmi_priv.mutex);
    150	wmi_priv.bios_attr_wdev = wdev;
    151	mutex_unlock(&wmi_priv.mutex);
    152	return 0;
    153}
    154
    155static void bios_attr_set_interface_remove(struct wmi_device *wdev)
    156{
    157	mutex_lock(&wmi_priv.mutex);
    158	wmi_priv.bios_attr_wdev = NULL;
    159	mutex_unlock(&wmi_priv.mutex);
    160}
    161
    162static const struct wmi_device_id bios_attr_set_interface_id_table[] = {
    163	{ .guid_string = DELL_WMI_BIOS_ATTRIBUTES_INTERFACE_GUID },
    164	{ },
    165};
    166static struct wmi_driver bios_attr_set_interface_driver = {
    167	.driver = {
    168		.name = DRIVER_NAME
    169	},
    170	.probe = bios_attr_set_interface_probe,
    171	.remove = bios_attr_set_interface_remove,
    172	.id_table = bios_attr_set_interface_id_table,
    173};
    174
    175int init_bios_attr_set_interface(void)
    176{
    177	return wmi_driver_register(&bios_attr_set_interface_driver);
    178}
    179
    180void exit_bios_attr_set_interface(void)
    181{
    182	wmi_driver_unregister(&bios_attr_set_interface_driver);
    183}
    184
    185MODULE_DEVICE_TABLE(wmi, bios_attr_set_interface_id_table);