Merge tag 'regmap-fix-v5.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux/fpc-iii.git] / drivers / platform / x86 / dell-wmi-sysman / passobj-attributes.c
blob3abcd95477c0789d67aabc1e01b8bc5435e192eb
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
6 * Copyright (c) 2020 Dell Inc.
7 */
9 #include "dell-wmi-sysman.h"
11 enum po_properties {IS_PASS_SET = 1, MIN_PASS_LEN, MAX_PASS_LEN};
13 get_instance_id(po);
15 static ssize_t is_enabled_show(struct kobject *kobj, struct kobj_attribute *attr,
16 char *buf)
18 int instance_id = get_po_instance_id(kobj);
19 union acpi_object *obj;
20 ssize_t ret;
22 if (instance_id < 0)
23 return instance_id;
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;
33 ret = snprintf(buf, PAGE_SIZE, "%lld\n", obj->package.elements[IS_PASS_SET].integer.value);
34 kfree(obj);
35 return ret;
38 static struct kobj_attribute po_is_pass_set = __ATTR_RO(is_enabled);
40 static ssize_t current_password_store(struct kobject *kobj,
41 struct kobj_attribute *attr,
42 const char *buf, size_t count)
44 char *target = NULL;
45 int length;
47 length = strlen(buf);
48 if (buf[length-1] == '\n')
49 length--;
51 /* firmware does verifiation of min/max password length,
52 * hence only check for not exceeding MAX_BUFF here.
54 if (length >= MAX_BUFF)
55 return -EINVAL;
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';
66 return count;
69 static struct kobj_attribute po_current_password = __ATTR_WO(current_password);
71 static ssize_t new_password_store(struct kobject *kobj,
72 struct kobj_attribute *attr,
73 const char *buf, size_t count)
75 char *p, *buf_cp;
76 int ret;
78 buf_cp = kstrdup(buf, GFP_KERNEL);
79 if (!buf_cp)
80 return -ENOMEM;
81 p = memchr(buf_cp, '\n', count);
83 if (p != NULL)
84 *p = '\0';
85 if (strlen(buf_cp) > MAX_BUFF) {
86 ret = -EINVAL;
87 goto out;
90 ret = set_new_password(kobj->name, buf_cp);
92 out:
93 kfree(buf_cp);
94 return ret ? ret : count;
97 static struct kobj_attribute po_new_password = __ATTR_WO(new_password);
99 attribute_n_property_show(min_password_length, po);
100 static struct kobj_attribute po_min_pass_length = __ATTR_RO(min_password_length);
102 attribute_n_property_show(max_password_length, po);
103 static struct kobj_attribute po_max_pass_length = __ATTR_RO(max_password_length);
105 static ssize_t mechanism_show(struct kobject *kobj, struct kobj_attribute *attr,
106 char *buf)
108 return sprintf(buf, "password\n");
111 static struct kobj_attribute po_mechanism = __ATTR_RO(mechanism);
113 static ssize_t role_show(struct kobject *kobj, struct kobj_attribute *attr,
114 char *buf)
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;
123 static struct kobj_attribute po_role = __ATTR_RO(role);
125 static 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,
136 static const struct attribute_group po_attr_group = {
137 .attrs = po_attrs,
140 int alloc_po_data(void)
142 int ret = 0;
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;
150 return ret;
154 * populate_po_data() - Populate all properties of an instance under password object attribute
155 * @po_obj: ACPI object with password object data
156 * @instance_id: The instance to enumerate
157 * @attr_name_kobj: The parent kernel object
159 int populate_po_data(union acpi_object *po_obj, int instance_id, struct kobject *attr_name_kobj)
161 wmi_priv.po_data[instance_id].attr_name_kobj = attr_name_kobj;
162 strlcpy_attr(wmi_priv.po_data[instance_id].attribute_name,
163 po_obj[ATTR_NAME].string.pointer);
164 wmi_priv.po_data[instance_id].min_password_length =
165 (uintptr_t)po_obj[MIN_PASS_LEN].string.pointer;
166 wmi_priv.po_data[instance_id].max_password_length =
167 (uintptr_t) po_obj[MAX_PASS_LEN].string.pointer;
169 return sysfs_create_group(attr_name_kobj, &po_attr_group);
173 * exit_po_attributes() - Clear all attribute data
175 * Clears all data allocated for this group of attributes
177 void exit_po_attributes(void)
179 int instance_id;
181 for (instance_id = 0; instance_id < wmi_priv.po_instances_count; instance_id++) {
182 if (wmi_priv.po_data[instance_id].attr_name_kobj)
183 sysfs_remove_group(wmi_priv.po_data[instance_id].attr_name_kobj,
184 &po_attr_group);
186 kfree(wmi_priv.po_data);