1 // SPDX-License-Identifier: GPL-2.0
3 * Functions corresponding to SET password methods under BIOS attributes interface GUID
5 * Copyright (c) 2020 Dell Inc.
9 #include "dell-wmi-sysman.h"
11 static int call_password_interface(struct wmi_device
*wdev
, char *in_args
, size_t size
)
13 struct acpi_buffer output
= {ACPI_ALLOCATE_BUFFER
, NULL
};
14 struct acpi_buffer input
;
15 union acpi_object
*obj
;
19 input
.length
= (acpi_size
) size
;
20 input
.pointer
= in_args
;
21 status
= wmidev_evaluate_method(wdev
, 0, 1, &input
, &output
);
22 if (ACPI_FAILURE(status
))
24 obj
= (union acpi_object
*)output
.pointer
;
25 if (obj
->type
== ACPI_TYPE_INTEGER
)
26 ret
= obj
->integer
.value
;
28 kfree(output
.pointer
);
29 /* let userland know it may need to check is_password_set again */
30 kobject_uevent(&wmi_priv
.class_dev
->kobj
, KOBJ_CHANGE
);
31 return map_wmi_error(ret
);
35 * set_new_password() - Sets a system admin password
36 * @password_type: The type of password to set
37 * @new: The new password
39 * Sets the password using plaintext interface
41 int set_new_password(const char *password_type
, const char *new)
43 size_t password_type_size
, current_password_size
, new_size
;
44 size_t security_area_size
, buffer_size
;
45 char *buffer
= NULL
, *start
;
46 char *current_password
;
49 mutex_lock(&wmi_priv
.mutex
);
50 if (!wmi_priv
.password_attr_wdev
) {
54 if (strcmp(password_type
, "Admin") == 0) {
55 current_password
= wmi_priv
.current_admin_password
;
56 } else if (strcmp(password_type
, "System") == 0) {
57 current_password
= wmi_priv
.current_system_password
;
60 dev_err(&wmi_priv
.password_attr_wdev
->dev
, "unknown password type %s\n",
65 /* build/calculate buffer */
66 security_area_size
= calculate_security_buffer(wmi_priv
.current_admin_password
);
67 password_type_size
= calculate_string_buffer(password_type
);
68 current_password_size
= calculate_string_buffer(current_password
);
69 new_size
= calculate_string_buffer(new);
70 buffer_size
= security_area_size
+ password_type_size
+ current_password_size
+ new_size
;
71 buffer
= kzalloc(buffer_size
, GFP_KERNEL
);
77 /* build security area */
78 populate_security_buffer(buffer
, wmi_priv
.current_admin_password
);
80 /* build variables to set */
81 start
= buffer
+ security_area_size
;
82 ret
= populate_string_buffer(start
, password_type_size
, password_type
);
87 ret
= populate_string_buffer(start
, current_password_size
, current_password
);
92 ret
= populate_string_buffer(start
, new_size
, new);
96 print_hex_dump_bytes("set new password data: ", DUMP_PREFIX_NONE
, buffer
, buffer_size
);
97 ret
= call_password_interface(wmi_priv
.password_attr_wdev
, buffer
, buffer_size
);
98 /* clear current_password here and use user input from wmi_priv.current_password */
100 memset(current_password
, 0, MAX_BUFF
);
101 /* explain to user the detailed failure reason */
102 else if (ret
== -EOPNOTSUPP
)
103 dev_err(&wmi_priv
.password_attr_wdev
->dev
, "admin password must be configured\n");
104 else if (ret
== -EACCES
)
105 dev_err(&wmi_priv
.password_attr_wdev
->dev
, "invalid password\n");
109 mutex_unlock(&wmi_priv
.mutex
);
114 static int bios_attr_pass_interface_probe(struct wmi_device
*wdev
, const void *context
)
116 mutex_lock(&wmi_priv
.mutex
);
117 wmi_priv
.password_attr_wdev
= wdev
;
118 mutex_unlock(&wmi_priv
.mutex
);
122 static int bios_attr_pass_interface_remove(struct wmi_device
*wdev
)
124 mutex_lock(&wmi_priv
.mutex
);
125 wmi_priv
.password_attr_wdev
= NULL
;
126 mutex_unlock(&wmi_priv
.mutex
);
130 static const struct wmi_device_id bios_attr_pass_interface_id_table
[] = {
131 { .guid_string
= DELL_WMI_BIOS_PASSWORD_INTERFACE_GUID
},
134 static struct wmi_driver bios_attr_pass_interface_driver
= {
136 .name
= DRIVER_NAME
"-password"
138 .probe
= bios_attr_pass_interface_probe
,
139 .remove
= bios_attr_pass_interface_remove
,
140 .id_table
= bios_attr_pass_interface_id_table
,
143 int init_bios_attr_pass_interface(void)
145 return wmi_driver_register(&bios_attr_pass_interface_driver
);
148 void exit_bios_attr_pass_interface(void)
150 wmi_driver_unregister(&bios_attr_pass_interface_driver
);
153 MODULE_DEVICE_TABLE(wmi
, bios_attr_pass_interface_id_table
);