1 // SPDX-License-Identifier: GPL-2.0
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.
9 #include "dell-wmi-sysman.h"
11 enum po_properties
{IS_PASS_SET
= 1, MIN_PASS_LEN
, MAX_PASS_LEN
};
15 static ssize_t
is_enabled_show(struct kobject
*kobj
, struct kobj_attribute
*attr
,
18 int instance_id
= get_po_instance_id(kobj
);
19 union acpi_object
*obj
;
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
);
29 if (obj
->package
.elements
[IS_PASS_SET
].type
!= ACPI_TYPE_INTEGER
) {
33 ret
= snprintf(buf
, PAGE_SIZE
, "%lld\n", obj
->package
.elements
[IS_PASS_SET
].integer
.value
);
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
)
48 if (buf
[length
-1] == '\n')
51 /* firmware does verifiation of min/max password length,
52 * hence only check for not exceeding MAX_BUFF here.
54 if (length
>= MAX_BUFF
)
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
;
63 memcpy(target
, buf
, length
);
64 target
[length
] = '\0';
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
)
78 buf_cp
= kstrdup(buf
, GFP_KERNEL
);
81 p
= memchr(buf_cp
, '\n', count
);
85 if (strlen(buf_cp
) > MAX_BUFF
) {
90 ret
= set_new_password(kobj
->name
, 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
,
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
,
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");
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
,
136 static const struct attribute_group po_attr_group
= {
140 int alloc_po_data(void)
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;
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)
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
,
186 kfree(wmi_priv
.po_data
);