brintos

brintos / linux-shallow public Read only

0
0
Text · 5.1 KiB · 230e6ee Raw
197 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Functions corresponding to password object type attributes under BIOS Password Object GUID for4 * use with dell-wmi-sysman5 *6 *  Copyright (c) 2020 Dell Inc.7 */8 9#include "dell-wmi-sysman.h"10 11enum po_properties {IS_PASS_SET = 1, MIN_PASS_LEN, MAX_PASS_LEN};12 13get_instance_id(po);14 15static ssize_t is_enabled_show(struct kobject *kobj, struct kobj_attribute *attr,16					  char *buf)17{18	int instance_id = get_po_instance_id(kobj);19	union acpi_object *obj;20	ssize_t ret;21 22	if (instance_id < 0)23		return instance_id;24 25	/* need to use specific instance_id and guid combination to get right data */26	obj = get_wmiobj_pointer(instance_id, DELL_WMI_BIOS_PASSOBJ_ATTRIBUTE_GUID);27	if (!obj)28		return -EIO;29	if (obj->package.elements[IS_PASS_SET].type != ACPI_TYPE_INTEGER) {30		kfree(obj);31		return -EINVAL;32	}33	ret = snprintf(buf, PAGE_SIZE, "%lld\n", obj->package.elements[IS_PASS_SET].integer.value);34	kfree(obj);35	return ret;36}37 38static struct kobj_attribute po_is_pass_set = __ATTR_RO(is_enabled);39 40static ssize_t current_password_store(struct kobject *kobj,41				      struct kobj_attribute *attr,42				      const char *buf, size_t count)43{44	char *target = NULL;45	int length;46 47	length = strlen(buf);48	if (buf[length-1] == '\n')49		length--;50 51	/* firmware does verifiation of min/max password length,52	 * hence only check for not exceeding MAX_BUFF here.53	 */54	if (length >= MAX_BUFF)55		return -EINVAL;56 57	if (strcmp(kobj->name, "Admin") == 0)58		target = wmi_priv.current_admin_password;59	else if (strcmp(kobj->name, "System") == 0)60		target = wmi_priv.current_system_password;61	if (!target)62		return -EIO;63	memcpy(target, buf, length);64	target[length] = '\0';65 66	return count;67}68 69static struct kobj_attribute po_current_password = __ATTR_WO(current_password);70 71static ssize_t new_password_store(struct kobject *kobj,72				  struct kobj_attribute *attr,73				  const char *buf, size_t count)74{75	char *p, *buf_cp;76	int ret;77 78	buf_cp = kstrdup(buf, GFP_KERNEL);79	if (!buf_cp)80		return -ENOMEM;81	p = memchr(buf_cp, '\n', count);82 83	if (p != NULL)84		*p = '\0';85	if (strlen(buf_cp) > MAX_BUFF) {86		ret = -EINVAL;87		goto out;88	}89 90	ret = set_new_password(kobj->name, buf_cp);91 92out:93	kfree(buf_cp);94	return ret ? ret : count;95}96 97static struct kobj_attribute po_new_password = __ATTR_WO(new_password);98 99attribute_n_property_show(min_password_length, po);100static struct kobj_attribute po_min_pass_length = __ATTR_RO(min_password_length);101 102attribute_n_property_show(max_password_length, po);103static struct kobj_attribute po_max_pass_length = __ATTR_RO(max_password_length);104 105static ssize_t mechanism_show(struct kobject *kobj, struct kobj_attribute *attr,106			 char *buf)107{108	return sprintf(buf, "password\n");109}110 111static struct kobj_attribute po_mechanism = __ATTR_RO(mechanism);112 113static ssize_t role_show(struct kobject *kobj, struct kobj_attribute *attr,114			 char *buf)115{116	if (strcmp(kobj->name, "Admin") == 0)117		return sprintf(buf, "bios-admin\n");118	else if (strcmp(kobj->name, "System") == 0)119		return sprintf(buf, "power-on\n");120	return -EIO;121}122 123static struct kobj_attribute po_role = __ATTR_RO(role);124 125static struct attribute *po_attrs[] = {126	&po_is_pass_set.attr,127	&po_min_pass_length.attr,128	&po_max_pass_length.attr,129	&po_current_password.attr,130	&po_new_password.attr,131	&po_role.attr,132	&po_mechanism.attr,133	NULL,134};135 136static const struct attribute_group po_attr_group = {137	.attrs = po_attrs,138};139 140int alloc_po_data(void)141{142	int ret = 0;143 144	wmi_priv.po_instances_count = get_instance_count(DELL_WMI_BIOS_PASSOBJ_ATTRIBUTE_GUID);145	wmi_priv.po_data = kcalloc(wmi_priv.po_instances_count, sizeof(struct po_data), GFP_KERNEL);146	if (!wmi_priv.po_data) {147		wmi_priv.po_instances_count = 0;148		ret = -ENOMEM;149	}150	return ret;151}152 153/**154 * populate_po_data() - Populate all properties of an instance under password object attribute155 * @po_obj: ACPI object with password object data156 * @instance_id: The instance to enumerate157 * @attr_name_kobj: The parent kernel object158 */159int populate_po_data(union acpi_object *po_obj, int instance_id, struct kobject *attr_name_kobj)160{161	wmi_priv.po_data[instance_id].attr_name_kobj = attr_name_kobj;162	if (check_property_type(po, ATTR_NAME, ACPI_TYPE_STRING))163		return -EINVAL;164	strlcpy_attr(wmi_priv.po_data[instance_id].attribute_name,165		     po_obj[ATTR_NAME].string.pointer);166	if (check_property_type(po, MIN_PASS_LEN, ACPI_TYPE_INTEGER))167		return -EINVAL;168	wmi_priv.po_data[instance_id].min_password_length =169		(uintptr_t)po_obj[MIN_PASS_LEN].string.pointer;170	if (check_property_type(po, MAX_PASS_LEN, ACPI_TYPE_INTEGER))171		return -EINVAL;172	wmi_priv.po_data[instance_id].max_password_length =173		(uintptr_t) po_obj[MAX_PASS_LEN].string.pointer;174 175	return sysfs_create_group(attr_name_kobj, &po_attr_group);176}177 178/**179 * exit_po_attributes() - Clear all attribute data180 *181 * Clears all data allocated for this group of attributes182 */183void exit_po_attributes(void)184{185	int instance_id;186 187	for (instance_id = 0; instance_id < wmi_priv.po_instances_count; instance_id++) {188		if (wmi_priv.po_data[instance_id].attr_name_kobj)189			sysfs_remove_group(wmi_priv.po_data[instance_id].attr_name_kobj,190								&po_attr_group);191	}192	wmi_priv.po_instances_count = 0;193 194	kfree(wmi_priv.po_data);195	wmi_priv.po_data = NULL;196}197