File Index
Files and directories
Sign in
FILE

passobj-attributes.c

File preview with syntax highlighting.

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