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->package.elements[IS_PASS_SET].type != ACPI_TYPE_INTEGER) { 30 kfree(obj); 31 return -EINVAL; 32 } 33 ret = snprintf(buf, PAGE_SIZE, "%lld\n", obj->package.elements[IS_PASS_SET].integer.value); 34 kfree(obj); 35 return ret; 36 } 37 38 static struct kobj_attribute po_is_pass_set = __ATTR_RO(is_enabled); 39 40 static ssize_t current_password_store(struct kobject *kobj, 41 struct kobj_attribute *attr, 42 const char *buf, size_t count) 43 { 44 char *target = NULL; 45 int length; 46 47 length = strlen(buf); 48 if (buf[length-1] == '\n') 49 length--; 50 51 /* firmware does verifiation of min/max password length, 52 * hence only check for not exceeding MAX_BUFF here. 53 */ 54 if (length >= MAX_BUFF) 55 return -EINVAL; 56 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'; 65 66 return count; 67 } 68 69 static struct kobj_attribute po_current_password = __ATTR_WO(current_password); 70 71 static ssize_t new_password_store(struct kobject *kobj, 72 struct kobj_attribute *attr, 73 const char *buf, size_t count) 74 { 75 char *p, *buf_cp; 76 int ret; 77 78 buf_cp = kstrdup(buf, GFP_KERNEL); 79 if (!buf_cp) 80 return -ENOMEM; 81 p = memchr(buf_cp, '\n', count); 82 83 if (p != NULL) 84 *p = '\0'; 85 if (strlen(buf_cp) > MAX_BUFF) { 86 ret = -EINVAL; 87 goto out; 88 } 89 90 ret = set_new_password(kobj->name, buf_cp); 91 92 out: 93 kfree(buf_cp); 94 return ret ? ret : count; 95 } 96 97 static struct kobj_attribute po_new_password = __ATTR_WO(new_password); 98 99 attribute_n_property_show(min_password_length, po); 100 static struct kobj_attribute po_min_pass_length = __ATTR_RO(min_password_length); 101 102 attribute_n_property_show(max_password_length, po); 103 static struct kobj_attribute po_max_pass_length = __ATTR_RO(max_password_length); 104 105 static ssize_t mechanism_show(struct kobject *kobj, struct kobj_attribute *attr, 106 char *buf) 107 { 108 return sprintf(buf, "password\n"); 109 } 110 111 static struct kobj_attribute po_mechanism = __ATTR_RO(mechanism); 112 113 static ssize_t role_show(struct kobject *kobj, struct kobj_attribute *attr, 114 char *buf) 115 { 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; 121 } 122 123 static struct kobj_attribute po_role = __ATTR_RO(role); 124 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, 134 }; 135 136 static const struct attribute_group po_attr_group = { 137 .attrs = po_attrs, 138 }; 139 140 int alloc_po_data(void) 141 { 142 int ret = 0; 143 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; 149 } 150 return ret; 151 } 152 153 /** 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 158 */ 159 int populate_po_data(union acpi_object *po_obj, int instance_id, struct kobject *attr_name_kobj) 160 { 161 wmi_priv.po_data[instance_id].attr_name_kobj = attr_name_kobj; 162 if (check_property_type(po, ATTR_NAME, ACPI_TYPE_STRING)) 163 return -EINVAL; 164 strlcpy_attr(wmi_priv.po_data[instance_id].attribute_name, 165 po_obj[ATTR_NAME].string.pointer); 166 if (check_property_type(po, MIN_PASS_LEN, ACPI_TYPE_INTEGER)) 167 return -EINVAL; 168 wmi_priv.po_data[instance_id].min_password_length = 169 (uintptr_t)po_obj[MIN_PASS_LEN].string.pointer; 170 if (check_property_type(po, MAX_PASS_LEN, ACPI_TYPE_INTEGER)) 171 return -EINVAL; 172 wmi_priv.po_data[instance_id].max_password_length = 173 (uintptr_t) po_obj[MAX_PASS_LEN].string.pointer; 174 175 return sysfs_create_group(attr_name_kobj, &po_attr_group); 176 } 177 178 /** 179 * exit_po_attributes() - Clear all attribute data 180 * 181 * Clears all data allocated for this group of attributes 182 */ 183 void exit_po_attributes(void) 184 { 185 int instance_id; 186 187 for (instance_id = 0; instance_id < wmi_priv.po_instances_count; instance_id++) { 188 if (wmi_priv.po_data[instance_id].attr_name_kobj) 189 sysfs_remove_group(wmi_priv.po_data[instance_id].attr_name_kobj, 190 &po_attr_group); 191 } 192 wmi_priv.po_instances_count = 0; 193 194 kfree(wmi_priv.po_data); 195 wmi_priv.po_data = NULL; 196 } 197