All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 2/2] dmi-id: add dmi/id/oem group for exporting oem strings to sysfs
@ 2016-07-29  9:29 Allen Hung
  0 siblings, 0 replies; only message in thread
From: Allen Hung @ 2016-07-29  9:29 UTC (permalink / raw)
  To: Jean Delvare, linux-kernel; +Cc: Mario Limonciello, Allen Hung

The oem strings in DMI system identification information of the BIOS have
been parsed and stored as dmi devices in dmi_scan.c but they are not
exported to userspace via sysfs.

The patch intends to export oem strings to sysfs device /sys/class/dmi/id.
As the number of oem strings are dynamic, a group "oem" is added to the
device and the strings will be added to the group as string1, string2, ...,
and stringN.

Signed-off-by: Allen Hung <allen_hung@dell.com>
---
 drivers/firmware/dmi-id.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c
index 44c0139..503b635 100644
--- a/drivers/firmware/dmi-id.c
+++ b/drivers/firmware/dmi-id.c
@@ -58,6 +58,44 @@ DEFINE_DMI_ATTR_WITH_SHOW(chassis_version,	0444, DMI_CHASSIS_VERSION);
 DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial,	0400, DMI_CHASSIS_SERIAL);
 DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag,	0444, DMI_CHASSIS_ASSET_TAG);
 
+static struct attribute *dmi_oem_attrs[] = {
+	NULL,
+};
+
+static const char oem_group[] = "oem";
+
+static struct attribute_group dmi_oem_attr_group = {
+	.attrs = dmi_oem_attrs,
+	.name  = oem_group,
+};
+
+static LIST_HEAD(dmi_oem_attrs_list);
+
+struct dmi_oem_attribute {
+	struct device_attribute dev_attr;
+	const char *oem_string;
+	char buf[32];
+	bool is_added:1;
+	struct list_head list;
+};
+
+#define to_dmi_oem_attr(_dev_attr) \
+	container_of(_dev_attr, struct dmi_oem_attribute, dev_attr)
+
+static ssize_t sys_dmi_oem_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *page)
+{
+	struct dmi_oem_attribute *oa = to_dmi_oem_attr(attr);
+	ssize_t len;
+
+	strlcpy(page, oa->oem_string, PAGE_SIZE-1);
+	len = strlen(page);
+	page[len++] = '\n';
+	page[len] = 0;
+	return len;
+}
+
 static void ascii_filter(char *d, const char *s)
 {
 	/* Filter out characters we don't want to see in the modalias string */
@@ -204,6 +242,69 @@ static void __init dmi_id_init_attr_table(void)
 	sys_dmi_attributes[i++] = &sys_dmi_modalias_attr.attr;
 }
 
+static int __init dmi_id_init_oem_attr_group(void)
+{
+	int i, ret;
+	const struct dmi_device *dev;
+	struct dmi_oem_attribute *oa, *tmp;
+	struct device_attribute dev_attr_tmpl =
+		__ATTR(, 0444, sys_dmi_oem_show, NULL);
+
+	ret = sysfs_create_group(&dmi_dev->kobj, &dmi_oem_attr_group);
+	if (ret)
+		return ret;
+
+	/* All devices with type=DMI_DEV_TYPE_OEM_STRING will be found in
+	 * the reverse order of what they were parsed in dmi_scan.c. However,
+	 * we do want to expose the OEM strings to sysfs in the same order as
+	 * what they were originally parsed. A linked list with 2-pass method
+	 * is used here to reverse the reserved order.
+	 *
+	 * Pass 1: find out all "OEM string" devices and add each "oem string"
+	 * to a linked list.
+	 */
+	dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, NULL);
+	while (dev)  {
+		oa = kzalloc(sizeof(*oa), GFP_KERNEL);
+		if (!oa) {
+			ret = -ENOMEM;
+			goto failed;
+		}
+		oa->dev_attr = dev_attr_tmpl;
+		oa->oem_string = dev->name;
+		list_add(&oa->list, &dmi_oem_attrs_list);
+		dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev);
+	}
+
+	/* Pass 2: traverse the list and add each string as a file to "oem"
+	 * group
+	 */
+	i = 0;
+	list_for_each_entry(oa, &dmi_oem_attrs_list, list) {
+		snprintf(oa->buf, sizeof(oa->buf), "string%d", ++i);
+		oa->dev_attr.attr.name = oa->buf;
+		ret = sysfs_add_file_to_group(
+			&dmi_dev->kobj, &oa->dev_attr.attr, oem_group);
+		if (ret)
+			goto failed;
+		oa->is_added = 1;
+	}
+
+	return 0;
+
+failed:
+	list_for_each_entry_safe(oa, tmp, &dmi_oem_attrs_list, list) {
+		if (oa->is_added)
+			sysfs_remove_file_from_group(
+				&dmi_dev->kobj,	&oa->dev_attr.attr, oem_group);
+		list_del(&oa->list);
+		kfree(oa);
+	}
+	sysfs_remove_group(&dmi_dev->kobj, &dmi_oem_attr_group);
+
+	return ret;
+}
+
 static int __init dmi_id_init(void)
 {
 	int ret;
@@ -231,8 +332,15 @@ static int __init dmi_id_init(void)
 	if (ret)
 		goto fail_put_dmi_dev;
 
+	ret = dmi_id_init_oem_attr_group();
+	if (ret)
+		goto fail_dev_unregister;
+
 	return 0;
 
+fail_dev_unregister:
+	device_unregister(dmi_dev);
+
 fail_put_dmi_dev:
 	put_device(dmi_dev);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2016-07-29  9:29 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-29  9:29 [PATCH v2 2/2] dmi-id: add dmi/id/oem group for exporting oem strings to sysfs Allen Hung

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.