1*e6c7b3e1SJorge Lopez // SPDX-License-Identifier: GPL-2.0 2*e6c7b3e1SJorge Lopez /* 3*e6c7b3e1SJorge Lopez * Functions corresponding to string type attributes under 4*e6c7b3e1SJorge Lopez * HP_WMI_BIOS_STRING_GUID for use with hp-bioscfg driver. 5*e6c7b3e1SJorge Lopez * 6*e6c7b3e1SJorge Lopez * Copyright (c) 2022 HP Development Company, L.P. 7*e6c7b3e1SJorge Lopez */ 8*e6c7b3e1SJorge Lopez 9*e6c7b3e1SJorge Lopez #include "bioscfg.h" 10*e6c7b3e1SJorge Lopez 11*e6c7b3e1SJorge Lopez #define WMI_STRING_TYPE "HPBIOS_BIOSString" 12*e6c7b3e1SJorge Lopez 13*e6c7b3e1SJorge Lopez GET_INSTANCE_ID(string); 14*e6c7b3e1SJorge Lopez 15*e6c7b3e1SJorge Lopez static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 16*e6c7b3e1SJorge Lopez { 17*e6c7b3e1SJorge Lopez int instance_id = get_string_instance_id(kobj); 18*e6c7b3e1SJorge Lopez 19*e6c7b3e1SJorge Lopez if (instance_id < 0) 20*e6c7b3e1SJorge Lopez return -EIO; 21*e6c7b3e1SJorge Lopez 22*e6c7b3e1SJorge Lopez return sysfs_emit(buf, "%s\n", 23*e6c7b3e1SJorge Lopez bioscfg_drv.string_data[instance_id].current_value); 24*e6c7b3e1SJorge Lopez } 25*e6c7b3e1SJorge Lopez 26*e6c7b3e1SJorge Lopez /** 27*e6c7b3e1SJorge Lopez * validate_string_input() - 28*e6c7b3e1SJorge Lopez * Validate input of current_value against min and max lengths 29*e6c7b3e1SJorge Lopez * 30*e6c7b3e1SJorge Lopez * @instance_id: The instance on which input is validated 31*e6c7b3e1SJorge Lopez * @buf: Input value 32*e6c7b3e1SJorge Lopez */ 33*e6c7b3e1SJorge Lopez static int validate_string_input(int instance_id, const char *buf) 34*e6c7b3e1SJorge Lopez { 35*e6c7b3e1SJorge Lopez int in_len = strlen(buf); 36*e6c7b3e1SJorge Lopez struct string_data *string_data = &bioscfg_drv.string_data[instance_id]; 37*e6c7b3e1SJorge Lopez 38*e6c7b3e1SJorge Lopez /* BIOS treats it as a read only attribute */ 39*e6c7b3e1SJorge Lopez if (string_data->common.is_readonly) 40*e6c7b3e1SJorge Lopez return -EIO; 41*e6c7b3e1SJorge Lopez 42*e6c7b3e1SJorge Lopez if (in_len < string_data->min_length || in_len > string_data->max_length) 43*e6c7b3e1SJorge Lopez return -ERANGE; 44*e6c7b3e1SJorge Lopez 45*e6c7b3e1SJorge Lopez return 0; 46*e6c7b3e1SJorge Lopez } 47*e6c7b3e1SJorge Lopez 48*e6c7b3e1SJorge Lopez static void update_string_value(int instance_id, char *attr_value) 49*e6c7b3e1SJorge Lopez { 50*e6c7b3e1SJorge Lopez struct string_data *string_data = &bioscfg_drv.string_data[instance_id]; 51*e6c7b3e1SJorge Lopez 52*e6c7b3e1SJorge Lopez /* Write settings to BIOS */ 53*e6c7b3e1SJorge Lopez strscpy(string_data->current_value, attr_value, sizeof(string_data->current_value)); 54*e6c7b3e1SJorge Lopez } 55*e6c7b3e1SJorge Lopez 56*e6c7b3e1SJorge Lopez /* 57*e6c7b3e1SJorge Lopez * ATTRIBUTE_S_COMMON_PROPERTY_SHOW(display_name_language_code, string); 58*e6c7b3e1SJorge Lopez * static struct kobj_attribute string_display_langcode = 59*e6c7b3e1SJorge Lopez * __ATTR_RO(display_name_language_code); 60*e6c7b3e1SJorge Lopez */ 61*e6c7b3e1SJorge Lopez 62*e6c7b3e1SJorge Lopez ATTRIBUTE_S_COMMON_PROPERTY_SHOW(display_name, string); 63*e6c7b3e1SJorge Lopez static struct kobj_attribute string_display_name = 64*e6c7b3e1SJorge Lopez __ATTR_RO(display_name); 65*e6c7b3e1SJorge Lopez 66*e6c7b3e1SJorge Lopez ATTRIBUTE_PROPERTY_STORE(current_value, string); 67*e6c7b3e1SJorge Lopez static struct kobj_attribute string_current_val = 68*e6c7b3e1SJorge Lopez __ATTR_RW_MODE(current_value, 0644); 69*e6c7b3e1SJorge Lopez 70*e6c7b3e1SJorge Lopez ATTRIBUTE_N_PROPERTY_SHOW(min_length, string); 71*e6c7b3e1SJorge Lopez static struct kobj_attribute string_min_length = 72*e6c7b3e1SJorge Lopez __ATTR_RO(min_length); 73*e6c7b3e1SJorge Lopez 74*e6c7b3e1SJorge Lopez ATTRIBUTE_N_PROPERTY_SHOW(max_length, string); 75*e6c7b3e1SJorge Lopez static struct kobj_attribute string_max_length = 76*e6c7b3e1SJorge Lopez __ATTR_RO(max_length); 77*e6c7b3e1SJorge Lopez 78*e6c7b3e1SJorge Lopez static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr, 79*e6c7b3e1SJorge Lopez char *buf) 80*e6c7b3e1SJorge Lopez { 81*e6c7b3e1SJorge Lopez return sysfs_emit(buf, "string\n"); 82*e6c7b3e1SJorge Lopez } 83*e6c7b3e1SJorge Lopez 84*e6c7b3e1SJorge Lopez static struct kobj_attribute string_type = 85*e6c7b3e1SJorge Lopez __ATTR_RO(type); 86*e6c7b3e1SJorge Lopez 87*e6c7b3e1SJorge Lopez static struct attribute *string_attrs[] = { 88*e6c7b3e1SJorge Lopez &common_display_langcode.attr, 89*e6c7b3e1SJorge Lopez &string_display_name.attr, 90*e6c7b3e1SJorge Lopez &string_current_val.attr, 91*e6c7b3e1SJorge Lopez &string_min_length.attr, 92*e6c7b3e1SJorge Lopez &string_max_length.attr, 93*e6c7b3e1SJorge Lopez &string_type.attr, 94*e6c7b3e1SJorge Lopez NULL 95*e6c7b3e1SJorge Lopez }; 96*e6c7b3e1SJorge Lopez 97*e6c7b3e1SJorge Lopez static const struct attribute_group string_attr_group = { 98*e6c7b3e1SJorge Lopez .attrs = string_attrs, 99*e6c7b3e1SJorge Lopez }; 100*e6c7b3e1SJorge Lopez 101*e6c7b3e1SJorge Lopez int hp_alloc_string_data(void) 102*e6c7b3e1SJorge Lopez { 103*e6c7b3e1SJorge Lopez bioscfg_drv.string_instances_count = hp_get_instance_count(HP_WMI_BIOS_STRING_GUID); 104*e6c7b3e1SJorge Lopez bioscfg_drv.string_data = kcalloc(bioscfg_drv.string_instances_count, 105*e6c7b3e1SJorge Lopez sizeof(*bioscfg_drv.string_data), GFP_KERNEL); 106*e6c7b3e1SJorge Lopez if (!bioscfg_drv.string_data) { 107*e6c7b3e1SJorge Lopez bioscfg_drv.string_instances_count = 0; 108*e6c7b3e1SJorge Lopez return -ENOMEM; 109*e6c7b3e1SJorge Lopez } 110*e6c7b3e1SJorge Lopez return 0; 111*e6c7b3e1SJorge Lopez } 112*e6c7b3e1SJorge Lopez 113*e6c7b3e1SJorge Lopez /* Expected Values types associated with each element */ 114*e6c7b3e1SJorge Lopez static const acpi_object_type expected_string_types[] = { 115*e6c7b3e1SJorge Lopez [NAME] = ACPI_TYPE_STRING, 116*e6c7b3e1SJorge Lopez [VALUE] = ACPI_TYPE_STRING, 117*e6c7b3e1SJorge Lopez [PATH] = ACPI_TYPE_STRING, 118*e6c7b3e1SJorge Lopez [IS_READONLY] = ACPI_TYPE_INTEGER, 119*e6c7b3e1SJorge Lopez [DISPLAY_IN_UI] = ACPI_TYPE_INTEGER, 120*e6c7b3e1SJorge Lopez [REQUIRES_PHYSICAL_PRESENCE] = ACPI_TYPE_INTEGER, 121*e6c7b3e1SJorge Lopez [SEQUENCE] = ACPI_TYPE_INTEGER, 122*e6c7b3e1SJorge Lopez [PREREQUISITES_SIZE] = ACPI_TYPE_INTEGER, 123*e6c7b3e1SJorge Lopez [PREREQUISITES] = ACPI_TYPE_STRING, 124*e6c7b3e1SJorge Lopez [SECURITY_LEVEL] = ACPI_TYPE_INTEGER, 125*e6c7b3e1SJorge Lopez [STR_MIN_LENGTH] = ACPI_TYPE_INTEGER, 126*e6c7b3e1SJorge Lopez [STR_MAX_LENGTH] = ACPI_TYPE_INTEGER, 127*e6c7b3e1SJorge Lopez }; 128*e6c7b3e1SJorge Lopez 129*e6c7b3e1SJorge Lopez static int hp_populate_string_elements_from_package(union acpi_object *string_obj, 130*e6c7b3e1SJorge Lopez int string_obj_count, 131*e6c7b3e1SJorge Lopez int instance_id) 132*e6c7b3e1SJorge Lopez { 133*e6c7b3e1SJorge Lopez char *str_value = NULL; 134*e6c7b3e1SJorge Lopez int value_len; 135*e6c7b3e1SJorge Lopez int ret = 0; 136*e6c7b3e1SJorge Lopez u32 int_value; 137*e6c7b3e1SJorge Lopez int elem; 138*e6c7b3e1SJorge Lopez int reqs; 139*e6c7b3e1SJorge Lopez int eloc; 140*e6c7b3e1SJorge Lopez int size; 141*e6c7b3e1SJorge Lopez struct string_data *string_data = &bioscfg_drv.string_data[instance_id]; 142*e6c7b3e1SJorge Lopez 143*e6c7b3e1SJorge Lopez if (!string_obj) 144*e6c7b3e1SJorge Lopez return -EINVAL; 145*e6c7b3e1SJorge Lopez 146*e6c7b3e1SJorge Lopez for (elem = 1, eloc = 1; elem < string_obj_count; elem++, eloc++) { 147*e6c7b3e1SJorge Lopez /* ONLY look at the first STRING_ELEM_CNT elements */ 148*e6c7b3e1SJorge Lopez if (eloc == STR_ELEM_CNT) 149*e6c7b3e1SJorge Lopez goto exit_string_package; 150*e6c7b3e1SJorge Lopez 151*e6c7b3e1SJorge Lopez switch (string_obj[elem].type) { 152*e6c7b3e1SJorge Lopez case ACPI_TYPE_STRING: 153*e6c7b3e1SJorge Lopez if (elem != PREREQUISITES) { 154*e6c7b3e1SJorge Lopez ret = hp_convert_hexstr_to_str(string_obj[elem].string.pointer, 155*e6c7b3e1SJorge Lopez string_obj[elem].string.length, 156*e6c7b3e1SJorge Lopez &str_value, &value_len); 157*e6c7b3e1SJorge Lopez 158*e6c7b3e1SJorge Lopez if (ret) 159*e6c7b3e1SJorge Lopez continue; 160*e6c7b3e1SJorge Lopez } 161*e6c7b3e1SJorge Lopez break; 162*e6c7b3e1SJorge Lopez case ACPI_TYPE_INTEGER: 163*e6c7b3e1SJorge Lopez int_value = (u32)string_obj[elem].integer.value; 164*e6c7b3e1SJorge Lopez break; 165*e6c7b3e1SJorge Lopez default: 166*e6c7b3e1SJorge Lopez pr_warn("Unsupported object type [%d]\n", string_obj[elem].type); 167*e6c7b3e1SJorge Lopez continue; 168*e6c7b3e1SJorge Lopez } 169*e6c7b3e1SJorge Lopez 170*e6c7b3e1SJorge Lopez /* Check that both expected and read object type match */ 171*e6c7b3e1SJorge Lopez if (expected_string_types[eloc] != string_obj[elem].type) { 172*e6c7b3e1SJorge Lopez pr_err("Error expected type %d for elem %d, but got type %d instead\n", 173*e6c7b3e1SJorge Lopez expected_string_types[eloc], elem, string_obj[elem].type); 174*e6c7b3e1SJorge Lopez return -EIO; 175*e6c7b3e1SJorge Lopez } 176*e6c7b3e1SJorge Lopez 177*e6c7b3e1SJorge Lopez /* Assign appropriate element value to corresponding field*/ 178*e6c7b3e1SJorge Lopez switch (eloc) { 179*e6c7b3e1SJorge Lopez case VALUE: 180*e6c7b3e1SJorge Lopez strscpy(string_data->current_value, 181*e6c7b3e1SJorge Lopez str_value, sizeof(string_data->current_value)); 182*e6c7b3e1SJorge Lopez break; 183*e6c7b3e1SJorge Lopez case PATH: 184*e6c7b3e1SJorge Lopez strscpy(string_data->common.path, str_value, 185*e6c7b3e1SJorge Lopez sizeof(string_data->common.path)); 186*e6c7b3e1SJorge Lopez break; 187*e6c7b3e1SJorge Lopez case IS_READONLY: 188*e6c7b3e1SJorge Lopez string_data->common.is_readonly = int_value; 189*e6c7b3e1SJorge Lopez break; 190*e6c7b3e1SJorge Lopez case DISPLAY_IN_UI: 191*e6c7b3e1SJorge Lopez string_data->common.display_in_ui = int_value; 192*e6c7b3e1SJorge Lopez break; 193*e6c7b3e1SJorge Lopez case REQUIRES_PHYSICAL_PRESENCE: 194*e6c7b3e1SJorge Lopez string_data->common.requires_physical_presence = int_value; 195*e6c7b3e1SJorge Lopez break; 196*e6c7b3e1SJorge Lopez case SEQUENCE: 197*e6c7b3e1SJorge Lopez string_data->common.sequence = int_value; 198*e6c7b3e1SJorge Lopez break; 199*e6c7b3e1SJorge Lopez case PREREQUISITES_SIZE: 200*e6c7b3e1SJorge Lopez string_data->common.prerequisites_size = int_value; 201*e6c7b3e1SJorge Lopez 202*e6c7b3e1SJorge Lopez if (string_data->common.prerequisites_size > MAX_PREREQUISITES_SIZE) 203*e6c7b3e1SJorge Lopez pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n"); 204*e6c7b3e1SJorge Lopez /* 205*e6c7b3e1SJorge Lopez * This HACK is needed to keep the expected 206*e6c7b3e1SJorge Lopez * element list pointing to the right obj[elem].type 207*e6c7b3e1SJorge Lopez * when the size is zero. PREREQUISITES 208*e6c7b3e1SJorge Lopez * object is omitted by BIOS when the size is 209*e6c7b3e1SJorge Lopez * zero. 210*e6c7b3e1SJorge Lopez */ 211*e6c7b3e1SJorge Lopez if (string_data->common.prerequisites_size == 0) 212*e6c7b3e1SJorge Lopez eloc++; 213*e6c7b3e1SJorge Lopez break; 214*e6c7b3e1SJorge Lopez case PREREQUISITES: 215*e6c7b3e1SJorge Lopez size = min_t(u32, string_data->common.prerequisites_size, 216*e6c7b3e1SJorge Lopez MAX_PREREQUISITES_SIZE); 217*e6c7b3e1SJorge Lopez 218*e6c7b3e1SJorge Lopez for (reqs = 0; reqs < size; reqs++) { 219*e6c7b3e1SJorge Lopez if (elem >= string_obj_count) { 220*e6c7b3e1SJorge Lopez pr_err("Error elem-objects package is too small\n"); 221*e6c7b3e1SJorge Lopez return -EINVAL; 222*e6c7b3e1SJorge Lopez } 223*e6c7b3e1SJorge Lopez 224*e6c7b3e1SJorge Lopez ret = hp_convert_hexstr_to_str(string_obj[elem + reqs].string.pointer, 225*e6c7b3e1SJorge Lopez string_obj[elem + reqs].string.length, 226*e6c7b3e1SJorge Lopez &str_value, &value_len); 227*e6c7b3e1SJorge Lopez 228*e6c7b3e1SJorge Lopez if (ret) 229*e6c7b3e1SJorge Lopez continue; 230*e6c7b3e1SJorge Lopez 231*e6c7b3e1SJorge Lopez strscpy(string_data->common.prerequisites[reqs], 232*e6c7b3e1SJorge Lopez str_value, 233*e6c7b3e1SJorge Lopez sizeof(string_data->common.prerequisites[reqs])); 234*e6c7b3e1SJorge Lopez kfree(str_value); 235*e6c7b3e1SJorge Lopez } 236*e6c7b3e1SJorge Lopez break; 237*e6c7b3e1SJorge Lopez 238*e6c7b3e1SJorge Lopez case SECURITY_LEVEL: 239*e6c7b3e1SJorge Lopez string_data->common.security_level = int_value; 240*e6c7b3e1SJorge Lopez break; 241*e6c7b3e1SJorge Lopez case STR_MIN_LENGTH: 242*e6c7b3e1SJorge Lopez string_data->min_length = int_value; 243*e6c7b3e1SJorge Lopez break; 244*e6c7b3e1SJorge Lopez case STR_MAX_LENGTH: 245*e6c7b3e1SJorge Lopez string_data->max_length = int_value; 246*e6c7b3e1SJorge Lopez break; 247*e6c7b3e1SJorge Lopez default: 248*e6c7b3e1SJorge Lopez pr_warn("Invalid element: %d found in String attribute or data may be malformed\n", elem); 249*e6c7b3e1SJorge Lopez break; 250*e6c7b3e1SJorge Lopez } 251*e6c7b3e1SJorge Lopez 252*e6c7b3e1SJorge Lopez kfree(str_value); 253*e6c7b3e1SJorge Lopez } 254*e6c7b3e1SJorge Lopez 255*e6c7b3e1SJorge Lopez exit_string_package: 256*e6c7b3e1SJorge Lopez kfree(str_value); 257*e6c7b3e1SJorge Lopez return 0; 258*e6c7b3e1SJorge Lopez } 259*e6c7b3e1SJorge Lopez 260*e6c7b3e1SJorge Lopez /** 261*e6c7b3e1SJorge Lopez * hp_populate_string_package_data() - 262*e6c7b3e1SJorge Lopez * Populate all properties of an instance under string attribute 263*e6c7b3e1SJorge Lopez * 264*e6c7b3e1SJorge Lopez * @string_obj: ACPI object with string data 265*e6c7b3e1SJorge Lopez * @instance_id: The instance to enumerate 266*e6c7b3e1SJorge Lopez * @attr_name_kobj: The parent kernel object 267*e6c7b3e1SJorge Lopez */ 268*e6c7b3e1SJorge Lopez int hp_populate_string_package_data(union acpi_object *string_obj, 269*e6c7b3e1SJorge Lopez int instance_id, 270*e6c7b3e1SJorge Lopez struct kobject *attr_name_kobj) 271*e6c7b3e1SJorge Lopez { 272*e6c7b3e1SJorge Lopez struct string_data *string_data = &bioscfg_drv.string_data[instance_id]; 273*e6c7b3e1SJorge Lopez 274*e6c7b3e1SJorge Lopez string_data->attr_name_kobj = attr_name_kobj; 275*e6c7b3e1SJorge Lopez 276*e6c7b3e1SJorge Lopez hp_populate_string_elements_from_package(string_obj, 277*e6c7b3e1SJorge Lopez string_obj->package.count, 278*e6c7b3e1SJorge Lopez instance_id); 279*e6c7b3e1SJorge Lopez 280*e6c7b3e1SJorge Lopez hp_update_attribute_permissions(string_data->common.is_readonly, 281*e6c7b3e1SJorge Lopez &string_current_val); 282*e6c7b3e1SJorge Lopez hp_friendly_user_name_update(string_data->common.path, 283*e6c7b3e1SJorge Lopez attr_name_kobj->name, 284*e6c7b3e1SJorge Lopez string_data->common.display_name, 285*e6c7b3e1SJorge Lopez sizeof(string_data->common.display_name)); 286*e6c7b3e1SJorge Lopez return sysfs_create_group(attr_name_kobj, &string_attr_group); 287*e6c7b3e1SJorge Lopez } 288*e6c7b3e1SJorge Lopez 289*e6c7b3e1SJorge Lopez static int hp_populate_string_elements_from_buffer(u8 *buffer_ptr, u32 *buffer_size, 290*e6c7b3e1SJorge Lopez int instance_id) 291*e6c7b3e1SJorge Lopez { 292*e6c7b3e1SJorge Lopez int ret = 0; 293*e6c7b3e1SJorge Lopez struct string_data *string_data = &bioscfg_drv.string_data[instance_id]; 294*e6c7b3e1SJorge Lopez 295*e6c7b3e1SJorge Lopez /* 296*e6c7b3e1SJorge Lopez * Only data relevant to this driver and its functionality is 297*e6c7b3e1SJorge Lopez * read. BIOS defines the order in which each * element is 298*e6c7b3e1SJorge Lopez * read. Element 0 data is not relevant to this 299*e6c7b3e1SJorge Lopez * driver hence it is ignored. For clarity, all element names 300*e6c7b3e1SJorge Lopez * (DISPLAY_IN_UI) which defines the order in which is read 301*e6c7b3e1SJorge Lopez * and the name matches the variable where the data is stored. 302*e6c7b3e1SJorge Lopez * 303*e6c7b3e1SJorge Lopez * In earlier implementation, reported errors were ignored 304*e6c7b3e1SJorge Lopez * causing the data to remain uninitialized. It is not 305*e6c7b3e1SJorge Lopez * possible to determine if data read from BIOS is valid or 306*e6c7b3e1SJorge Lopez * not. It is for this reason functions may return a error 307*e6c7b3e1SJorge Lopez * without validating the data itself. 308*e6c7b3e1SJorge Lopez */ 309*e6c7b3e1SJorge Lopez 310*e6c7b3e1SJorge Lopez // VALUE: 311*e6c7b3e1SJorge Lopez ret = hp_get_string_from_buffer(&buffer_ptr, buffer_size, string_data->current_value, 312*e6c7b3e1SJorge Lopez sizeof(string_data->current_value)); 313*e6c7b3e1SJorge Lopez if (ret < 0) 314*e6c7b3e1SJorge Lopez goto buffer_exit; 315*e6c7b3e1SJorge Lopez 316*e6c7b3e1SJorge Lopez // COMMON: 317*e6c7b3e1SJorge Lopez ret = hp_get_common_data_from_buffer(&buffer_ptr, buffer_size, &string_data->common); 318*e6c7b3e1SJorge Lopez if (ret < 0) 319*e6c7b3e1SJorge Lopez goto buffer_exit; 320*e6c7b3e1SJorge Lopez 321*e6c7b3e1SJorge Lopez // STR_MIN_LENGTH: 322*e6c7b3e1SJorge Lopez ret = hp_get_integer_from_buffer(&buffer_ptr, buffer_size, 323*e6c7b3e1SJorge Lopez &string_data->min_length); 324*e6c7b3e1SJorge Lopez if (ret < 0) 325*e6c7b3e1SJorge Lopez goto buffer_exit; 326*e6c7b3e1SJorge Lopez 327*e6c7b3e1SJorge Lopez // STR_MAX_LENGTH: 328*e6c7b3e1SJorge Lopez ret = hp_get_integer_from_buffer(&buffer_ptr, buffer_size, 329*e6c7b3e1SJorge Lopez &string_data->max_length); 330*e6c7b3e1SJorge Lopez 331*e6c7b3e1SJorge Lopez buffer_exit: 332*e6c7b3e1SJorge Lopez 333*e6c7b3e1SJorge Lopez return ret; 334*e6c7b3e1SJorge Lopez } 335*e6c7b3e1SJorge Lopez 336*e6c7b3e1SJorge Lopez /** 337*e6c7b3e1SJorge Lopez * hp_populate_string_buffer_data() - 338*e6c7b3e1SJorge Lopez * Populate all properties of an instance under string attribute 339*e6c7b3e1SJorge Lopez * 340*e6c7b3e1SJorge Lopez * @buffer_ptr: Buffer pointer 341*e6c7b3e1SJorge Lopez * @buffer_size: Buffer size 342*e6c7b3e1SJorge Lopez * @instance_id: The instance to enumerate 343*e6c7b3e1SJorge Lopez * @attr_name_kobj: The parent kernel object 344*e6c7b3e1SJorge Lopez */ 345*e6c7b3e1SJorge Lopez int hp_populate_string_buffer_data(u8 *buffer_ptr, u32 *buffer_size, 346*e6c7b3e1SJorge Lopez int instance_id, 347*e6c7b3e1SJorge Lopez struct kobject *attr_name_kobj) 348*e6c7b3e1SJorge Lopez { 349*e6c7b3e1SJorge Lopez struct string_data *string_data = &bioscfg_drv.string_data[instance_id]; 350*e6c7b3e1SJorge Lopez int ret = 0; 351*e6c7b3e1SJorge Lopez 352*e6c7b3e1SJorge Lopez string_data->attr_name_kobj = attr_name_kobj; 353*e6c7b3e1SJorge Lopez 354*e6c7b3e1SJorge Lopez ret = hp_populate_string_elements_from_buffer(buffer_ptr, buffer_size, 355*e6c7b3e1SJorge Lopez instance_id); 356*e6c7b3e1SJorge Lopez if (ret < 0) 357*e6c7b3e1SJorge Lopez return ret; 358*e6c7b3e1SJorge Lopez 359*e6c7b3e1SJorge Lopez hp_update_attribute_permissions(string_data->common.is_readonly, 360*e6c7b3e1SJorge Lopez &string_current_val); 361*e6c7b3e1SJorge Lopez hp_friendly_user_name_update(string_data->common.path, 362*e6c7b3e1SJorge Lopez attr_name_kobj->name, 363*e6c7b3e1SJorge Lopez string_data->common.display_name, 364*e6c7b3e1SJorge Lopez sizeof(string_data->common.display_name)); 365*e6c7b3e1SJorge Lopez 366*e6c7b3e1SJorge Lopez return sysfs_create_group(attr_name_kobj, &string_attr_group); 367*e6c7b3e1SJorge Lopez } 368*e6c7b3e1SJorge Lopez 369*e6c7b3e1SJorge Lopez /** 370*e6c7b3e1SJorge Lopez * hp_exit_string_attributes() - Clear all attribute data 371*e6c7b3e1SJorge Lopez * 372*e6c7b3e1SJorge Lopez * Clears all data allocated for this group of attributes 373*e6c7b3e1SJorge Lopez */ 374*e6c7b3e1SJorge Lopez void hp_exit_string_attributes(void) 375*e6c7b3e1SJorge Lopez { 376*e6c7b3e1SJorge Lopez int instance_id; 377*e6c7b3e1SJorge Lopez 378*e6c7b3e1SJorge Lopez for (instance_id = 0; instance_id < bioscfg_drv.string_instances_count; 379*e6c7b3e1SJorge Lopez instance_id++) { 380*e6c7b3e1SJorge Lopez struct kobject *attr_name_kobj = 381*e6c7b3e1SJorge Lopez bioscfg_drv.string_data[instance_id].attr_name_kobj; 382*e6c7b3e1SJorge Lopez 383*e6c7b3e1SJorge Lopez if (attr_name_kobj) 384*e6c7b3e1SJorge Lopez sysfs_remove_group(attr_name_kobj, &string_attr_group); 385*e6c7b3e1SJorge Lopez } 386*e6c7b3e1SJorge Lopez bioscfg_drv.string_instances_count = 0; 387*e6c7b3e1SJorge Lopez 388*e6c7b3e1SJorge Lopez kfree(bioscfg_drv.string_data); 389*e6c7b3e1SJorge Lopez bioscfg_drv.string_data = NULL; 390*e6c7b3e1SJorge Lopez } 391