FILE
bioscfg.c
File preview with syntax highlighting.
linux-6.19.14/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Common methods for use with hp-bioscfg driver 4 * 5 * Copyright (c) 2022 HP Development Company, L.P. 6 */ 7 8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 10#include <linux/fs.h> 11#include <linux/module.h> 12#include <linux/kernel.h> 13#include <linux/printk.h> 14#include <linux/string.h> 15#include <linux/wmi.h> 16#include "bioscfg.h" 17#include "../../firmware_attributes_class.h" 18#include <linux/nls.h> 19#include <linux/errno.h> 20 21MODULE_AUTHOR("Jorge Lopez <jorge.lopez2@hp.com>"); 22MODULE_DESCRIPTION("HP BIOS Configuration Driver"); 23MODULE_LICENSE("GPL"); 24 25struct bioscfg_priv bioscfg_drv = { 26 .mutex = __MUTEX_INITIALIZER(bioscfg_drv.mutex), 27}; 28 29ssize_t display_name_language_code_show(struct kobject *kobj, 30 struct kobj_attribute *attr, 31 char *buf) 32{ 33 return sysfs_emit(buf, "%s\n", LANG_CODE_STR); 34} 35 36struct kobj_attribute common_display_langcode = 37 __ATTR_RO(display_name_language_code); 38 39int hp_get_integer_from_buffer(u8 **buffer, u32 *buffer_size, u32 *integer) 40{ 41 int *ptr = PTR_ALIGN((int *)*buffer, sizeof(int)); 42 43 /* Ensure there is enough space remaining to read the integer */ 44 if (*buffer_size < sizeof(int)) 45 return -EINVAL; 46 47 *integer = *(ptr++); 48 *buffer = (u8 *)ptr; 49 *buffer_size -= sizeof(int); 50 51 return 0; 52} 53 54int hp_get_string_from_buffer(u8 **buffer, u32 *buffer_size, char *dst, u32 dst_size) 55{ 56 u16 *src = (u16 *)*buffer; 57 u16 src_size; 58 59 u16 size; 60 int i; 61 int conv_dst_size; 62 63 if (*buffer_size < sizeof(u16)) 64 return -EINVAL; 65 66 src_size = *(src++); 67 /* size value in u16 chars */ 68 size = src_size / sizeof(u16); 69 70 /* Ensure there is enough space remaining to read and convert 71 * the string 72 */ 73 if (*buffer_size < src_size) 74 return -EINVAL; 75 76 for (i = 0; i < size; i++) 77 if (src[i] == '\\' || 78 src[i] == '\r' || 79 src[i] == '\n' || 80 src[i] == '\t') 81 size++; 82 83 /* 84 * Conversion is limited to destination string max number of 85 * bytes. 86 */ 87 conv_dst_size = size; 88 if (size > dst_size) 89 conv_dst_size = dst_size - 1; 90 91 /* 92 * convert from UTF-16 unicode to ASCII 93 */ 94 utf16s_to_utf8s(src, src_size, UTF16_HOST_ENDIAN, dst, conv_dst_size); 95 dst[conv_dst_size] = 0; 96 97 for (i = 0; i < conv_dst_size; i++) { 98 if (*src == '\\' || 99 *src == '\r' || 100 *src == '\n' || 101 *src == '\t') { 102 dst[i++] = '\\'; 103 if (i == conv_dst_size) 104 break; 105 } 106 107 if (*src == '\r') 108 dst[i] = 'r'; 109 else if (*src == '\n') 110 dst[i] = 'n'; 111 else if (*src == '\t') 112 dst[i] = 't'; 113 else if (*src == '"') 114 dst[i] = '\''; 115 else 116 dst[i] = *src; 117 src++; 118 } 119 120 *buffer = (u8 *)src; 121 *buffer_size -= size * sizeof(u16); 122 123 return size; 124} 125 126int hp_get_common_data_from_buffer(u8 **buffer_ptr, u32 *buffer_size, 127 struct common_data *common_data) 128{ 129 int ret = 0; 130 int reqs; 131 132 // PATH: 133 ret = hp_get_string_from_buffer(buffer_ptr, buffer_size, common_data->path, 134 sizeof(common_data->path)); 135 if (ret < 0) 136 goto common_exit; 137 138 // IS_READONLY: 139 ret = hp_get_integer_from_buffer(buffer_ptr, buffer_size, 140 &common_data->is_readonly); 141 if (ret < 0) 142 goto common_exit; 143 144 //DISPLAY_IN_UI: 145 ret = hp_get_integer_from_buffer(buffer_ptr, buffer_size, 146 &common_data->display_in_ui); 147 if (ret < 0) 148 goto common_exit; 149 150 // REQUIRES_PHYSICAL_PRESENCE: 151 ret = hp_get_integer_from_buffer(buffer_ptr, buffer_size, 152 &common_data->requires_physical_presence); 153 if (ret < 0) 154 goto common_exit; 155 156 // SEQUENCE: 157 ret = hp_get_integer_from_buffer(buffer_ptr, buffer_size, 158 &common_data->sequence); 159 if (ret < 0) 160 goto common_exit; 161 162 // PREREQUISITES_SIZE: 163 ret = hp_get_integer_from_buffer(buffer_ptr, buffer_size, 164 &common_data->prerequisites_size); 165 if (ret < 0) 166 goto common_exit; 167 168 if (common_data->prerequisites_size > MAX_PREREQUISITES_SIZE) { 169 /* Report a message and limit prerequisite size to maximum value */ 170 pr_warn("Prerequisites size value exceeded the maximum number of elements supported or data may be malformed\n"); 171 common_data->prerequisites_size = MAX_PREREQUISITES_SIZE; 172 } 173 174 // PREREQUISITES: 175 for (reqs = 0; reqs < common_data->prerequisites_size; reqs++) { 176 ret = hp_get_string_from_buffer(buffer_ptr, buffer_size, 177 common_data->prerequisites[reqs], 178 sizeof(common_data->prerequisites[reqs])); 179 if (ret < 0) 180 break; 181 } 182 183 // SECURITY_LEVEL: 184 ret = hp_get_integer_from_buffer(buffer_ptr, buffer_size, 185 &common_data->security_level); 186 187common_exit: 188 return ret; 189} 190 191int hp_enforce_single_line_input(char *buf, size_t count) 192{ 193 char *p; 194 195 p = memchr(buf, '\n', count); 196 197 if (p == buf + count - 1) 198 *p = '\0'; /* strip trailing newline */ 199 else if (p) 200 return -EINVAL; /* enforce single line input */ 201 202 return 0; 203} 204 205/* Set pending reboot value and generate KOBJ_NAME event */ 206void hp_set_reboot_and_signal_event(void) 207{ 208 bioscfg_drv.pending_reboot = true; 209 kobject_uevent(&bioscfg_drv.class_dev->kobj, KOBJ_CHANGE); 210} 211 212/** 213 * hp_calculate_string_buffer() - determines size of string buffer for 214 * use with BIOS communication 215 * 216 * @str: the string to calculate based upon 217 */ 218size_t hp_calculate_string_buffer(const char *str) 219{ 220 size_t length = strlen(str); 221 222 /* BIOS expects 4 bytes when an empty string is found */ 223 if (length == 0) 224 return 4; 225 226 /* u16 length field + one UTF16 char for each input char */ 227 return sizeof(u16) + strlen(str) * sizeof(u16); 228} 229 230int hp_wmi_error_and_message(int error_code) 231{ 232 char *error_msg = NULL; 233 int ret; 234 235 switch (error_code) { 236 case SUCCESS: 237 error_msg = "Success"; 238 ret = 0; 239 break; 240 case CMD_FAILED: 241 error_msg = "Command failed"; 242 ret = -EINVAL; 243 break; 244 case INVALID_SIGN: 245 error_msg = "Invalid signature"; 246 ret = -EINVAL; 247 break; 248 case INVALID_CMD_VALUE: 249 error_msg = "Invalid command value/Feature not supported"; 250 ret = -EOPNOTSUPP; 251 break; 252 case INVALID_CMD_TYPE: 253 error_msg = "Invalid command type"; 254 ret = -EINVAL; 255 break; 256 case INVALID_DATA_SIZE: 257 error_msg = "Invalid data size"; 258 ret = -EINVAL; 259 break; 260 case INVALID_CMD_PARAM: 261 error_msg = "Invalid command parameter"; 262 ret = -EINVAL; 263 break; 264 case ENCRYP_CMD_REQUIRED: 265 error_msg = "Secure/encrypted command required"; 266 ret = -EACCES; 267 break; 268 case NO_SECURE_SESSION: 269 error_msg = "No secure session established"; 270 ret = -EACCES; 271 break; 272 case SECURE_SESSION_FOUND: 273 error_msg = "Secure session already established"; 274 ret = -EACCES; 275 break; 276 case SECURE_SESSION_FAILED: 277 error_msg = "Secure session failed"; 278 ret = -EIO; 279 break; 280 case AUTH_FAILED: 281 error_msg = "Other permission/Authentication failed"; 282 ret = -EACCES; 283 break; 284 case INVALID_BIOS_AUTH: 285 error_msg = "Invalid BIOS administrator password"; 286 ret = -EINVAL; 287 break; 288 case NONCE_DID_NOT_MATCH: 289 error_msg = "Nonce did not match"; 290 ret = -EINVAL; 291 break; 292 case GENERIC_ERROR: 293 error_msg = "Generic/Other error"; 294 ret = -EIO; 295 break; 296 case BIOS_ADMIN_POLICY_NOT_MET: 297 error_msg = "BIOS Admin password does not meet password policy requirements"; 298 ret = -EINVAL; 299 break; 300 case BIOS_ADMIN_NOT_SET: 301 error_msg = "BIOS Setup password is not set"; 302 ret = -EPERM; 303 break; 304 case P21_NO_PROVISIONED: 305 error_msg = "P21 is not provisioned"; 306 ret = -EPERM; 307 break; 308 case P21_PROVISION_IN_PROGRESS: 309 error_msg = "P21 is already provisioned or provisioning is in progress and a signing key has already been sent"; 310 ret = -EINPROGRESS; 311 break; 312 case P21_IN_USE: 313 error_msg = "P21 in use (cannot deprovision)"; 314 ret = -EPERM; 315 break; 316 case HEP_NOT_ACTIVE: 317 error_msg = "HEP not activated"; 318 ret = -EPERM; 319 break; 320 case HEP_ALREADY_SET: 321 error_msg = "HEP Transport already set"; 322 ret = -EINVAL; 323 break; 324 case HEP_CHECK_STATE: 325 error_msg = "Check the current HEP state"; 326 ret = -EINVAL; 327 break; 328 default: 329 error_msg = "Generic/Other error"; 330 ret = -EIO; 331 break; 332 } 333 334 if (error_code) 335 pr_warn_ratelimited("Returned error 0x%x, \"%s\"\n", error_code, error_msg); 336 337 return ret; 338} 339 340static ssize_t pending_reboot_show(struct kobject *kobj, 341 struct kobj_attribute *attr, 342 char *buf) 343{ 344 return sysfs_emit(buf, "%d\n", bioscfg_drv.pending_reboot); 345} 346 347static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot); 348 349/* 350 * create_attributes_level_sysfs_files() - Creates pending_reboot attributes 351 */ 352static int create_attributes_level_sysfs_files(void) 353{ 354 return sysfs_create_file(&bioscfg_drv.main_dir_kset->kobj, 355 &pending_reboot.attr); 356} 357 358static void attr_name_release(struct kobject *kobj) 359{ 360 kfree(kobj); 361} 362 363static const struct kobj_type attr_name_ktype = { 364 .release = attr_name_release, 365 .sysfs_ops = &kobj_sysfs_ops, 366}; 367 368/** 369 * hp_get_wmiobj_pointer() - Get Content of WMI block for particular instance 370 * 371 * @instance_id: WMI instance ID 372 * @guid_string: WMI GUID (in str form) 373 * 374 * Fetches the content for WMI block (instance_id) under GUID (guid_string) 375 * Caller must kfree the return 376 */ 377union acpi_object *hp_get_wmiobj_pointer(int instance_id, const char *guid_string) 378{ 379 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; 380 acpi_status status; 381 382 status = wmi_query_block(guid_string, instance_id, &out); 383 return ACPI_SUCCESS(status) ? (union acpi_object *)out.pointer : NULL; 384} 385 386/** 387 * hp_get_instance_count() - Compute total number of instances under guid_string 388 * 389 * @guid_string: WMI GUID (in string form) 390 */ 391int hp_get_instance_count(const char *guid_string) 392{ 393 int ret; 394 395 ret = wmi_instance_count(guid_string); 396 if (ret < 0) 397 return 0; 398 399 return ret; 400} 401 402/** 403 * hp_alloc_attributes_data() - Allocate attributes data for a particular type 404 * 405 * @attr_type: Attribute type to allocate 406 */ 407static int hp_alloc_attributes_data(int attr_type) 408{ 409 switch (attr_type) { 410 case HPWMI_STRING_TYPE: 411 return hp_alloc_string_data(); 412 413 case HPWMI_INTEGER_TYPE: 414 return hp_alloc_integer_data(); 415 416 case HPWMI_ENUMERATION_TYPE: 417 return hp_alloc_enumeration_data(); 418 419 case HPWMI_ORDERED_LIST_TYPE: 420 return hp_alloc_ordered_list_data(); 421 422 case HPWMI_PASSWORD_TYPE: 423 return hp_alloc_password_data(); 424 425 default: 426 return 0; 427 } 428} 429 430int hp_convert_hexstr_to_str(const char *input, u32 input_len, char **str, int *len) 431{ 432 int ret = 0; 433 int new_len = 0; 434 char tmp[] = "0x00"; 435 char *new_str = NULL; 436 long ch; 437 int i; 438 439 if (input_len <= 0 || !input || !str || !len) 440 return -EINVAL; 441 442 *len = 0; 443 *str = NULL; 444 445 new_str = kmalloc(input_len, GFP_KERNEL); 446 if (!new_str) 447 return -ENOMEM; 448 449 for (i = 0; i < input_len; i += 5) { 450 strscpy(tmp, input + i); 451 if (kstrtol(tmp, 16, &ch) == 0) { 452 // escape char 453 if (ch == '\\' || 454 ch == '\r' || 455 ch == '\n' || ch == '\t') { 456 if (ch == '\r') 457 ch = 'r'; 458 else if (ch == '\n') 459 ch = 'n'; 460 else if (ch == '\t') 461 ch = 't'; 462 new_str[new_len++] = '\\'; 463 } 464 new_str[new_len++] = ch; 465 if (ch == '\0') 466 break; 467 } 468 } 469 470 if (new_len) { 471 new_str[new_len] = '\0'; 472 *str = krealloc(new_str, (new_len + 1) * sizeof(char), 473 GFP_KERNEL); 474 if (*str) 475 *len = new_len; 476 else 477 ret = -ENOMEM; 478 } else { 479 ret = -EFAULT; 480 } 481 482 if (ret) 483 kfree(new_str); 484 return ret; 485} 486 487/* map output size to the corresponding WMI method id */ 488int hp_encode_outsize_for_pvsz(int outsize) 489{ 490 if (outsize > 4096) 491 return -EINVAL; 492 if (outsize > 1024) 493 return 5; 494 if (outsize > 128) 495 return 4; 496 if (outsize > 4) 497 return 3; 498 if (outsize > 0) 499 return 2; 500 return 1; 501} 502 503/* 504 * Update friendly display name for several attributes associated to 505 * 'Schedule Power-On' 506 */ 507void hp_friendly_user_name_update(char *path, const char *attr_name, 508 char *attr_display, int attr_size) 509{ 510 if (strstr(path, SCHEDULE_POWER_ON)) 511 snprintf(attr_display, attr_size, "%s - %s", SCHEDULE_POWER_ON, attr_name); 512 else 513 strscpy(attr_display, attr_name, attr_size); 514} 515 516/** 517 * hp_update_attribute_permissions() - Update attributes permissions when 518 * isReadOnly value is 1 519 * 520 * @is_readonly: bool value to indicate if it a readonly attribute. 521 * @current_val: kobj_attribute corresponding to attribute. 522 * 523 */ 524void hp_update_attribute_permissions(bool is_readonly, struct kobj_attribute *current_val) 525{ 526 current_val->attr.mode = is_readonly ? 0444 : 0644; 527} 528 529/** 530 * destroy_attribute_objs() - Free a kset of kobjects 531 * @kset: The kset to destroy 532 * 533 * Fress kobjects created for each attribute_name under attribute type kset 534 */ 535static void destroy_attribute_objs(struct kset *kset) 536{ 537 struct kobject *pos, *next; 538 539 list_for_each_entry_safe(pos, next, &kset->list, entry) 540 kobject_put(pos); 541} 542 543/** 544 * release_attributes_data() - Clean-up all sysfs directories and files created 545 */ 546static void release_attributes_data(void) 547{ 548 mutex_lock(&bioscfg_drv.mutex); 549 550 hp_exit_string_attributes(); 551 hp_exit_integer_attributes(); 552 hp_exit_enumeration_attributes(); 553 hp_exit_ordered_list_attributes(); 554 hp_exit_password_attributes(); 555 hp_exit_sure_start_attributes(); 556 hp_exit_secure_platform_attributes(); 557 558 if (bioscfg_drv.authentication_dir_kset) { 559 destroy_attribute_objs(bioscfg_drv.authentication_dir_kset); 560 kset_unregister(bioscfg_drv.authentication_dir_kset); 561 bioscfg_drv.authentication_dir_kset = NULL; 562 } 563 if (bioscfg_drv.main_dir_kset) { 564 sysfs_remove_file(&bioscfg_drv.main_dir_kset->kobj, &pending_reboot.attr); 565 destroy_attribute_objs(bioscfg_drv.main_dir_kset); 566 kset_unregister(bioscfg_drv.main_dir_kset); 567 bioscfg_drv.main_dir_kset = NULL; 568 } 569 mutex_unlock(&bioscfg_drv.mutex); 570} 571 572/** 573 * hp_add_other_attributes() - Initialize HP custom attributes not 574 * reported by BIOS and required to support Secure Platform and Sure 575 * Start. 576 * 577 * @attr_type: Custom HP attribute not reported by BIOS 578 * 579 * Initialize all 2 types of attributes: Platform and Sure Start 580 * object. Populates each attribute types respective properties 581 * under sysfs files. 582 * 583 * Returns zero(0) if successful. Otherwise, a negative value. 584 */ 585static int hp_add_other_attributes(int attr_type) 586{ 587 struct kobject *attr_name_kobj; 588 int ret; 589 char *attr_name; 590 591 attr_name_kobj = kzalloc(sizeof(*attr_name_kobj), GFP_KERNEL); 592 if (!attr_name_kobj) 593 return -ENOMEM; 594 595 mutex_lock(&bioscfg_drv.mutex); 596 597 /* Check if attribute type is supported */ 598 switch (attr_type) { 599 case HPWMI_SECURE_PLATFORM_TYPE: 600 attr_name_kobj->kset = bioscfg_drv.authentication_dir_kset; 601 attr_name = SPM_STR; 602 break; 603 604 case HPWMI_SURE_START_TYPE: 605 attr_name_kobj->kset = bioscfg_drv.main_dir_kset; 606 attr_name = SURE_START_STR; 607 break; 608 609 default: 610 pr_err("Error: Unknown attr_type: %d\n", attr_type); 611 ret = -EINVAL; 612 kfree(attr_name_kobj); 613 goto unlock_drv_mutex; 614 } 615 616 ret = kobject_init_and_add(attr_name_kobj, &attr_name_ktype, 617 NULL, "%s", attr_name); 618 if (ret) { 619 pr_err("Error encountered [%d]\n", ret); 620 goto err_other_attr_init; 621 } 622 623 /* Populate attribute data */ 624 switch (attr_type) { 625 case HPWMI_SECURE_PLATFORM_TYPE: 626 ret = hp_populate_secure_platform_data(attr_name_kobj); 627 break; 628 629 case HPWMI_SURE_START_TYPE: 630 ret = hp_populate_sure_start_data(attr_name_kobj); 631 break; 632 633 default: 634 ret = -EINVAL; 635 } 636 637 if (ret) 638 goto err_other_attr_init; 639 640 mutex_unlock(&bioscfg_drv.mutex); 641 return 0; 642 643err_other_attr_init: 644 kobject_put(attr_name_kobj); 645unlock_drv_mutex: 646 mutex_unlock(&bioscfg_drv.mutex); 647 return ret; 648} 649 650static int hp_init_bios_package_attribute(enum hp_wmi_data_type attr_type, 651 union acpi_object *obj, 652 const char *guid, int min_elements, 653 int instance_id) 654{ 655 struct kobject *attr_name_kobj, *duplicate; 656 union acpi_object *elements; 657 struct kset *temp_kset; 658 659 char *str_value = NULL; 660 int str_len; 661 int ret = 0; 662 663 /* Take action appropriate to each ACPI TYPE */ 664 if (obj->package.count < min_elements) { 665 pr_err("ACPI-package does not have enough elements: %d < %d\n", 666 obj->package.count, min_elements); 667 goto pack_attr_exit; 668 } 669 670 elements = obj->package.elements; 671 672 /* sanity checking */ 673 if (elements[NAME].type != ACPI_TYPE_STRING) { 674 pr_debug("incorrect element type\n"); 675 goto pack_attr_exit; 676 } 677 if (strlen(elements[NAME].string.pointer) == 0) { 678 pr_debug("empty attribute found\n"); 679 goto pack_attr_exit; 680 } 681 682 if (attr_type == HPWMI_PASSWORD_TYPE) 683 temp_kset = bioscfg_drv.authentication_dir_kset; 684 else 685 temp_kset = bioscfg_drv.main_dir_kset; 686 687 /* convert attribute name to string */ 688 ret = hp_convert_hexstr_to_str(elements[NAME].string.pointer, 689 elements[NAME].string.length, 690 &str_value, &str_len); 691 692 if (ret) { 693 pr_debug("Failed to populate integer package data. Error [0%0x]\n", 694 ret); 695 kfree(str_value); 696 return ret; 697 } 698 699 if (!str_value || !str_value[0]) { 700 pr_debug("Ignoring attribute with empty name\n"); 701 goto pack_attr_exit; 702 } 703 704 /* All duplicate attributes found are ignored */ 705 duplicate = kset_find_obj(temp_kset, str_value); 706 if (duplicate) { 707 pr_debug("Duplicate attribute name found - %s\n", str_value); 708 /* kset_find_obj() returns a reference */ 709 kobject_put(duplicate); 710 goto pack_attr_exit; 711 } 712 713 /* build attribute */ 714 attr_name_kobj = kzalloc(sizeof(*attr_name_kobj), GFP_KERNEL); 715 if (!attr_name_kobj) { 716 ret = -ENOMEM; 717 goto pack_attr_exit; 718 } 719 720 attr_name_kobj->kset = temp_kset; 721 722 ret = kobject_init_and_add(attr_name_kobj, &attr_name_ktype, 723 NULL, "%s", str_value); 724 725 if (ret) { 726 kobject_put(attr_name_kobj); 727 goto pack_attr_exit; 728 } 729 730 /* enumerate all of these attributes */ 731 switch (attr_type) { 732 case HPWMI_STRING_TYPE: 733 ret = hp_populate_string_package_data(elements, 734 instance_id, 735 attr_name_kobj); 736 break; 737 case HPWMI_INTEGER_TYPE: 738 ret = hp_populate_integer_package_data(elements, 739 instance_id, 740 attr_name_kobj); 741 break; 742 case HPWMI_ENUMERATION_TYPE: 743 ret = hp_populate_enumeration_package_data(elements, 744 instance_id, 745 attr_name_kobj); 746 break; 747 case HPWMI_ORDERED_LIST_TYPE: 748 ret = hp_populate_ordered_list_package_data(elements, 749 instance_id, 750 attr_name_kobj); 751 break; 752 case HPWMI_PASSWORD_TYPE: 753 ret = hp_populate_password_package_data(elements, 754 instance_id, 755 attr_name_kobj); 756 break; 757 default: 758 pr_debug("Unknown attribute type found: 0x%x\n", attr_type); 759 break; 760 } 761 762pack_attr_exit: 763 kfree(str_value); 764 return ret; 765} 766 767static int hp_init_bios_buffer_attribute(enum hp_wmi_data_type attr_type, 768 union acpi_object *obj, 769 const char *guid, int min_elements, 770 int instance_id) 771{ 772 struct kobject *attr_name_kobj, *duplicate; 773 struct kset *temp_kset; 774 char str[MAX_BUFF_SIZE]; 775 776 char *temp_str = NULL; 777 char *str_value = NULL; 778 u8 *buffer_ptr = NULL; 779 int buffer_size; 780 int ret = 0; 781 782 buffer_size = obj->buffer.length; 783 buffer_ptr = obj->buffer.pointer; 784 785 ret = hp_get_string_from_buffer(&buffer_ptr, 786 &buffer_size, str, MAX_BUFF_SIZE); 787 788 if (ret < 0) 789 goto buff_attr_exit; 790 791 if (strlen(str) == 0) { 792 pr_debug("Ignoring attribute with empty name\n"); 793 ret = 0; 794 goto buff_attr_exit; 795 } 796 797 if (attr_type == HPWMI_PASSWORD_TYPE || 798 attr_type == HPWMI_SECURE_PLATFORM_TYPE) 799 temp_kset = bioscfg_drv.authentication_dir_kset; 800 else 801 temp_kset = bioscfg_drv.main_dir_kset; 802 803 /* All duplicate attributes found are ignored */ 804 duplicate = kset_find_obj(temp_kset, str); 805 if (duplicate) { 806 pr_debug("Duplicate attribute name found - %s\n", str); 807 /* kset_find_obj() returns a reference */ 808 kobject_put(duplicate); 809 goto buff_attr_exit; 810 } 811 812 /* build attribute */ 813 attr_name_kobj = kzalloc(sizeof(*attr_name_kobj), GFP_KERNEL); 814 if (!attr_name_kobj) { 815 ret = -ENOMEM; 816 goto buff_attr_exit; 817 } 818 819 attr_name_kobj->kset = temp_kset; 820 821 temp_str = str; 822 if (attr_type == HPWMI_SECURE_PLATFORM_TYPE) 823 temp_str = "SPM"; 824 825 ret = kobject_init_and_add(attr_name_kobj, 826 &attr_name_ktype, NULL, "%s", temp_str); 827 if (ret) { 828 kobject_put(attr_name_kobj); 829 goto buff_attr_exit; 830 } 831 832 /* enumerate all of these attributes */ 833 switch (attr_type) { 834 case HPWMI_STRING_TYPE: 835 ret = hp_populate_string_buffer_data(buffer_ptr, 836 &buffer_size, 837 instance_id, 838 attr_name_kobj); 839 break; 840 case HPWMI_INTEGER_TYPE: 841 ret = hp_populate_integer_buffer_data(buffer_ptr, 842 &buffer_size, 843 instance_id, 844 attr_name_kobj); 845 break; 846 case HPWMI_ENUMERATION_TYPE: 847 ret = hp_populate_enumeration_buffer_data(buffer_ptr, 848 &buffer_size, 849 instance_id, 850 attr_name_kobj); 851 break; 852 case HPWMI_ORDERED_LIST_TYPE: 853 ret = hp_populate_ordered_list_buffer_data(buffer_ptr, 854 &buffer_size, 855 instance_id, 856 attr_name_kobj); 857 break; 858 case HPWMI_PASSWORD_TYPE: 859 ret = hp_populate_password_buffer_data(buffer_ptr, 860 &buffer_size, 861 instance_id, 862 attr_name_kobj); 863 break; 864 default: 865 pr_debug("Unknown attribute type found: 0x%x\n", attr_type); 866 break; 867 } 868 869buff_attr_exit: 870 kfree(str_value); 871 return ret; 872} 873 874/** 875 * hp_init_bios_attributes() - Initialize all attributes for a type 876 * @attr_type: The attribute type to initialize 877 * @guid: The WMI GUID associated with this type to initialize 878 * 879 * Initialize all 5 types of attributes: enumeration, integer, 880 * string, password, ordered list object. Populates each attribute types 881 * respective properties under sysfs files 882 */ 883static int hp_init_bios_attributes(enum hp_wmi_data_type attr_type, const char *guid) 884{ 885 union acpi_object *obj = NULL; 886 int min_elements; 887 888 /* instance_id needs to be reset for each type GUID 889 * also, instance IDs are unique within GUID but not across 890 */ 891 int instance_id = 0; 892 int cur_instance_id = instance_id; 893 int ret = 0; 894 895 ret = hp_alloc_attributes_data(attr_type); 896 if (ret) 897 return ret; 898 899 switch (attr_type) { 900 case HPWMI_STRING_TYPE: 901 min_elements = STR_ELEM_CNT; 902 break; 903 case HPWMI_INTEGER_TYPE: 904 min_elements = INT_ELEM_CNT; 905 break; 906 case HPWMI_ENUMERATION_TYPE: 907 min_elements = ENUM_ELEM_CNT; 908 break; 909 case HPWMI_ORDERED_LIST_TYPE: 910 min_elements = ORD_ELEM_CNT; 911 break; 912 case HPWMI_PASSWORD_TYPE: 913 min_elements = PSWD_ELEM_CNT; 914 break; 915 default: 916 pr_err("Error: Unknown attr_type: %d\n", attr_type); 917 return -EINVAL; 918 } 919 920 /* need to use specific instance_id and guid combination to get right data */ 921 obj = hp_get_wmiobj_pointer(instance_id, guid); 922 if (!obj) 923 return -ENODEV; 924 925 mutex_lock(&bioscfg_drv.mutex); 926 while (obj) { 927 /* Take action appropriate to each ACPI TYPE */ 928 if (obj->type == ACPI_TYPE_PACKAGE) { 929 ret = hp_init_bios_package_attribute(attr_type, obj, 930 guid, min_elements, 931 cur_instance_id); 932 933 } else if (obj->type == ACPI_TYPE_BUFFER) { 934 ret = hp_init_bios_buffer_attribute(attr_type, obj, 935 guid, min_elements, 936 cur_instance_id); 937 938 } else { 939 pr_err("Expected ACPI-package or buffer type, got: %d\n", 940 obj->type); 941 ret = -EIO; 942 goto err_attr_init; 943 } 944 945 /* 946 * Failure reported in one attribute must not 947 * stop process of the remaining attribute values. 948 */ 949 if (ret >= 0) 950 cur_instance_id++; 951 952 kfree(obj); 953 instance_id++; 954 obj = hp_get_wmiobj_pointer(instance_id, guid); 955 } 956 957err_attr_init: 958 mutex_unlock(&bioscfg_drv.mutex); 959 kfree(obj); 960 return ret; 961} 962 963static int __init hp_init(void) 964{ 965 int ret; 966 int hp_bios_capable = wmi_has_guid(HP_WMI_BIOS_GUID); 967 int set_bios_settings = wmi_has_guid(HP_WMI_SET_BIOS_SETTING_GUID); 968 969 if (!hp_bios_capable) { 970 pr_err("Unable to run on non-HP system\n"); 971 return -ENODEV; 972 } 973 974 if (!set_bios_settings) { 975 pr_err("Unable to set BIOS settings on HP systems\n"); 976 return -ENODEV; 977 } 978 979 ret = hp_init_attr_set_interface(); 980 if (ret) 981 return ret; 982 983 bioscfg_drv.class_dev = device_create(&firmware_attributes_class, NULL, MKDEV(0, 0), 984 NULL, "%s", DRIVER_NAME); 985 if (IS_ERR(bioscfg_drv.class_dev)) { 986 ret = PTR_ERR(bioscfg_drv.class_dev); 987 goto err_unregister_class; 988 } 989 990 bioscfg_drv.main_dir_kset = kset_create_and_add("attributes", NULL, 991 &bioscfg_drv.class_dev->kobj); 992 if (!bioscfg_drv.main_dir_kset) { 993 ret = -ENOMEM; 994 pr_debug("Failed to create and add attributes\n"); 995 goto err_destroy_classdev; 996 } 997 998 bioscfg_drv.authentication_dir_kset = kset_create_and_add("authentication", NULL, 999 &bioscfg_drv.class_dev->kobj); 1000 if (!bioscfg_drv.authentication_dir_kset) { 1001 ret = -ENOMEM; 1002 pr_debug("Failed to create and add authentication\n"); 1003 goto err_release_attributes_data; 1004 } 1005 1006 /* 1007 * sysfs level attributes. 1008 * - pending_reboot 1009 */ 1010 ret = create_attributes_level_sysfs_files(); 1011 if (ret) 1012 pr_debug("Failed to create sysfs level attributes\n"); 1013 1014 ret = hp_init_bios_attributes(HPWMI_STRING_TYPE, HP_WMI_BIOS_STRING_GUID); 1015 if (ret) 1016 pr_debug("Failed to populate string type attributes\n"); 1017 1018 ret = hp_init_bios_attributes(HPWMI_INTEGER_TYPE, HP_WMI_BIOS_INTEGER_GUID); 1019 if (ret) 1020 pr_debug("Failed to populate integer type attributes\n"); 1021 1022 ret = hp_init_bios_attributes(HPWMI_ENUMERATION_TYPE, HP_WMI_BIOS_ENUMERATION_GUID); 1023 if (ret) 1024 pr_debug("Failed to populate enumeration type attributes\n"); 1025 1026 ret = hp_init_bios_attributes(HPWMI_ORDERED_LIST_TYPE, HP_WMI_BIOS_ORDERED_LIST_GUID); 1027 if (ret) 1028 pr_debug("Failed to populate ordered list object type attributes\n"); 1029 1030 ret = hp_init_bios_attributes(HPWMI_PASSWORD_TYPE, HP_WMI_BIOS_PASSWORD_GUID); 1031 if (ret) 1032 pr_debug("Failed to populate password object type attributes\n"); 1033 1034 bioscfg_drv.spm_data.attr_name_kobj = NULL; 1035 ret = hp_add_other_attributes(HPWMI_SECURE_PLATFORM_TYPE); 1036 if (ret) 1037 pr_debug("Failed to populate secure platform object type attribute\n"); 1038 1039 bioscfg_drv.sure_start_attr_kobj = NULL; 1040 ret = hp_add_other_attributes(HPWMI_SURE_START_TYPE); 1041 if (ret) 1042 pr_debug("Failed to populate sure start object type attribute\n"); 1043 1044 return 0; 1045 1046err_release_attributes_data: 1047 release_attributes_data(); 1048 1049err_destroy_classdev: 1050 device_unregister(bioscfg_drv.class_dev); 1051 1052err_unregister_class: 1053 hp_exit_attr_set_interface(); 1054 1055 return ret; 1056} 1057 1058static void __exit hp_exit(void) 1059{ 1060 release_attributes_data(); 1061 device_unregister(bioscfg_drv.class_dev); 1062 1063 hp_exit_attr_set_interface(); 1064} 1065 1066module_init(hp_init); 1067module_exit(hp_exit);
~/
Read-only file preview.