1 // SPDX-License-Identifier: GPL-2.0
3 * Common methods for use with hp-bioscfg driver
5 * Copyright (c) 2022 HP Development Company, L.P.
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/wmi.h>
15 #include "../../firmware_attributes_class.h"
16 #include <linux/nls.h>
17 #include <linux/errno.h>
19 MODULE_AUTHOR("Jorge Lopez <jorge.lopez2@hp.com>");
20 MODULE_DESCRIPTION("HP BIOS Configuration Driver");
21 MODULE_LICENSE("GPL");
23 struct bioscfg_priv bioscfg_drv
= {
24 .mutex
= __MUTEX_INITIALIZER(bioscfg_drv
.mutex
),
27 static struct class *fw_attr_class
;
29 ssize_t
display_name_language_code_show(struct kobject
*kobj
,
30 struct kobj_attribute
*attr
,
33 return sysfs_emit(buf
, "%s\n", LANG_CODE_STR
);
36 struct kobj_attribute common_display_langcode
=
37 __ATTR_RO(display_name_language_code
);
39 int hp_get_integer_from_buffer(u8
**buffer
, u32
*buffer_size
, u32
*integer
)
41 int *ptr
= PTR_ALIGN((int *)*buffer
, sizeof(int));
43 /* Ensure there is enough space remaining to read the integer */
44 if (*buffer_size
< sizeof(int))
49 *buffer_size
-= sizeof(int);
54 int hp_get_string_from_buffer(u8
**buffer
, u32
*buffer_size
, char *dst
, u32 dst_size
)
56 u16
*src
= (u16
*)*buffer
;
63 if (*buffer_size
< sizeof(u16
))
67 /* size value in u16 chars */
68 size
= src_size
/ sizeof(u16
);
70 /* Ensure there is enough space remaining to read and convert
73 if (*buffer_size
< src_size
)
76 for (i
= 0; i
< size
; i
++)
84 * Conversion is limited to destination string max number of
89 conv_dst_size
= dst_size
- 1;
92 * convert from UTF-16 unicode to ASCII
94 utf16s_to_utf8s(src
, src_size
, UTF16_HOST_ENDIAN
, dst
, conv_dst_size
);
95 dst
[conv_dst_size
] = 0;
97 for (i
= 0; i
< conv_dst_size
; i
++) {
103 if (i
== conv_dst_size
)
109 else if (*src
== '\n')
111 else if (*src
== '\t')
113 else if (*src
== '"')
121 *buffer_size
-= size
* sizeof(u16
);
126 int hp_get_common_data_from_buffer(u8
**buffer_ptr
, u32
*buffer_size
,
127 struct common_data
*common_data
)
133 ret
= hp_get_string_from_buffer(buffer_ptr
, buffer_size
, common_data
->path
,
134 sizeof(common_data
->path
));
139 ret
= hp_get_integer_from_buffer(buffer_ptr
, buffer_size
,
140 &common_data
->is_readonly
);
145 ret
= hp_get_integer_from_buffer(buffer_ptr
, buffer_size
,
146 &common_data
->display_in_ui
);
150 // REQUIRES_PHYSICAL_PRESENCE:
151 ret
= hp_get_integer_from_buffer(buffer_ptr
, buffer_size
,
152 &common_data
->requires_physical_presence
);
157 ret
= hp_get_integer_from_buffer(buffer_ptr
, buffer_size
,
158 &common_data
->sequence
);
162 // PREREQUISITES_SIZE:
163 ret
= hp_get_integer_from_buffer(buffer_ptr
, buffer_size
,
164 &common_data
->prerequisites_size
);
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
;
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
]));
184 ret
= hp_get_integer_from_buffer(buffer_ptr
, buffer_size
,
185 &common_data
->security_level
);
191 int hp_enforce_single_line_input(char *buf
, size_t count
)
195 p
= memchr(buf
, '\n', count
);
197 if (p
== buf
+ count
- 1)
198 *p
= '\0'; /* strip trailing newline */
200 return -EINVAL
; /* enforce single line input */
205 /* Set pending reboot value and generate KOBJ_NAME event */
206 void hp_set_reboot_and_signal_event(void)
208 bioscfg_drv
.pending_reboot
= true;
209 kobject_uevent(&bioscfg_drv
.class_dev
->kobj
, KOBJ_CHANGE
);
213 * hp_calculate_string_buffer() - determines size of string buffer for
214 * use with BIOS communication
216 * @str: the string to calculate based upon
218 size_t hp_calculate_string_buffer(const char *str
)
220 size_t length
= strlen(str
);
222 /* BIOS expects 4 bytes when an empty string is found */
226 /* u16 length field + one UTF16 char for each input char */
227 return sizeof(u16
) + strlen(str
) * sizeof(u16
);
230 int hp_wmi_error_and_message(int error_code
)
232 char *error_msg
= NULL
;
235 switch (error_code
) {
237 error_msg
= "Success";
241 error_msg
= "Command failed";
245 error_msg
= "Invalid signature";
248 case INVALID_CMD_VALUE
:
249 error_msg
= "Invalid command value/Feature not supported";
252 case INVALID_CMD_TYPE
:
253 error_msg
= "Invalid command type";
256 case INVALID_DATA_SIZE
:
257 error_msg
= "Invalid data size";
260 case INVALID_CMD_PARAM
:
261 error_msg
= "Invalid command parameter";
264 case ENCRYP_CMD_REQUIRED
:
265 error_msg
= "Secure/encrypted command required";
268 case NO_SECURE_SESSION
:
269 error_msg
= "No secure session established";
272 case SECURE_SESSION_FOUND
:
273 error_msg
= "Secure session already established";
276 case SECURE_SESSION_FAILED
:
277 error_msg
= "Secure session failed";
281 error_msg
= "Other permission/Authentication failed";
284 case INVALID_BIOS_AUTH
:
285 error_msg
= "Invalid BIOS administrator password";
288 case NONCE_DID_NOT_MATCH
:
289 error_msg
= "Nonce did not match";
293 error_msg
= "Generic/Other error";
296 case BIOS_ADMIN_POLICY_NOT_MET
:
297 error_msg
= "BIOS Admin password does not meet password policy requirements";
300 case BIOS_ADMIN_NOT_SET
:
301 error_msg
= "BIOS Setup password is not set";
304 case P21_NO_PROVISIONED
:
305 error_msg
= "P21 is not provisioned";
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";
313 error_msg
= "P21 in use (cannot deprovision)";
317 error_msg
= "HEP not activated";
320 case HEP_ALREADY_SET
:
321 error_msg
= "HEP Transport already set";
324 case HEP_CHECK_STATE
:
325 error_msg
= "Check the current HEP state";
329 error_msg
= "Generic/Other error";
335 pr_warn_ratelimited("Returned error 0x%x, \"%s\"\n", error_code
, error_msg
);
340 static ssize_t
pending_reboot_show(struct kobject
*kobj
,
341 struct kobj_attribute
*attr
,
344 return sysfs_emit(buf
, "%d\n", bioscfg_drv
.pending_reboot
);
347 static struct kobj_attribute pending_reboot
= __ATTR_RO(pending_reboot
);
350 * create_attributes_level_sysfs_files() - Creates pending_reboot attributes
352 static int create_attributes_level_sysfs_files(void)
354 return sysfs_create_file(&bioscfg_drv
.main_dir_kset
->kobj
,
355 &pending_reboot
.attr
);
358 static void attr_name_release(struct kobject
*kobj
)
363 static const struct kobj_type attr_name_ktype
= {
364 .release
= attr_name_release
,
365 .sysfs_ops
= &kobj_sysfs_ops
,
369 * hp_get_wmiobj_pointer() - Get Content of WMI block for particular instance
371 * @instance_id: WMI instance ID
372 * @guid_string: WMI GUID (in str form)
374 * Fetches the content for WMI block (instance_id) under GUID (guid_string)
375 * Caller must kfree the return
377 union acpi_object
*hp_get_wmiobj_pointer(int instance_id
, const char *guid_string
)
379 struct acpi_buffer out
= { ACPI_ALLOCATE_BUFFER
, NULL
};
382 status
= wmi_query_block(guid_string
, instance_id
, &out
);
383 return ACPI_SUCCESS(status
) ? (union acpi_object
*)out
.pointer
: NULL
;
387 * hp_get_instance_count() - Compute total number of instances under guid_string
389 * @guid_string: WMI GUID (in string form)
391 int hp_get_instance_count(const char *guid_string
)
393 union acpi_object
*wmi_obj
= NULL
;
398 wmi_obj
= hp_get_wmiobj_pointer(i
, guid_string
);
406 * hp_alloc_attributes_data() - Allocate attributes data for a particular type
408 * @attr_type: Attribute type to allocate
410 static int hp_alloc_attributes_data(int attr_type
)
413 case HPWMI_STRING_TYPE
:
414 return hp_alloc_string_data();
416 case HPWMI_INTEGER_TYPE
:
417 return hp_alloc_integer_data();
419 case HPWMI_ENUMERATION_TYPE
:
420 return hp_alloc_enumeration_data();
422 case HPWMI_ORDERED_LIST_TYPE
:
423 return hp_alloc_ordered_list_data();
425 case HPWMI_PASSWORD_TYPE
:
426 return hp_alloc_password_data();
433 int hp_convert_hexstr_to_str(const char *input
, u32 input_len
, char **str
, int *len
)
438 char *new_str
= NULL
;
442 if (input_len
<= 0 || !input
|| !str
|| !len
)
448 new_str
= kmalloc(input_len
, GFP_KERNEL
);
452 for (i
= 0; i
< input_len
; i
+= 5) {
453 strncpy(tmp
, input
+ i
, strlen(tmp
));
454 if (kstrtol(tmp
, 16, &ch
) == 0) {
458 ch
== '\n' || ch
== '\t') {
465 new_str
[new_len
++] = '\\';
467 new_str
[new_len
++] = ch
;
474 new_str
[new_len
] = '\0';
475 *str
= krealloc(new_str
, (new_len
+ 1) * sizeof(char),
490 /* map output size to the corresponding WMI method id */
491 int hp_encode_outsize_for_pvsz(int outsize
)
507 * Update friendly display name for several attributes associated to
508 * 'Schedule Power-On'
510 void hp_friendly_user_name_update(char *path
, const char *attr_name
,
511 char *attr_display
, int attr_size
)
513 if (strstr(path
, SCHEDULE_POWER_ON
))
514 snprintf(attr_display
, attr_size
, "%s - %s", SCHEDULE_POWER_ON
, attr_name
);
516 strscpy(attr_display
, attr_name
, attr_size
);
520 * hp_update_attribute_permissions() - Update attributes permissions when
521 * isReadOnly value is 1
523 * @is_readonly: bool value to indicate if it a readonly attribute.
524 * @current_val: kobj_attribute corresponding to attribute.
527 void hp_update_attribute_permissions(bool is_readonly
, struct kobj_attribute
*current_val
)
529 current_val
->attr
.mode
= is_readonly
? 0444 : 0644;
533 * destroy_attribute_objs() - Free a kset of kobjects
534 * @kset: The kset to destroy
536 * Fress kobjects created for each attribute_name under attribute type kset
538 static void destroy_attribute_objs(struct kset
*kset
)
540 struct kobject
*pos
, *next
;
542 list_for_each_entry_safe(pos
, next
, &kset
->list
, entry
)
547 * release_attributes_data() - Clean-up all sysfs directories and files created
549 static void release_attributes_data(void)
551 mutex_lock(&bioscfg_drv
.mutex
);
553 hp_exit_string_attributes();
554 hp_exit_integer_attributes();
555 hp_exit_enumeration_attributes();
556 hp_exit_ordered_list_attributes();
557 hp_exit_password_attributes();
558 hp_exit_sure_start_attributes();
559 hp_exit_secure_platform_attributes();
561 if (bioscfg_drv
.authentication_dir_kset
) {
562 destroy_attribute_objs(bioscfg_drv
.authentication_dir_kset
);
563 kset_unregister(bioscfg_drv
.authentication_dir_kset
);
564 bioscfg_drv
.authentication_dir_kset
= NULL
;
566 if (bioscfg_drv
.main_dir_kset
) {
567 sysfs_remove_file(&bioscfg_drv
.main_dir_kset
->kobj
, &pending_reboot
.attr
);
568 destroy_attribute_objs(bioscfg_drv
.main_dir_kset
);
569 kset_unregister(bioscfg_drv
.main_dir_kset
);
570 bioscfg_drv
.main_dir_kset
= NULL
;
572 mutex_unlock(&bioscfg_drv
.mutex
);
576 * hp_add_other_attributes() - Initialize HP custom attributes not
577 * reported by BIOS and required to support Secure Platform and Sure
580 * @attr_type: Custom HP attribute not reported by BIOS
582 * Initialize all 2 types of attributes: Platform and Sure Start
583 * object. Populates each attribute types respective properties
586 * Returns zero(0) if successful. Otherwise, a negative value.
588 static int hp_add_other_attributes(int attr_type
)
590 struct kobject
*attr_name_kobj
;
594 attr_name_kobj
= kzalloc(sizeof(*attr_name_kobj
), GFP_KERNEL
);
598 mutex_lock(&bioscfg_drv
.mutex
);
600 /* Check if attribute type is supported */
602 case HPWMI_SECURE_PLATFORM_TYPE
:
603 attr_name_kobj
->kset
= bioscfg_drv
.authentication_dir_kset
;
607 case HPWMI_SURE_START_TYPE
:
608 attr_name_kobj
->kset
= bioscfg_drv
.main_dir_kset
;
609 attr_name
= SURE_START_STR
;
613 pr_err("Error: Unknown attr_type: %d\n", attr_type
);
615 kfree(attr_name_kobj
);
616 goto unlock_drv_mutex
;
619 ret
= kobject_init_and_add(attr_name_kobj
, &attr_name_ktype
,
620 NULL
, "%s", attr_name
);
622 pr_err("Error encountered [%d]\n", ret
);
623 goto err_other_attr_init
;
626 /* Populate attribute data */
628 case HPWMI_SECURE_PLATFORM_TYPE
:
629 ret
= hp_populate_secure_platform_data(attr_name_kobj
);
632 case HPWMI_SURE_START_TYPE
:
633 ret
= hp_populate_sure_start_data(attr_name_kobj
);
641 goto err_other_attr_init
;
643 mutex_unlock(&bioscfg_drv
.mutex
);
647 kobject_put(attr_name_kobj
);
649 mutex_unlock(&bioscfg_drv
.mutex
);
653 static int hp_init_bios_package_attribute(enum hp_wmi_data_type attr_type
,
654 union acpi_object
*obj
,
655 const char *guid
, int min_elements
,
658 struct kobject
*attr_name_kobj
, *duplicate
;
659 union acpi_object
*elements
;
660 struct kset
*temp_kset
;
662 char *str_value
= NULL
;
666 /* Take action appropriate to each ACPI TYPE */
667 if (obj
->package
.count
< min_elements
) {
668 pr_err("ACPI-package does not have enough elements: %d < %d\n",
669 obj
->package
.count
, min_elements
);
673 elements
= obj
->package
.elements
;
675 /* sanity checking */
676 if (elements
[NAME
].type
!= ACPI_TYPE_STRING
) {
677 pr_debug("incorrect element type\n");
680 if (strlen(elements
[NAME
].string
.pointer
) == 0) {
681 pr_debug("empty attribute found\n");
685 if (attr_type
== HPWMI_PASSWORD_TYPE
)
686 temp_kset
= bioscfg_drv
.authentication_dir_kset
;
688 temp_kset
= bioscfg_drv
.main_dir_kset
;
690 /* convert attribute name to string */
691 ret
= hp_convert_hexstr_to_str(elements
[NAME
].string
.pointer
,
692 elements
[NAME
].string
.length
,
693 &str_value
, &str_len
);
696 pr_debug("Failed to populate integer package data. Error [0%0x]\n",
702 /* All duplicate attributes found are ignored */
703 duplicate
= kset_find_obj(temp_kset
, str_value
);
705 pr_debug("Duplicate attribute name found - %s\n", str_value
);
706 /* kset_find_obj() returns a reference */
707 kobject_put(duplicate
);
711 /* build attribute */
712 attr_name_kobj
= kzalloc(sizeof(*attr_name_kobj
), GFP_KERNEL
);
713 if (!attr_name_kobj
) {
718 attr_name_kobj
->kset
= temp_kset
;
720 ret
= kobject_init_and_add(attr_name_kobj
, &attr_name_ktype
,
721 NULL
, "%s", str_value
);
724 kobject_put(attr_name_kobj
);
728 /* enumerate all of these attributes */
730 case HPWMI_STRING_TYPE
:
731 ret
= hp_populate_string_package_data(elements
,
735 case HPWMI_INTEGER_TYPE
:
736 ret
= hp_populate_integer_package_data(elements
,
740 case HPWMI_ENUMERATION_TYPE
:
741 ret
= hp_populate_enumeration_package_data(elements
,
745 case HPWMI_ORDERED_LIST_TYPE
:
746 ret
= hp_populate_ordered_list_package_data(elements
,
750 case HPWMI_PASSWORD_TYPE
:
751 ret
= hp_populate_password_package_data(elements
,
756 pr_debug("Unknown attribute type found: 0x%x\n", attr_type
);
765 static int hp_init_bios_buffer_attribute(enum hp_wmi_data_type attr_type
,
766 union acpi_object
*obj
,
767 const char *guid
, int min_elements
,
770 struct kobject
*attr_name_kobj
, *duplicate
;
771 struct kset
*temp_kset
;
772 char str
[MAX_BUFF_SIZE
];
774 char *temp_str
= NULL
;
775 char *str_value
= NULL
;
776 u8
*buffer_ptr
= NULL
;
780 buffer_size
= obj
->buffer
.length
;
781 buffer_ptr
= obj
->buffer
.pointer
;
783 ret
= hp_get_string_from_buffer(&buffer_ptr
,
784 &buffer_size
, str
, MAX_BUFF_SIZE
);
789 if (attr_type
== HPWMI_PASSWORD_TYPE
||
790 attr_type
== HPWMI_SECURE_PLATFORM_TYPE
)
791 temp_kset
= bioscfg_drv
.authentication_dir_kset
;
793 temp_kset
= bioscfg_drv
.main_dir_kset
;
795 /* All duplicate attributes found are ignored */
796 duplicate
= kset_find_obj(temp_kset
, str
);
798 pr_debug("Duplicate attribute name found - %s\n", str
);
799 /* kset_find_obj() returns a reference */
800 kobject_put(duplicate
);
804 /* build attribute */
805 attr_name_kobj
= kzalloc(sizeof(*attr_name_kobj
), GFP_KERNEL
);
806 if (!attr_name_kobj
) {
811 attr_name_kobj
->kset
= temp_kset
;
814 if (attr_type
== HPWMI_SECURE_PLATFORM_TYPE
)
817 ret
= kobject_init_and_add(attr_name_kobj
,
818 &attr_name_ktype
, NULL
, "%s", temp_str
);
820 kobject_put(attr_name_kobj
);
824 /* enumerate all of these attributes */
826 case HPWMI_STRING_TYPE
:
827 ret
= hp_populate_string_buffer_data(buffer_ptr
,
832 case HPWMI_INTEGER_TYPE
:
833 ret
= hp_populate_integer_buffer_data(buffer_ptr
,
838 case HPWMI_ENUMERATION_TYPE
:
839 ret
= hp_populate_enumeration_buffer_data(buffer_ptr
,
844 case HPWMI_ORDERED_LIST_TYPE
:
845 ret
= hp_populate_ordered_list_buffer_data(buffer_ptr
,
850 case HPWMI_PASSWORD_TYPE
:
851 ret
= hp_populate_password_buffer_data(buffer_ptr
,
857 pr_debug("Unknown attribute type found: 0x%x\n", attr_type
);
867 * hp_init_bios_attributes() - Initialize all attributes for a type
868 * @attr_type: The attribute type to initialize
869 * @guid: The WMI GUID associated with this type to initialize
871 * Initialize all 5 types of attributes: enumeration, integer,
872 * string, password, ordered list object. Populates each attribute types
873 * respective properties under sysfs files
875 static int hp_init_bios_attributes(enum hp_wmi_data_type attr_type
, const char *guid
)
877 union acpi_object
*obj
= NULL
;
880 /* instance_id needs to be reset for each type GUID
881 * also, instance IDs are unique within GUID but not across
884 int cur_instance_id
= instance_id
;
887 ret
= hp_alloc_attributes_data(attr_type
);
892 case HPWMI_STRING_TYPE
:
893 min_elements
= STR_ELEM_CNT
;
895 case HPWMI_INTEGER_TYPE
:
896 min_elements
= INT_ELEM_CNT
;
898 case HPWMI_ENUMERATION_TYPE
:
899 min_elements
= ENUM_ELEM_CNT
;
901 case HPWMI_ORDERED_LIST_TYPE
:
902 min_elements
= ORD_ELEM_CNT
;
904 case HPWMI_PASSWORD_TYPE
:
905 min_elements
= PSWD_ELEM_CNT
;
908 pr_err("Error: Unknown attr_type: %d\n", attr_type
);
912 /* need to use specific instance_id and guid combination to get right data */
913 obj
= hp_get_wmiobj_pointer(instance_id
, guid
);
917 mutex_lock(&bioscfg_drv
.mutex
);
919 /* Take action appropriate to each ACPI TYPE */
920 if (obj
->type
== ACPI_TYPE_PACKAGE
) {
921 ret
= hp_init_bios_package_attribute(attr_type
, obj
,
925 } else if (obj
->type
== ACPI_TYPE_BUFFER
) {
926 ret
= hp_init_bios_buffer_attribute(attr_type
, obj
,
931 pr_err("Expected ACPI-package or buffer type, got: %d\n",
938 * Failure reported in one attribute must not
939 * stop process of the remaining attribute values.
946 obj
= hp_get_wmiobj_pointer(instance_id
, guid
);
950 mutex_unlock(&bioscfg_drv
.mutex
);
955 static int __init
hp_init(void)
958 int hp_bios_capable
= wmi_has_guid(HP_WMI_BIOS_GUID
);
959 int set_bios_settings
= wmi_has_guid(HP_WMI_SET_BIOS_SETTING_GUID
);
961 if (!hp_bios_capable
) {
962 pr_err("Unable to run on non-HP system\n");
966 if (!set_bios_settings
) {
967 pr_err("Unable to set BIOS settings on HP systems\n");
971 ret
= hp_init_attr_set_interface();
975 ret
= fw_attributes_class_get(&fw_attr_class
);
977 goto err_unregister_class
;
979 bioscfg_drv
.class_dev
= device_create(fw_attr_class
, NULL
, MKDEV(0, 0),
980 NULL
, "%s", DRIVER_NAME
);
981 if (IS_ERR(bioscfg_drv
.class_dev
)) {
982 ret
= PTR_ERR(bioscfg_drv
.class_dev
);
983 goto err_unregister_class
;
986 bioscfg_drv
.main_dir_kset
= kset_create_and_add("attributes", NULL
,
987 &bioscfg_drv
.class_dev
->kobj
);
988 if (!bioscfg_drv
.main_dir_kset
) {
990 pr_debug("Failed to create and add attributes\n");
991 goto err_destroy_classdev
;
994 bioscfg_drv
.authentication_dir_kset
= kset_create_and_add("authentication", NULL
,
995 &bioscfg_drv
.class_dev
->kobj
);
996 if (!bioscfg_drv
.authentication_dir_kset
) {
998 pr_debug("Failed to create and add authentication\n");
999 goto err_release_attributes_data
;
1003 * sysfs level attributes.
1006 ret
= create_attributes_level_sysfs_files();
1008 pr_debug("Failed to create sysfs level attributes\n");
1010 ret
= hp_init_bios_attributes(HPWMI_STRING_TYPE
, HP_WMI_BIOS_STRING_GUID
);
1012 pr_debug("Failed to populate string type attributes\n");
1014 ret
= hp_init_bios_attributes(HPWMI_INTEGER_TYPE
, HP_WMI_BIOS_INTEGER_GUID
);
1016 pr_debug("Failed to populate integer type attributes\n");
1018 ret
= hp_init_bios_attributes(HPWMI_ENUMERATION_TYPE
, HP_WMI_BIOS_ENUMERATION_GUID
);
1020 pr_debug("Failed to populate enumeration type attributes\n");
1022 ret
= hp_init_bios_attributes(HPWMI_ORDERED_LIST_TYPE
, HP_WMI_BIOS_ORDERED_LIST_GUID
);
1024 pr_debug("Failed to populate ordered list object type attributes\n");
1026 ret
= hp_init_bios_attributes(HPWMI_PASSWORD_TYPE
, HP_WMI_BIOS_PASSWORD_GUID
);
1028 pr_debug("Failed to populate password object type attributes\n");
1030 bioscfg_drv
.spm_data
.attr_name_kobj
= NULL
;
1031 ret
= hp_add_other_attributes(HPWMI_SECURE_PLATFORM_TYPE
);
1033 pr_debug("Failed to populate secure platform object type attribute\n");
1035 bioscfg_drv
.sure_start_attr_kobj
= NULL
;
1036 ret
= hp_add_other_attributes(HPWMI_SURE_START_TYPE
);
1038 pr_debug("Failed to populate sure start object type attribute\n");
1042 err_release_attributes_data
:
1043 release_attributes_data();
1045 err_destroy_classdev
:
1046 device_destroy(fw_attr_class
, MKDEV(0, 0));
1048 err_unregister_class
:
1049 fw_attributes_class_put();
1050 hp_exit_attr_set_interface();
1055 static void __exit
hp_exit(void)
1057 release_attributes_data();
1058 device_destroy(fw_attr_class
, MKDEV(0, 0));
1060 fw_attributes_class_put();
1061 hp_exit_attr_set_interface();
1064 module_init(hp_init
);
1065 module_exit(hp_exit
);