[PATCH v4 5/6] HP BIOSCFG driver - set 4

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The purpose for this patch is submit HP BIOSCFG driver to be list of
HP Linux kernel drivers.  The driver include a total of 12 files
broken in several patches.  This is set 4 of 4.

Signed-off-by: Jorge Lopez <jorge.lopez2@xxxxxx>

---
Based on the latest platform-drivers-x86.git/for-next
---
 .../x86/hp/hp-bioscfg/sureadmin-attributes.c  | 1014 +++++++++++++++++
 .../x86/hp/hp-bioscfg/surestart-attributes.c  |  145 +++
 2 files changed, 1159 insertions(+)
 create mode 100644 drivers/platform/x86/hp/hp-bioscfg/sureadmin-attributes.c
 create mode 100644 drivers/platform/x86/hp/hp-bioscfg/surestart-attributes.c

diff --git a/drivers/platform/x86/hp/hp-bioscfg/sureadmin-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/sureadmin-attributes.c
new file mode 100644
index 000000000000..5ad45cdddad9
--- /dev/null
+++ b/drivers/platform/x86/hp/hp-bioscfg/sureadmin-attributes.c
@@ -0,0 +1,1014 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Functions corresponding to sure admin object type attributes under
+ * BIOS for use with hp-bioscfg driver
+ *
+ *  Copyright (c) 2022 HP Development Company, L.P.
+ */
+
+#include "bioscfg.h"
+
+static int bios_settings_size;
+static int buf_alloc_size;
+static char *bios_settings_buffer;
+
+const char *hp_wmi_classes[] = {
+	"HPBIOS_BIOSString",
+	"HPBIOS_BIOSInteger",
+	"HPBIOS_BIOSEnumeration",
+	"HPBIOS_BIOSOrderedList",
+	"HPBIOS_BIOSPassword"
+};
+
+get_instance_id_for_attribute(string);
+get_instance_id_for_attribute(integer);
+get_instance_id_for_attribute(enumeration);
+get_instance_id_for_attribute(ordered_list);
+
+static ssize_t sure_admin_settings_write(struct file *filp, struct kobject *kobj,
+					 struct bin_attribute *attr,
+					 char *buf, loff_t off, size_t count)
+{
+	int status = 0;
+	char *part = NULL;
+	char *attr_name = NULL;
+	char *attr_value = NULL;
+	int part_len = 0;
+	unsigned short *buffer = NULL;
+	unsigned short *tmpstr = NULL;
+	int buffer_size = (count + strlen(UTF_PREFIX)) * sizeof(unsigned short);
+
+	buffer = kmalloc(buffer_size, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	tmpstr = buffer;
+	part = strsep(&buf, ",");
+	if (!part) {
+		status = -EINVAL;
+		goto exit_settings;
+	}
+	// Save attr_name
+	attr_name = kmalloc(strlen(part) + 1, GFP_KERNEL);
+	if (!attr_name) {
+		status = -EINVAL;
+		goto exit_settings;
+	}
+	strncpy(attr_name, part, strlen(part));
+
+	tmpstr = ascii_to_utf16_unicode(tmpstr, part);
+	part = strsep(&buf, ",");
+	if (!part) {
+		status = -EINVAL;
+		goto exit_settings;
+	}
+
+	part_len = strlen(part);
+
+	/* Add extra buffer space when encountering an empty string */
+	if (!part_len) {
+		buffer_size += sizeof(unsigned short);
+		part_len += sizeof(unsigned short);
+	}
+
+	// Save attr_value
+	attr_value = kmalloc(part_len + 1, GFP_KERNEL);
+	if (!attr_value) {
+		status = -EINVAL;
+		goto exit_settings;
+	}
+	strncpy(attr_value, part, part_len);
+
+	tmpstr = ascii_to_utf16_unicode(tmpstr, part);
+	part = strsep(&buf, ",");
+	if (!part) {
+		status = -EINVAL;
+		goto exit_settings;
+	}
+	part_len = strlen(part) - 1;
+	part[part_len] = '\0';
+
+	if (strncmp(part, BEAM_PREFIX, strlen(BEAM_PREFIX)) == 0) {
+	       /*
+		* BEAM_PREFIX is append to buffer when a signature
+		* is provided and Sure Admin is enabled in BIOS
+		*/
+		// BEAM_PREFIX found, convert part to unicode
+		tmpstr = ascii_to_utf16_unicode(tmpstr, part);
+		// decrease buffer size allocated initially for UTF_PREFIX
+		buffer_size -= strlen(UTF_PREFIX) * sizeof(unsigned short);
+	} else {
+		/*
+		 * UTF-16 prefix is append to the * buffer when a BIOS
+		 * admin password is configured in BIOS
+		 */
+
+		// append UTF_PREFIX to part and then convert it to unicode
+		part = kasprintf(GFP_KERNEL, "%s%s", UTF_PREFIX, part);
+		if (!part)
+			goto exit_settings;
+
+		tmpstr = ascii_to_utf16_unicode(tmpstr, part);
+		kfree(part);
+	}
+
+	part = strsep(&buf, ",");
+	if (part) {
+		status = -EINVAL;
+		goto exit_settings;
+	}
+
+	status = hp_wmi_set_bios_setting(buffer, buffer_size);
+	if (ACPI_FAILURE(status)) {
+		status = -EINVAL;
+		goto exit_settings;
+	}
+
+	if (attr_name == NULL)
+		pr_warn("Name is null\n");
+	if (attr_value == NULL)
+		pr_warn("Value is null\n");
+
+	update_attribute_value(attr_name, attr_value);
+
+
+exit_settings:
+	kfree(buffer);
+	kfree(attr_name);
+	kfree(attr_value);
+
+	if (ACPI_SUCCESS(status))
+		return count;
+
+	return status;
+}
+
+int update_attribute_value(char *attr_name, char *attr_value)
+{
+	int instance = -EIO;
+	int int_val;
+	int ret;
+
+	if (!attr_name || !attr_value)
+		return -EIO;
+
+	/* update value for the attribute */
+	instance = get_instance_id_for_string(attr_name);
+	if (instance >= 0) {
+		strscpy(bioscfg_drv.string_data[instance].current_value,
+			attr_value,
+			sizeof(bioscfg_drv.string_data[instance].current_value));
+
+		/*
+		 * set pending reboot flag depending on
+		 * "RequiresPhysicalPresence" value
+		 */
+		if (bioscfg_drv.string_data[instance].requires_physical_presence)
+			bioscfg_drv.pending_reboot = TRUE;
+		goto exit_update_attribute;
+	}
+
+	instance = get_instance_id_for_integer(attr_name);
+	if (instance >= 0) {
+		ret = kstrtoint(attr_value, 10, &int_val);
+		if (!ret) {
+			bioscfg_drv.integer_data[instance].current_value = int_val;
+			/*
+			 * set pending reboot flag depending on
+			 * "RequiresPhysicalPresence" value
+			 */
+			if (bioscfg_drv.integer_data[instance].requires_physical_presence)
+				bioscfg_drv.pending_reboot = TRUE;
+		}
+
+		goto exit_update_attribute;
+	}
+
+	instance = get_instance_id_for_enumeration(attr_name);
+	if (instance >= 0) {
+		strscpy(bioscfg_drv.enumeration_data[instance].current_value,
+			attr_value,
+			sizeof(bioscfg_drv.enumeration_data[instance].current_value));
+		/*
+		 * set pending reboot flag depending on
+		 * "RequiresPhysicalPresence" value
+		 */
+		if (bioscfg_drv.enumeration_data[instance].requires_physical_presence)
+			bioscfg_drv.pending_reboot = TRUE;
+
+		goto exit_update_attribute;
+	}
+	instance = get_instance_id_for_ordered_list(attr_name);
+	if (instance >= 0) {
+		strscpy(bioscfg_drv.ordered_list_data[instance].current_value,
+			attr_value,
+			sizeof(bioscfg_drv.ordered_list_data[instance].current_value));
+
+		/*
+		 * set pending reboot flag depending on
+		 * "RequiresPhysicalPresence" value
+		 */
+		if (bioscfg_drv.ordered_list_data[instance].requires_physical_presence)
+			bioscfg_drv.pending_reboot = TRUE;
+	}
+
+exit_update_attribute:
+	return instance;
+}
+
+static ssize_t sure_admin_settings_read(struct file *filp, struct kobject *kobj,
+					struct bin_attribute *attr, char *buf,
+					loff_t off, size_t count)
+{
+	ssize_t ret;
+
+	/* clear the buffer when offset is pointing to the last position */
+	if (off >= bios_settings_size && bios_settings_size > 0) {
+		hp_bios_settings_free_buffer();
+		return 0;
+	}
+
+	/* clear the buffer whenever the read starts from the first position */
+	if (off == 0 && bios_settings_size > 0)
+		hp_bios_settings_free_buffer();
+
+	if (bios_settings_size == 0)
+		hp_bios_settings_fill_buffer();
+
+	mutex_lock(&bioscfg_drv.mutex);
+	ret = memory_read_from_buffer(buf, count, &off, bios_settings_buffer,
+				      bios_settings_size);
+	mutex_unlock(&bioscfg_drv.mutex);
+
+	return ret;
+}
+
+HPWMI_BINATTR_RW(sure_admin, settings, 0);
+
+static struct bin_attribute *sure_admin_binattrs[] = {
+	&sure_admin_settings,
+	NULL,
+};
+
+static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
+			 char *buf)
+{
+	return sprintf(buf, "sure-admin\n");
+}
+static struct kobj_attribute sure_admin_type = __ATTR_RO(type);
+
+static ssize_t display_name_language_code_show(struct kobject *kobj,
+					       struct kobj_attribute *attr,
+					       char *buf)
+{
+	return sprintf(buf, "%s\n", LANG_CODE_STR);
+}
+
+static struct kobj_attribute sure_admin_display_langcode =
+		__ATTR_RO(display_name_language_code);
+
+
+static ssize_t display_name_show(struct kobject *kobj,
+				 struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%s\n", SURE_ADMIN_DESC);
+}
+static struct kobj_attribute sure_admin_display_name = __ATTR_RO(display_name);
+
+static struct attribute *sure_admin_attrs[] = {
+	&sure_admin_display_name.attr,
+	&sure_admin_display_langcode.attr,
+	&sure_admin_type.attr,
+	NULL,
+};
+
+static const struct attribute_group sure_admin_attr_group = {
+	.attrs = sure_admin_attrs,
+	.bin_attrs = sure_admin_binattrs,
+};
+
+void exit_sure_admin_attributes(void)
+{
+	sysfs_remove_group(bioscfg_drv.sure_admin_attr_kobj, &sure_admin_attr_group);
+}
+
+int populate_sure_admin_data(struct kobject *attr_name_kobj)
+{
+	bioscfg_drv.sure_admin_attr_kobj = attr_name_kobj;
+	return sysfs_create_group(attr_name_kobj, &sure_admin_attr_group);
+}
+
+int hp_bios_settings_fill_buffer(void)
+{
+	int status = 0;
+	int initial_buffer_size = 20 * PAGE_SIZE;
+
+	mutex_lock(&bioscfg_drv.mutex);
+	bios_settings_buffer = kmalloc(initial_buffer_size, GFP_KERNEL);
+	mutex_unlock(&bioscfg_drv.mutex);
+	if (!bios_settings_buffer)
+		return -ENOMEM;
+
+	mutex_lock(&bioscfg_drv.mutex);
+	buf_alloc_size = ksize(bios_settings_buffer);
+	memset(bios_settings_buffer, 0x00, buf_alloc_size);
+	bios_settings_size = snprintf(bios_settings_buffer,
+					buf_alloc_size, "[\n");
+	mutex_unlock(&bioscfg_drv.mutex);
+
+	status = append_read_settings(HPWMI_STRING_TYPE,
+					   &bios_settings_buffer,
+					   &bios_settings_size,
+					   &buf_alloc_size);
+	if (ACPI_FAILURE(status))
+		pr_err("error 0x%x occurred retrieving string instances\n", status);
+
+	status = append_read_settings(HPWMI_INTEGER_TYPE,
+					   &bios_settings_buffer,
+					   &bios_settings_size,
+					   &buf_alloc_size);
+	if (ACPI_FAILURE(status))
+		pr_err("error 0x%x occurred retrieving integer instances\n", status);
+
+	status = append_read_settings(HPWMI_ENUMERATION_TYPE,
+					   &bios_settings_buffer,
+					   &bios_settings_size,
+					   &buf_alloc_size);
+	if (ACPI_FAILURE(status))
+		pr_err("error 0x%x occurred retrieving enumeration instances\n", status);
+
+	status = append_read_settings(HPWMI_ORDERED_LIST_TYPE,
+					   &bios_settings_buffer,
+					   &bios_settings_size,
+					   &buf_alloc_size);
+	if (ACPI_FAILURE(status))
+		pr_err("error 0x%x occurred retrieving ordered list instances\n", status);
+
+	status = append_read_settings(HPWMI_PASSWORD_TYPE,
+					   &bios_settings_buffer,
+					   &bios_settings_size,
+					   &buf_alloc_size);
+	if (ACPI_FAILURE(status))
+		pr_err("error 0x%x occurred retrieving password list instances\n", status);
+
+	mutex_lock(&bioscfg_drv.mutex);
+	/*
+	 * remove trailing comma
+	 */
+	if (bios_settings_size >= 3) {
+		if (bios_settings_buffer[bios_settings_size - 2] == ',')
+			bios_settings_buffer[bios_settings_size - 2] = ' ';
+	}
+	bios_settings_size = snprintf(bios_settings_buffer,
+					buf_alloc_size, "%s]\n",
+					bios_settings_buffer);
+	mutex_unlock(&bioscfg_drv.mutex);
+
+	return bios_settings_size;
+}
+
+int hp_bios_settings_free_buffer(void)
+{
+	mutex_lock(&bioscfg_drv.mutex);
+	kfree(bios_settings_buffer);
+	bios_settings_size = 0;
+	buf_alloc_size = 0;
+	mutex_unlock(&bioscfg_drv.mutex);
+
+	return 0;
+}
+int hp_bios_settings_realloc_buffer(char **buf, int *buf_size, int *alloc_size)
+{
+	int new_buffer_size;
+	char *new_buf = NULL;
+	int ret = 0;
+
+	if (*buf_size + PAGE_SIZE >= *alloc_size) {
+		new_buffer_size = buf_alloc_size + 2 * PAGE_SIZE;
+
+		mutex_lock(&bioscfg_drv.mutex);
+		new_buf = krealloc(*buf, new_buffer_size, GFP_KERNEL);
+		mutex_unlock(&bioscfg_drv.mutex);
+		if (new_buf) {
+			mutex_lock(&bioscfg_drv.mutex);
+			*buf = new_buf;
+			*alloc_size = ksize(new_buf);
+			mutex_unlock(&bioscfg_drv.mutex);
+		} else {
+			hp_bios_settings_free_buffer();
+			ret = -ENOMEM;
+		}
+	}
+
+	return ret;
+}
+
+int append_read_settings(enum hp_wmi_data_type type, char **buf,
+			 int *buf_size, int *alloc_size)
+{
+	int ret = 0;
+	int status = 0;
+	int instance = 0;
+	int instance_count = 0;
+
+	switch (type) {
+	case HPWMI_STRING_TYPE:
+		instance_count = bioscfg_drv.string_instances_count;
+		break;
+	case HPWMI_INTEGER_TYPE:
+		instance_count = bioscfg_drv.integer_instances_count;
+		break;
+	case HPWMI_ENUMERATION_TYPE:
+		instance_count = bioscfg_drv.enumeration_instances_count;
+		break;
+	case HPWMI_ORDERED_LIST_TYPE:
+		instance_count = bioscfg_drv.ordered_list_instances_count;
+		break;
+	case HPWMI_PASSWORD_TYPE:
+		instance_count = bioscfg_drv.password_instances_count;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Query all the instances
+	 */
+	for (instance = 0; instance < instance_count; instance++) {
+		mutex_lock(&bioscfg_drv.mutex);
+		status = append_read_attributes(buf, *alloc_size,
+						     instance, type);
+		if (status > 0)
+			*buf_size = status;
+
+		mutex_unlock(&bioscfg_drv.mutex);
+
+		ret = hp_bios_settings_realloc_buffer(buf, buf_size,
+						      alloc_size);
+	}
+	return ret;
+}
+
+int append_read_attributes(char **buf, int alloc_size,
+			   int instance, enum hp_wmi_data_type type)
+{
+	int status = 0;
+
+	switch (type) {
+	case HPWMI_STRING_TYPE:
+		status = append_read_string_attributes(*buf, alloc_size,
+						       instance, type);
+		break;
+	case HPWMI_INTEGER_TYPE:
+		status = append_read_integer_attributes(*buf, alloc_size,
+							instance, type);
+		break;
+	case HPWMI_ENUMERATION_TYPE:
+		status = append_read_enumeration_attributes(*buf,
+							    alloc_size,
+							    instance, type);
+		break;
+	case HPWMI_ORDERED_LIST_TYPE:
+		status = append_read_ordered_list_attributes(*buf,
+							     alloc_size,
+							     instance, type);
+		break;
+	case HPWMI_PASSWORD_TYPE:
+		status = append_read_password_attributes(*buf,
+							 alloc_size,
+							 instance, type);
+		break;
+	default:
+		status = -EINVAL;
+		break;
+	}
+	return status;
+}
+
+
+int append_read_string_attributes(char *buf, int alloc_size,
+				  int instance,
+				  enum hp_wmi_data_type type)
+{
+	int buf_size;
+	char *part_tmp = NULL;
+	char *part = NULL;
+
+	if (type >= ARRAY_SIZE(hp_wmi_classes) || !buf)
+		return -EINVAL;
+
+	buf_size = snprintf(buf, alloc_size, "%s{\n", buf);
+	buf_size = snprintf(buf, alloc_size, "%s\t\"Class\": \"%s\",\n",
+			    buf, hp_wmi_classes[type]);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Name\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.string_data[instance].display_name);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Value\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.string_data[instance].current_value);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Path\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.string_data[instance].path);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"IsReadOnly\": %d,\n",
+			    buf,
+			    bioscfg_drv.string_data[instance].is_readonly);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"DisplayInUI\": %d,\n",
+			    buf,
+			    bioscfg_drv.string_data[instance].display_in_ui);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"RequiresPhysicalPresence\": %d,\n",
+			    buf,
+			    bioscfg_drv.string_data[instance].requires_physical_presence);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Sequence\": %d,\n",
+			    buf,
+			    bioscfg_drv.string_data[instance].sequence);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"PrerequisiteSize\": %d,\n",
+			    buf,
+			    bioscfg_drv.string_data[instance].prerequisitesize);
+
+	buf_size = snprintf(buf, alloc_size, "%s\t\"Prerequisites\": [\n", buf);
+
+	if (bioscfg_drv.string_data[instance].prerequisitesize) {
+		part_tmp = kstrdup(bioscfg_drv.string_data[instance].prerequisites,
+				   GFP_KERNEL);
+		part = strsep(&part_tmp, ";");
+		while (part) {
+			buf_size = snprintf(buf, alloc_size, "%s\t\t\"%s\"", buf, part);
+			part = strsep(&part_tmp, ";");
+			if (part)
+				buf_size = snprintf(buf, alloc_size, "%s,\n", buf);
+			else
+				buf_size = snprintf(buf, alloc_size, "%s\n", buf);
+		}
+		kfree(part_tmp);
+		part_tmp = NULL;
+	}
+	buf_size = snprintf(buf, alloc_size, "%s\t],\n", buf);
+
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"SecurityLevel\": %d,\n",
+			    buf,
+			    bioscfg_drv.string_data[instance].security_level);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"MinLength\": %d,\n",
+			    buf,
+			    bioscfg_drv.string_data[instance].min_length);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"MaxLength\": %d\n",
+			    buf,
+			    bioscfg_drv.string_data[instance].max_length);
+
+	return snprintf(buf, alloc_size, "%s},\n", buf);
+}
+
+
+int append_read_integer_attributes(char *buf, int alloc_size,
+				   int instance,
+				   enum hp_wmi_data_type type)
+{
+	int buf_size;
+	char *part_tmp = NULL;
+	char *part = NULL;
+
+	if (type >= ARRAY_SIZE(hp_wmi_classes) || !buf)
+		return -EINVAL;
+
+	buf_size = snprintf(buf, alloc_size, "%s{\n", buf);
+	buf_size = snprintf(buf, alloc_size, "%s\t\"Class\": \"%s\",\n",
+			    buf, hp_wmi_classes[type]);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Name\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].display_name);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Value\": \"%d\",\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].current_value);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Path\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].path);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"IsReadOnly\": %d,\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].is_readonly);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"DisplayInUI\": %d,\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].display_in_ui);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"RequiresPhysicalPresence\": %d,\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].requires_physical_presence);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Sequence\": %d,\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].sequence);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"PrerequisiteSize\": %d,\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].prerequisitesize);
+
+	buf_size = snprintf(buf, alloc_size, "%s\t\"Prerequisites\": [\n", buf);
+
+	if (bioscfg_drv.integer_data[instance].prerequisitesize) {
+		part_tmp = kstrdup(bioscfg_drv.integer_data[instance].prerequisites,
+				   GFP_KERNEL);
+		part = strsep(&part_tmp, ";");
+		while (part) {
+			buf_size = snprintf(buf, alloc_size, "%s\t\t\"%s\"", buf, part);
+			part = strsep(&part_tmp, ";");
+			if (part)
+				buf_size = snprintf(buf, alloc_size, "%s,\n", buf);
+			else
+				buf_size = snprintf(buf, alloc_size, "%s\n", buf);
+		}
+		kfree(part_tmp);
+		part_tmp = NULL;
+	}
+	buf_size = snprintf(buf, alloc_size, "%s\t],\n", buf);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"SecurityLevel\": %d,\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].security_level);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"LowerBound\": %d,\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].lower_bound);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"UpperBound\": %d,\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].upper_bound);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"IntValue\": %d\n",
+			    buf,
+			    bioscfg_drv.integer_data[instance].scalar_increment);
+
+	return snprintf(buf, alloc_size, "%s},\n", buf);
+}
+
+int append_read_enumeration_attributes(char *buf, int alloc_size,
+				       int instance,
+				       enum hp_wmi_data_type type)
+{
+	int buf_size;
+	char *part_tmp = NULL;
+	char *part = NULL;
+
+	if (type >= ARRAY_SIZE(hp_wmi_classes) || !buf)
+		return -EINVAL;
+
+	buf_size = snprintf(buf, alloc_size, "%s{\n", buf);
+	buf_size = snprintf(buf, alloc_size, "%s\t\"Class\": \"%s\",\n",
+			    buf, hp_wmi_classes[type]);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Name\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.enumeration_data[instance].display_name);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Path\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.enumeration_data[instance].path);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"IsReadOnly\": %d,\n",
+			    buf,
+			    bioscfg_drv.enumeration_data[instance].is_readonly);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"DisplayInUI\": %d,\n",
+			    buf,
+			    bioscfg_drv.enumeration_data[instance].display_in_ui);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"RequiresPhysicalPresence\": %d,\n",
+			    buf,
+			    bioscfg_drv.enumeration_data[instance].requires_physical_presence);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Sequence\": %d,\n",
+			    buf,
+			    bioscfg_drv.enumeration_data[instance].sequence);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"PrerequisiteSize\": %d,\n",
+			    buf,
+			    bioscfg_drv.enumeration_data[instance].prerequisitesize);
+
+	buf_size = snprintf(buf, alloc_size, "%s\t\"Prerequisites\": [\n", buf);
+
+	if (bioscfg_drv.enumeration_data[instance].prerequisitesize) {
+		part_tmp = kstrdup(bioscfg_drv.enumeration_data[instance].prerequisites,
+				   GFP_KERNEL);
+		part = strsep(&part_tmp, ";");
+		while (part) {
+			buf_size = snprintf(buf, alloc_size, "%s\t\t\"%s\"", buf, part);
+			part = strsep(&part_tmp, ";");
+			if (part)
+				buf_size = snprintf(buf, alloc_size, "%s,\n", buf);
+			else
+				buf_size = snprintf(buf, alloc_size, "%s\n", buf);
+		}
+		kfree(part_tmp);
+		part_tmp = NULL;
+	}
+	buf_size = snprintf(buf, alloc_size, "%s\t],\n", buf);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"SecurityLevel\": %d,\n",
+			    buf,
+			    bioscfg_drv.enumeration_data[instance].security_level);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Value\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.enumeration_data[instance].current_value);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Size\": %d,\n",
+			    buf,
+			    bioscfg_drv.enumeration_data[instance].size);
+
+	buf_size = snprintf(buf, alloc_size, "%s\t\"PossibleValues\": [\n", buf);
+
+	if (bioscfg_drv.enumeration_data[instance].size) {
+		part_tmp = kstrdup(bioscfg_drv.enumeration_data[instance].possible_values,
+				   GFP_KERNEL);
+		part = strsep(&part_tmp, ";");
+		while (part) {
+			buf_size = snprintf(buf, alloc_size, "%s\t\t\"%s\"", buf, part);
+			part = strsep(&part_tmp, ";");
+			if (part)
+				buf_size = snprintf(buf, alloc_size, "%s,\n", buf);
+			else
+				buf_size = snprintf(buf, alloc_size, "%s\n", buf);
+		}
+		kfree(part_tmp);
+		part_tmp = NULL;
+	}
+	buf_size = snprintf(buf, alloc_size, "%s\t]\n", buf);
+
+	return snprintf(buf, alloc_size, "%s},\n", buf);
+}
+
+int append_read_ordered_list_attributes(char *buf, int alloc_size,
+					int instance,
+					enum hp_wmi_data_type type)
+{
+	int buf_size;
+	char *part_tmp = NULL;
+	char *part = NULL;
+
+	if (type >= ARRAY_SIZE(hp_wmi_classes) || !buf)
+		return -EINVAL;
+
+	buf_size = snprintf(buf, alloc_size, "%s{\n", buf);
+	buf_size = snprintf(buf, alloc_size, "%s\t\"Class\": \"%s\",\n",
+			    buf, hp_wmi_classes[type]);
+
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Name\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.ordered_list_data[instance].display_name);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Value\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.ordered_list_data[instance].current_value);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Path\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.ordered_list_data[instance].path);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"IsReadOnly\": %d,\n",
+			    buf,
+			    bioscfg_drv.ordered_list_data[instance].is_readonly);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"DisplayInUI\": %d,\n",
+			    buf,
+			    bioscfg_drv.ordered_list_data[instance].display_in_ui);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"RequiresPhysicalPresence\": %d,\n",
+			    buf,
+			    bioscfg_drv.ordered_list_data[instance].requires_physical_presence);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Sequence\": %d,\n",
+			    buf,
+			    bioscfg_drv.ordered_list_data[instance].sequence);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"PrerequisiteSize\": %d,\n",
+			    buf,
+			    bioscfg_drv.ordered_list_data[instance].prerequisitesize);
+
+	buf_size = snprintf(buf, alloc_size, "%s\t\"Prerequisites\": [\n", buf);
+
+	if (bioscfg_drv.ordered_list_data[instance].prerequisitesize) {
+		part_tmp = kstrdup(bioscfg_drv.ordered_list_data[instance].prerequisites,
+				   GFP_KERNEL);
+		part = strsep(&part_tmp, ";");
+		while (part) {
+			buf_size = snprintf(buf, alloc_size, "%s\t\t\"%s\"", buf, part);
+			part = strsep(&part_tmp, ";");
+			if (part)
+				buf_size = snprintf(buf, alloc_size, "%s,\n", buf);
+			else
+				buf_size = snprintf(buf, alloc_size, "%s\n", buf);
+		}
+		kfree(part_tmp);
+		part_tmp = NULL;
+	}
+	buf_size = snprintf(buf, alloc_size, "%s\t],\n", buf);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"SecurityLevel\": %d,\n",
+			    buf,
+			    bioscfg_drv.ordered_list_data[instance].security_level);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Size\": %d,\n",
+			    buf,
+			    bioscfg_drv.ordered_list_data[instance].size);
+
+	buf_size = snprintf(buf, alloc_size, "%s\t\"Elements\": [\n", buf);
+
+	if (bioscfg_drv.ordered_list_data[instance].size) {
+		part_tmp = kstrdup(bioscfg_drv.ordered_list_data[instance].elements,
+				   GFP_KERNEL);
+		part = strsep(&part_tmp, ";");
+		while (part) {
+			buf_size = snprintf(buf, alloc_size, "%s\t\t\"%s\"", buf, part);
+			part = strsep(&part_tmp, ";");
+			if (part)
+				buf_size = snprintf(buf, alloc_size, "%s,\n", buf);
+			else
+				buf_size = snprintf(buf, alloc_size, "%s\n", buf);
+		}
+		kfree(part_tmp);
+		part_tmp = NULL;
+	}
+	buf_size = snprintf(buf, alloc_size, "%s\t]\n", buf);
+
+	return snprintf(buf, alloc_size, "%s},\n", buf);
+}
+
+
+int append_read_password_attributes(char *buf, int alloc_size,
+				    int instance,
+				    enum hp_wmi_data_type type)
+{
+	int buf_size;
+	char *part_tmp = NULL;
+	char *part = NULL;
+
+	if (type >= ARRAY_SIZE(hp_wmi_classes) || !buf)
+		return -EINVAL;
+
+	buf_size = snprintf(buf, alloc_size, "%s{\n", buf);
+	buf_size = snprintf(buf, alloc_size, "%s\t\"Class\": \"%s\",\n",
+			    buf, hp_wmi_classes[type]);
+
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Name\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].display_name);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Value\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].current_password);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Path\": \"%s\",\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].path);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"IsReadOnly\": %d,\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].is_readonly);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"DisplayInUI\": %d,\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].display_in_ui);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"RequiresPhysicalPresence\": %d,\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].requires_physical_presence);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Sequence\": %d,\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].sequence);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"PrerequisiteSize\": %d,\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].prerequisitesize);
+
+	buf_size = snprintf(buf, alloc_size, "%s\t\"Prerequisites\": [\n", buf);
+
+	if (bioscfg_drv.password_data[instance].prerequisitesize) {
+		part_tmp = kstrdup(bioscfg_drv.password_data[instance].prerequisites,
+				   GFP_KERNEL);
+		part = strsep(&part_tmp, ";");
+		while (part) {
+			buf_size = snprintf(buf, alloc_size, "%s\t\t\"%s\"", buf, part);
+			part = strsep(&part_tmp, ";");
+			if (part)
+				buf_size = snprintf(buf, alloc_size, "%s,\n", buf);
+			else
+				buf_size = snprintf(buf, alloc_size, "%s\n", buf);
+		}
+		kfree(part_tmp);
+		part_tmp = NULL;
+	}
+	buf_size = snprintf(buf, alloc_size, "%s\t],\n", buf);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"SecurityLevel\": %d,\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].security_level);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"MinLength\": %d,\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].min_password_length);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"MaxLength\": %d,\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].max_password_length);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"Size\": %d,\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].encoding_size);
+
+	buf_size = snprintf(buf, alloc_size, "%s\t\"SupportedEncoding\": [\n", buf);
+
+	if (bioscfg_drv.password_data[instance].encoding_size) {
+		part_tmp = kstrdup(bioscfg_drv.password_data[instance].supported_encoding,
+				   GFP_KERNEL);
+		part = strsep(&part_tmp, ";");
+		while (part) {
+			buf_size = snprintf(buf, alloc_size, "%s\t\t\"%s\"", buf, part);
+			part = strsep(&part_tmp, ";");
+			if (part)
+				buf_size = snprintf(buf, alloc_size, "%s,\n", buf);
+			else
+				buf_size = snprintf(buf, alloc_size, "%s\n", buf);
+		}
+		kfree(part_tmp);
+		part_tmp = NULL;
+	}
+	buf_size = snprintf(buf, alloc_size, "%s\t],\n", buf);
+
+	buf_size = snprintf(buf, alloc_size,
+			    "%s\t\"IsSet\": %d\n",
+			    buf,
+			    bioscfg_drv.password_data[instance].is_enabled);
+
+	return snprintf(buf, alloc_size, "%s},\n", buf);
+}
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
index 000000000000..41c5a549f2ca
--- /dev/null
+++ b/drivers/platform/x86/hp/hp-bioscfg/surestart-attributes.c
@@ -0,0 +1,145 @@
+// 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 <asm-generic/posix_types.h>
+
+#define LOG_MAX_ENTRIES	254
+#define LOG_ENTRY_SIZE	16
+
+/*
+ * audit_log_entry_count_show - Reports the number of
+ *				existing audit log entries available
+ *				to be read
+ *
+ * @kobj:  Pointer to a kernel object of things that show up as directory
+ *	   in the sysfs filesystem.
+ * @attr:  Pointer to list of attributes for the operation
+ * @buf:   Pointer to buffer
+ *
+ * Returns number of existing audit log entries available to be read,
+ *         audit log entry size, and maximum number of entries
+ *         supported. Otherwise, an HP WMI query specific error code
+ *         (which is negative)
+ *
+ *         [No of entries],[log entry size],[Max number of entries supported]
+ */
+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, 0, sizeof(count));
+	if (ret < 0)
+		return ret;
+
+	return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n", count, LOG_ENTRY_SIZE, LOG_MAX_ENTRIES);
+}
+
+/*
+ * audit_log_entries_show() - Return all entries found in log file
+ *
+ * @kobj:  Pointer to a kernel object of things that show up as
+ *	   directory in the sysfs filesystem.
+ * @attr:  Pointer to list of attributes for the operation
+ * @buf:   Pointer to buffer
+ *
+ * Returns number of bytes needed to read all audit logs entries to be read.
+ *         Otherwise, an HP WMI query specific error code (which is negative)
+ *	   -EFAULT if the audit logs size exceeds 4KB
+ *
+ */
+static ssize_t audit_log_entries_show(struct kobject *kobj,
+				      struct kobj_attribute *attr, char *buf)
+{
+	int ret;
+	int i;
+	u32 count = 0;
+
+	// Get the number of event logs
+	ret = hp_wmi_perform_query(HPWMI_SURESTART_GET_LOG_COUNT, HPWMI_SURESTART,
+				   &count, 1, 4);
+
+	/*
+	 * The show() api will not work if the audit logs ever go
+	 *  beyond 4KB
+	 */
+	if (count * LOG_ENTRY_SIZE > PAGE_SIZE)
+		return -EFAULT;
+
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * We are guaranteed the buffer is 4KB so today all the event
+	 * logs will fit
+	 */
+	for (i = 0; ((i < count) & (ret >= 0)); i++) {
+		*buf = (i + 1);
+		ret = hp_wmi_perform_query(HPWMI_SURESTART_GET_LOG,
+					   HPWMI_SURESTART,
+					   buf, 1, 128);
+		if (ret >= 0)
+			buf += LOG_ENTRY_SIZE;
+	}
+	return (count * LOG_ENTRY_SIZE);
+}
+
+static struct kobj_attribute sure_start_audit_log_entry_count = __ATTR_RO(audit_log_entry_count);
+struct kobj_attribute sure_start_audit_log_entries = __ATTR_RO(audit_log_entries);
+
+static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
+			 char *buf)
+{
+	return sprintf(buf, "sure-start\n");
+}
+static struct kobj_attribute sure_start_type = __ATTR_RO(type);
+
+static ssize_t display_name_language_code_show(struct kobject *kobj,
+					       struct kobj_attribute *attr,
+					       char *buf)
+{
+	return sprintf(buf, "%s\n", LANG_CODE_STR);
+}
+
+static struct kobj_attribute sure_start_display_langcode =
+		__ATTR_RO(display_name_language_code);
+
+
+static ssize_t display_name_show(struct kobject *kobj,
+				 struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%s\n", SURE_START_DESC);
+}
+static struct kobj_attribute sure_start_display_name = __ATTR_RO(display_name);
+
+static struct attribute *sure_start_attrs[] = {
+	&sure_start_display_name.attr,
+	&sure_start_display_langcode.attr,
+	&sure_start_audit_log_entry_count.attr,
+	&sure_start_audit_log_entries.attr,
+	&sure_start_type.attr,
+	NULL,
+};
+
+static const struct attribute_group sure_start_attr_group = {
+	.attrs = sure_start_attrs,
+};
+
+void exit_sure_start_attributes(void)
+{
+	sysfs_remove_group(bioscfg_drv.sure_start_attr_kobj, &sure_start_attr_group);
+}
+
+int 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);
+}
-- 
2.34.1




[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux