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