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 */
audit_log_entry_count_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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 */
audit_log_entries_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
hp_exit_sure_start_attributes(void)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
hp_populate_sure_start_data(struct kobject * attr_name_kobj)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