public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Michael Brown <Michael_E_Brown@Dell.com>
To: Greg KH <greg@kroah.com>
Cc: akpm@osdl.org, linux-kernel@vger.kernel.org
Subject: Re: [BK PATCH] add SMBIOS tables to sysfs -- UPDATED
Date: Tue, 27 Apr 2004 23:41:08 -0500	[thread overview]
Message-ID: <1083127267.1195.2848.camel@debian> (raw)
In-Reply-To: <20040428033020.GA14078@kroah.com>

[-- Attachment #1: Type: text/plain, Size: 379 bytes --]

On Tue, 2004-04-27 at 22:30, Greg KH wrote:
> > +	snprintf(sdev->kobj.name, 7, "smbios" );
> 
> Try using kobject_set_name() instead, it will do the proper thing if the
> string is bigger than the base kobj.name field.

Updated per Greg's comments. One other change, I fixed up a cut and
paste error in the copyright line, no code affected.

built and run tested ok.
--
Michael


[-- Attachment #2: Type: text/x-patch, Size: 10978 bytes --]

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/04/27 23:29:00-05:00 michael_e_brown@meb-laptop.michaels-house.net 
#   Add driver to present SMBIOS data in sysfs.
# 
# drivers/firmware/smbios.h
#   2004/04/27 23:26:57-05:00 michael_e_brown@meb-laptop.michaels-house.net +53 -0
# 
# drivers/firmware/smbios.h
#   2004/04/27 23:26:57-05:00 michael_e_brown@meb-laptop.michaels-house.net +0 -0
#   BitKeeper file /home/michael_e_brown/kernel/bk/subtrees/smbios-driver-work-fb/drivers/firmware/smbios.h
# 
# drivers/firmware/smbios.c
#   2004/04/27 23:26:56-05:00 michael_e_brown@meb-laptop.michaels-house.net +266 -0
# 
# drivers/firmware/smbios.c
#   2004/04/27 23:26:56-05:00 michael_e_brown@meb-laptop.michaels-house.net +0 -0
#   BitKeeper file /home/michael_e_brown/kernel/bk/subtrees/smbios-driver-work-fb/drivers/firmware/smbios.c
# 
# drivers/firmware/Makefile
#   2004/04/27 23:26:56-05:00 michael_e_brown@meb-laptop.michaels-house.net +1 -0
#   add SMBIOS sysfs driver to build system
# 
# drivers/firmware/Kconfig
#   2004/04/27 23:26:56-05:00 michael_e_brown@meb-laptop.michaels-house.net +8 -0
#   Add SMBIOS sysfs config option
# 
diff -Nru a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
--- a/drivers/firmware/Kconfig	Tue Apr 27 23:30:02 2004
+++ b/drivers/firmware/Kconfig	Tue Apr 27 23:30:02 2004
@@ -34,4 +34,12 @@
 	  Subsequent efibootmgr releases may be found at:
 	  http://linux.dell.com/efibootmgr
 
+config SMBIOS
+	tristate "BIOS SMBIOS table access driver."
+	help
+	  Say Y or M here if you want to enable access to the SMBIOS table
+	  via driverfs. It exposes /sys/firmware/smbios/ subdirectory tree
+	  containing a binary dump of the SMBIOS table header as well as the SMBIOS
+	  table.
+
 endmenu
diff -Nru a/drivers/firmware/Makefile b/drivers/firmware/Makefile
--- a/drivers/firmware/Makefile	Tue Apr 27 23:30:02 2004
+++ b/drivers/firmware/Makefile	Tue Apr 27 23:30:02 2004
@@ -3,3 +3,4 @@
 #
 obj-$(CONFIG_EDD)             	+= edd.o
 obj-$(CONFIG_EFI_VARS)		+= efivars.o
+obj-$(CONFIG_SMBIOS)            += smbios.o
diff -Nru a/drivers/firmware/smbios.c b/drivers/firmware/smbios.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/firmware/smbios.c	Tue Apr 27 23:30:02 2004
@@ -0,0 +1,266 @@
+/*
+ * linux/drivers/firmware/smbios.c
+ *  Copyright (C) 2004 Dell Inc.
+ *  by Michael Brown <Michael_E_Brown@dell.com>
+ *  vim:noet:ts=8:sw=8:filetype=c:textwidth=80:
+ *
+ * BIOS SMBIOS Table access
+ * conformant to DMTF SMBIOS definition
+ *   at http://www.dmtf.org/standards/smbios
+ *
+ * This code takes information provided by SMBIOS tables
+ * and presents it in sysfs as:
+ *    /sys/firmware/smbios/smbios
+ *				|--> /table_entry_point
+ *				|--> /table
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "smbios.h"
+
+MODULE_AUTHOR("Michael Brown <Michael_E_Brown@Dell.com>");
+MODULE_DESCRIPTION("sysfs interface to SMBIOS information");
+MODULE_LICENSE("GPL");
+
+#define SMBIOS_VERSION "1.0 2004-04-19"
+
+struct smbios_device {
+	struct smbios_table_entry_point table_eps;
+	unsigned int smbios_table_real_length;
+	struct kobject kobj;
+};
+
+/* there shall be only one */
+static struct smbios_device the_smbios_device;
+
+#define to_smbios_device(obj) container_of(obj,struct smbios_device,kobj)
+
+/* don't currently have any "normal" attributes, so we don't need a way to
+ * show them. */
+static struct sysfs_ops smbios_attr_ops = { };
+
+static __init int
+checksum_eps(struct smbios_table_entry_point *table_eps)
+{
+	u8 *p = (u8 *)table_eps;
+	u8 checksum = 0;
+	int i=0;
+	for (i=0; i < table_eps->eps_length && i < sizeof(*table_eps); ++i) {
+		checksum += p[i];
+	}
+	return( checksum == 0 );
+}
+
+static __init int
+find_table_entry_point(struct smbios_device *sdev)
+{
+	struct smbios_table_entry_point *table_eps = &(sdev->table_eps);
+	u32 fp = 0xF0000;
+	while (fp < 0xFFFFF) {
+		isa_memcpy_fromio(table_eps, fp, sizeof(*table_eps));
+		if (memcmp(table_eps->anchor, "_SM_", 4)==0 &&
+					checksum_eps(table_eps)) {
+			return 0;
+		}
+		fp += 16;
+	}
+
+	printk(KERN_INFO "SMBIOS table entry point not found in "
+			"0xF0000 - 0xFFFFF\n");
+	return -ENODEV;
+}
+
+static __init int
+find_table_max_address(struct smbios_device *sdev)
+{
+	/* break out on one of three conditions:
+	 *   -- hit table_eps.table_length
+	 *   -- hit number of items that table claims we have
+	 *   -- hit structure type 127
+	 */
+
+	u8 *buf = ioremap(sdev->table_eps.table_address,
+			sdev->table_eps.table_length);
+	u8 *ptr = buf;
+	int count = 0, keep_going = 1;
+	int max_count = sdev->table_eps.table_num_structs;
+	int max_length = sdev->table_eps.table_length;
+	while(keep_going && ((ptr - buf) <= max_length) && count < max_count){
+		if( ptr[0] == 0x7F )   /* ptr[0] is type */
+			keep_going = 0;
+
+		ptr += ptr[1]; /* ptr[1] is length, skip structure */
+		/* skip strings at end of structure */
+		while((ptr-buf) < max_length && (ptr[0] || ptr[1]))
+			++ptr;
+
+		/* string area ends in double-null. skip it. */
+		ptr += 2;
+		++count;
+	}
+	sdev->smbios_table_real_length = (ptr - buf);
+	iounmap(buf);
+
+	if( count != max_count )
+		printk(KERN_INFO "Warning: SMBIOS table structure count"
+				" does not match count specified in the"
+				" table entry point.\n"
+				" Table entry point count: %d\n"
+				" Actual count: %d\n",
+				max_count, count );
+
+	if(keep_going != 0)
+		printk(KERN_INFO "Warning: SMBIOS table does not end with a"
+				" structure type 127. This may indicate a"
+				" truncated table.");
+
+	if(sdev->smbios_table_real_length != max_length)
+		printk(KERN_INFO "Warning: BIOS specified SMBIOS table length"
+				" does not match calculated length.\n"
+				" BIOS specified: %d\n"
+				" calculated length: %d\n",
+				max_length, sdev->smbios_table_real_length);
+
+	return sdev->smbios_table_real_length;
+}
+
+static ssize_t
+smbios_read_table_entry_point(struct kobject *kobj, char *buffer,
+				loff_t pos, size_t size)
+{
+	struct smbios_device *sdev = to_smbios_device(kobj);
+	const char *p = (const char *)&(sdev->table_eps);
+	unsigned int count =
+		size > sizeof(sdev->table_eps) ?
+			sizeof(sdev->table_eps) : size;
+	memcpy( buffer, p, count );
+	return count;
+}
+
+static ssize_t
+smbios_read_table(struct kobject *kobj, char *buffer,
+				loff_t pos, size_t size)
+{
+	struct smbios_device *sdev = to_smbios_device(kobj);
+	u8 *buf;
+	unsigned int count = sdev->smbios_table_real_length - pos;
+	int i = 0;
+	count = count < size ? count : size;
+
+	if (pos > sdev->smbios_table_real_length)
+		return 0;
+
+	buf = ioremap(sdev->table_eps.table_address, sdev->smbios_table_real_length);
+	if (buf == NULL)
+		return -ENXIO;
+
+	/* memcpy( buffer, buf+pos, count ); */
+	for (i = 0; i < count; ++i) {
+		buffer[i] = readb( buf+pos+i );
+	}
+
+	iounmap(buf);
+
+	return count;
+}
+
+static struct bin_attribute tep_attr = {
+	.attr = {.name = "table_entry_point", .owner = THIS_MODULE, .mode = 0444},
+	.size = sizeof(struct smbios_table_entry_point),
+	.read = smbios_read_table_entry_point,
+	/* not writeable */
+};
+
+static struct bin_attribute table_attr = {
+	.attr = { .name = "table", .owner = THIS_MODULE, .mode = 0444 },
+	/* size set later, we don't know it here. */
+	.read = smbios_read_table,
+	/* not writeable */
+};
+
+/* no default attributes yet. */
+static struct attribute * def_attrs[] = { NULL, };
+
+static struct kobj_type ktype_smbios = {
+	.sysfs_ops	= &smbios_attr_ops,
+	.default_attrs	= def_attrs,
+	/* statically allocated, no release method necessary */
+};
+
+static decl_subsys(smbios,&ktype_smbios,NULL);
+
+static inline void
+smbios_device_unregister(struct smbios_device *sdev)
+{
+	sysfs_remove_bin_file(&sdev->kobj, &tep_attr );
+	sysfs_remove_bin_file(&sdev->kobj, &table_attr );
+	kobject_unregister(&sdev->kobj);
+}
+
+static int
+smbios_device_register(struct smbios_device *sdev)
+{
+	int error;
+
+	if (!sdev)
+		return 1;
+
+	kobject_set_name(&sdev->kobj, "smbios");
+	kobj_set_kset_s(sdev,smbios_subsys);
+	error = kobject_register(&sdev->kobj);
+	if (!error){
+		sysfs_create_bin_file(&sdev->kobj, &tep_attr );
+		sysfs_create_bin_file(&sdev->kobj, &table_attr );
+	}
+	return error;
+}
+
+static int __init
+smbios_init(void)
+{
+	int rc=0;
+
+	printk(KERN_INFO "SMBIOS facility v%s\n", SMBIOS_VERSION );
+
+	rc = find_table_entry_point(&the_smbios_device);
+	if (rc)
+		return rc;
+
+	table_attr.size = find_table_max_address(&the_smbios_device);
+
+	rc = firmware_register(&smbios_subsys);
+	if (rc)
+		return rc;
+
+	rc = smbios_device_register(&the_smbios_device);
+
+	if (rc)
+		firmware_unregister(&smbios_subsys);
+
+	return rc;
+}
+
+static void __exit
+smbios_exit(void)
+{
+	smbios_device_unregister(&the_smbios_device);
+	firmware_unregister(&smbios_subsys);
+}
+
+late_initcall(smbios_init);
+module_exit(smbios_exit);
diff -Nru a/drivers/firmware/smbios.h b/drivers/firmware/smbios.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/firmware/smbios.h	Tue Apr 27 23:30:02 2004
@@ -0,0 +1,53 @@
+/*
+ * linux/drivers/firmware/smbios.c
+ *  Copyright (C) 2002, 2003, 2004 Dell Inc.
+ *  by Michael Brown <Michael_E_Brown@dell.com>
+ *  vim:noet:ts=8:sw=8:filetype=c:textwidth=80:
+ *
+ * BIOS SMBIOS Table access 
+ * conformant to DMTF SMBIOS definition
+ *   at http://www.dmtf.org/standards/smbios
+ *
+ * This code takes information provided by SMBIOS tables
+ * and presents it in sysfs.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_SMBIOS_H
+#define _LINUX_SMBIOS_H
+
+#include <linux/types.h>
+
+struct smbios_table_entry_point {
+	u8 anchor[4];
+	u8 checksum;
+	u8 eps_length;
+	u8 major_ver;
+	u8 minor_ver;
+	u16 max_struct_size;
+	u8 revision;
+	u8 formatted_area[5];
+	u8 dmi_anchor[5];
+	u8 intermediate_checksum;
+	u16 table_length;
+	u32 table_address;
+	u16 table_num_structs;
+	u8 smbios_bcd_revision;
+} __attribute__ ((packed));
+
+struct smbios_structure_header {
+	u8 type;
+	u8 length;
+	u16 handle;
+} __attribute__ ((packed));
+
+#endif				/* _LINUX_SMBIOS_H */

      parent reply	other threads:[~2004-04-28  4:43 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-04-28  2:27 [BK PATCH] add SMBIOS tables to sysfs Michael Brown
2004-04-28  3:30 ` Greg KH
2004-04-28  3:38   ` Michael Brown
2004-04-28 16:50     ` Greg KH
2004-04-28  3:55   ` Michael Brown
2004-04-28 16:51     ` Greg KH
2004-04-28  4:41   ` Michael Brown [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1083127267.1195.2848.camel@debian \
    --to=michael_e_brown@dell.com \
    --cc=akpm@osdl.org \
    --cc=greg@kroah.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox