brintos

brintos / linux-shallow public Read only

0
0
Text · 4.8 KiB · c2dd2de Raw
186 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Functions corresponding to SET methods under BIOS attributes interface GUID for use4 * with dell-wmi-sysman5 *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					0x0213#define SETBIOSDEFAULTS_METHOD_ID					0x0314#define SETATTRIBUTE_METHOD_ID						0x0415 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 value45 * @a_name: The attribute name46 * @a_value: The attribute value47 *48 * Sets an attribute to new value49 */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 defaults104 * @deftype: the type of BIOS value reset to issue.105 *106 * Resets BIOS defaults107 */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_NAME169	},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);186