1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Functions corresponding to sure start object type attributes under
4  * BIOS for use with hp-bioscfg driver
5  *
6  * Copyright (c) 2022 HP Development Company, L.P.
7  */
8 
9 #include "bioscfg.h"
10 #include <linux/types.h>
11 
12 /* Maximum number of log entries supported when log entry size is 16
13  * bytes. This value is calculated by dividing 4096 (page size) by
14  * log entry size.
15  */
16 #define LOG_MAX_ENTRIES		254
17 
18 /*
19  * Current Log entry size. This value size will change in the
20  * future. The driver reads a total of 128 bytes for each log entry
21  * provided by BIOS but only the first 16 bytes are used/read.
22  */
23 #define LOG_ENTRY_SIZE		16
24 
25 /*
26  * audit_log_entry_count_show - Reports the number of
27  *				existing audit log entries available
28  *				to be read
29  */
30 static ssize_t audit_log_entry_count_show(struct kobject *kobj,
31 					  struct kobj_attribute *attr, char *buf)
32 {
33 	int ret;
34 	u32 count = 0;
35 
36 	ret = hp_wmi_perform_query(HPWMI_SURESTART_GET_LOG_COUNT,
37 				   HPWMI_SURESTART,
38 				   &count, 1, sizeof(count));
39 
40 	if (ret < 0)
41 		return ret;
42 
43 	return sysfs_emit(buf, "%d,%d,%d\n", count, LOG_ENTRY_SIZE,
44 			  LOG_MAX_ENTRIES);
45 }
46 
47 /*
48  * audit_log_entries_show() - Return all entries found in log file
49  */
50 static ssize_t audit_log_entries_show(struct kobject *kobj,
51 				      struct kobj_attribute *attr, char *buf)
52 {
53 	int ret;
54 	int i;
55 	u32 count = 0;
56 	u8 audit_log_buffer[128];
57 
58 	// Get the number of event logs
59 	ret = hp_wmi_perform_query(HPWMI_SURESTART_GET_LOG_COUNT,
60 				   HPWMI_SURESTART,
61 				   &count, 1, sizeof(count));
62 
63 	if (ret < 0)
64 		return ret;
65 
66 	/*
67 	 * The show() api will not work if the audit logs ever go
68 	 * beyond 4KB
69 	 */
70 	if (count * LOG_ENTRY_SIZE > PAGE_SIZE)
71 		return -EIO;
72 
73 	/*
74 	 * We are guaranteed the buffer is 4KB so today all the event
75 	 * logs will fit
76 	 */
77 	for (i = 0; i < count; i++) {
78 		audit_log_buffer[0] = i + 1;
79 
80 		/*
81 		 * read audit log entry at a time. 'buf' input value
82 		 * provides the audit log entry to be read. On
83 		 * input, Byte 0 = Audit Log entry number from
84 		 * beginning (1..254)
85 		 * Entry number 1 is the newest entry whereas the
86 		 * highest entry number (number of entries) is the
87 		 * oldest entry.
88 		 */
89 		ret = hp_wmi_perform_query(HPWMI_SURESTART_GET_LOG,
90 					   HPWMI_SURESTART,
91 					   audit_log_buffer, 1, 128);
92 
93 		if (ret < 0 || (LOG_ENTRY_SIZE * i) > PAGE_SIZE) {
94 			/*
95 			 * Encountered a failure while reading
96 			 * individual logs. Only a partial list of
97 			 * audit log will be returned.
98 			 */
99 			break;
100 		} else {
101 			memcpy(buf, audit_log_buffer, LOG_ENTRY_SIZE);
102 			buf += LOG_ENTRY_SIZE;
103 		}
104 	}
105 
106 	return i * LOG_ENTRY_SIZE;
107 }
108 
109 static struct kobj_attribute sure_start_audit_log_entry_count = __ATTR_RO(audit_log_entry_count);
110 static struct kobj_attribute sure_start_audit_log_entries = __ATTR_RO(audit_log_entries);
111 
112 static struct attribute *sure_start_attrs[] = {
113 	&sure_start_audit_log_entry_count.attr,
114 	&sure_start_audit_log_entries.attr,
115 	NULL
116 };
117 
118 static const struct attribute_group sure_start_attr_group = {
119 	.attrs = sure_start_attrs,
120 };
121 
122 void hp_exit_sure_start_attributes(void)
123 {
124 	sysfs_remove_group(bioscfg_drv.sure_start_attr_kobj,
125 			   &sure_start_attr_group);
126 }
127 
128 int hp_populate_sure_start_data(struct kobject *attr_name_kobj)
129 {
130 	bioscfg_drv.sure_start_attr_kobj = attr_name_kobj;
131 	return sysfs_create_group(attr_name_kobj, &sure_start_attr_group);
132 }
133