platform/x86: hp-bioscfg: surestart-attributes
authorJorge Lopez <jorge.lopez2@hp.com>
Thu, 8 Jun 2023 16:33:17 +0000 (11:33 -0500)
committerHans de Goede <hdegoede@redhat.com>
Mon, 10 Jul 2023 12:41:28 +0000 (14:41 +0200)
Add Sure Start attributes support to hp-bioscfg.

HP BIOS Configuration driver purpose is to provide a driver supporting
the latest sysfs class firmware attributes framework allowing the user
to change BIOS settings and security solutions on HP Inc.’s commercial
notebooks.

Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com>
Reviewed-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://lore.kernel.org/r/20230608163319.18934-12-jorge.lopez2@hp.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
drivers/platform/x86/hp/hp-bioscfg/surestart-attributes.c [new file with mode: 0644]

diff --git a/drivers/platform/x86/hp/hp-bioscfg/surestart-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/surestart-attributes.c
new file mode 100644 (file)
index 0000000..b57e42f
--- /dev/null
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Functions corresponding to sure start object type attributes under
+ * BIOS for use with hp-bioscfg driver
+ *
+ * Copyright (c) 2022 HP Development Company, L.P.
+ */
+
+#include "bioscfg.h"
+#include <linux/types.h>
+
+/* Maximum number of log entries supported when log entry size is 16
+ * bytes. This value is calculated by dividing 4096 (page size) by
+ * log entry size.
+ */
+#define LOG_MAX_ENTRIES                254
+
+/*
+ * Current Log entry size. This value size will change in the
+ * future. The driver reads a total of 128 bytes for each log entry
+ * provided by BIOS but only the first 16 bytes are used/read.
+ */
+#define LOG_ENTRY_SIZE         16
+
+/*
+ * audit_log_entry_count_show - Reports the number of
+ *                             existing audit log entries available
+ *                             to be read
+ */
+static ssize_t audit_log_entry_count_show(struct kobject *kobj,
+                                         struct kobj_attribute *attr, char *buf)
+{
+       int ret;
+       u32 count = 0;
+
+       ret = hp_wmi_perform_query(HPWMI_SURESTART_GET_LOG_COUNT,
+                                  HPWMI_SURESTART,
+                                  &count, 1, sizeof(count));
+
+       if (ret < 0)
+               return ret;
+
+       return sysfs_emit(buf, "%d,%d,%d\n", count, LOG_ENTRY_SIZE,
+                         LOG_MAX_ENTRIES);
+}
+
+/*
+ * audit_log_entries_show() - Return all entries found in log file
+ */
+static ssize_t audit_log_entries_show(struct kobject *kobj,
+                                     struct kobj_attribute *attr, char *buf)
+{
+       int ret;
+       int i;
+       u32 count = 0;
+       u8 audit_log_buffer[128];
+
+       // Get the number of event logs
+       ret = hp_wmi_perform_query(HPWMI_SURESTART_GET_LOG_COUNT,
+                                  HPWMI_SURESTART,
+                                  &count, 1, sizeof(count));
+
+       if (ret < 0)
+               return ret;
+
+       /*
+        * The show() api will not work if the audit logs ever go
+        * beyond 4KB
+        */
+       if (count * LOG_ENTRY_SIZE > PAGE_SIZE)
+               return -EIO;
+
+       /*
+        * We are guaranteed the buffer is 4KB so today all the event
+        * logs will fit
+        */
+       for (i = 0; i < count; i++) {
+               audit_log_buffer[0] = i + 1;
+
+               /*
+                * read audit log entry at a time. 'buf' input value
+                * provides the audit log entry to be read. On
+                * input, Byte 0 = Audit Log entry number from
+                * beginning (1..254)
+                * Entry number 1 is the newest entry whereas the
+                * highest entry number (number of entries) is the
+                * oldest entry.
+                */
+               ret = hp_wmi_perform_query(HPWMI_SURESTART_GET_LOG,
+                                          HPWMI_SURESTART,
+                                          audit_log_buffer, 1, 128);
+
+               if (ret < 0 || (LOG_ENTRY_SIZE * i) > PAGE_SIZE) {
+                       /*
+                        * Encountered a failure while reading
+                        * individual logs. Only a partial list of
+                        * audit log will be returned.
+                        */
+                       break;
+               } else {
+                       memcpy(buf, audit_log_buffer, LOG_ENTRY_SIZE);
+                       buf += LOG_ENTRY_SIZE;
+               }
+       }
+
+       return i * LOG_ENTRY_SIZE;
+}
+
+static struct kobj_attribute sure_start_audit_log_entry_count = __ATTR_RO(audit_log_entry_count);
+static struct kobj_attribute sure_start_audit_log_entries = __ATTR_RO(audit_log_entries);
+
+static struct attribute *sure_start_attrs[] = {
+       &sure_start_audit_log_entry_count.attr,
+       &sure_start_audit_log_entries.attr,
+       NULL
+};
+
+static const struct attribute_group sure_start_attr_group = {
+       .attrs = sure_start_attrs,
+};
+
+void hp_exit_sure_start_attributes(void)
+{
+       sysfs_remove_group(bioscfg_drv.sure_start_attr_kobj,
+                          &sure_start_attr_group);
+}
+
+int hp_populate_sure_start_data(struct kobject *attr_name_kobj)
+{
+       bioscfg_drv.sure_start_attr_kobj = attr_name_kobj;
+       return sysfs_create_group(attr_name_kobj, &sure_start_attr_group);
+}