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 11 enum po_properties {IS_PASS_SET = 1, MIN_PASS_LEN, MAX_PASS_LEN}; 12 13 get_instance_id(po); 14 15 static 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 39 static struct kobj_attribute po_is_pass_set = __ATTR_RO(is_enabled); 40 41 static 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 70 static struct kobj_attribute po_current_password = __ATTR_WO(current_password); 71 72 static 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 93 out: 94 kfree(buf_cp); 95 return ret ? ret : count; 96 } 97 98 static struct kobj_attribute po_new_password = __ATTR_WO(new_password); 99 100 attribute_n_property_show(min_password_length, po); 101 static struct kobj_attribute po_min_pass_length = __ATTR_RO(min_password_length); 102 103 attribute_n_property_show(max_password_length, po); 104 static struct kobj_attribute po_max_pass_length = __ATTR_RO(max_password_length); 105 106 static ssize_t mechanism_show(struct kobject *kobj, struct kobj_attribute *attr, 107 char *buf) 108 { 109 return sprintf(buf, "password\n"); 110 } 111 112 static struct kobj_attribute po_mechanism = __ATTR_RO(mechanism); 113 114 static 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 124 static struct kobj_attribute po_role = __ATTR_RO(role); 125 126 static 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 137 static const struct attribute_group po_attr_group = { 138 .attrs = po_attrs, 139 }; 140 141 int 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 */ 160 int 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 */ 184 void 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 } 198