patch-2.2.18 linux/arch/i386/kernel/dmi_scan.c

Next file: linux/arch/i386/kernel/i386_ksyms.c
Previous file: linux/arch/i386/kernel/cpuid.c
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/arch/i386/kernel/dmi_scan.c linux/arch/i386/kernel/dmi_scan.c
@@ -0,0 +1,182 @@
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+struct dmi_header
+{
+	u8	type;
+	u8	length;
+	u16	handle;
+};
+
+static char * __init dmi_string(struct dmi_header *dm, u8 s)
+{
+	u8 *bp=(u8 *)dm;
+	bp+=dm->length;
+	s--;
+	while(s>0)
+	{
+		bp+=strlen(bp);
+		bp++;
+		s--;
+	}
+	return bp;
+}
+
+static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
+{
+	u8 *buf;
+	struct dmi_header *dm;
+	u8 *data;
+	int i=1;
+	int last = 0;		
+		
+	buf = ioremap(base, len);
+	if(buf==NULL)
+		return -1;
+
+	data = buf;
+	while(i<num && (data-buf) < len)
+	{
+		dm=(struct dmi_header *)data;
+		if(dm->type < last)
+			break;
+		last = dm->type;
+		decode(dm);		
+		data+=dm->length;
+		while(*data || data[1])
+			data++;
+		data+=2;
+		i++;
+	}
+	iounmap(buf);
+	return 0;
+}
+
+
+int __init dmi_iterate(void (*decode)(struct dmi_header *))
+{
+	unsigned char buf[20];
+	long fp=0xE0000L;
+	fp -= 16;
+	
+	while( fp < 0xFFFFF)
+	{
+		fp+=16;
+		memcpy_fromio(buf, fp, 20);
+		if(memcmp(buf, "_DMI_", 5)==0)
+		{
+			u16 num=buf[13]<<8|buf[12];
+			u16 len=buf[7]<<8|buf[6];
+			u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
+#ifdef DUMP_DMI
+			printk(KERN_INFO "DMI %d.%d present.\n",
+				buf[14]>>4, buf[14]&0x0F);
+			printk(KERN_INFO "%d structures occupying %d bytes.\n",
+				buf[13]<<8|buf[12],
+				buf[7]<<8|buf[6]);
+			printk(KERN_INFO "DMI table at 0x%08X.\n",
+				buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]);
+#endif				
+			if(dmi_table(base,len, num, decode)==0)
+				return 0;
+		}
+	}
+	return -1;
+}
+
+
+/*
+ *	Process a DMI table entry. Right now all we care about are the BIOS
+ *	and machine entries. For 2.4 we should pull the smbus controller info
+ *	out of here.
+ */
+
+static void __init dmi_decode(struct dmi_header *dm)
+{
+	u8 *data = (u8 *)dm;
+	char *p;
+	
+	switch(dm->type)
+	{
+		case  0:		
+#ifdef DUMP_DMI
+			p=dmi_string(dm,data[4]);
+			if(*p && *p!=' ')
+			{
+				printk("BIOS Vendor: %s\n", p);
+				printk("BIOS Version: %s\n", 
+					dmi_string(dm, data[5]));
+				printk("BIOS Release: %s\n",
+					dmi_string(dm, data[8]));
+			}
+#endif				
+			/*
+			 *  Check for clue free BIOS implementations who use
+			 *  the following QA technique
+			 *
+			 *      [ Write BIOS Code ]<------
+			 *               |                ^
+			 *      < Does it Compile >----N--
+			 *               |Y               ^
+			 *	< Does it Boot Win98 >-N--
+			 *               |Y
+			 *           [Ship It]
+			 */
+			 
+			if(strcmp(dmi_string(dm, data[4]), "Phoenix Technologies LTD")==0 &&
+			   strcmp(dmi_string(dm, data[5]), "A04")==0 &&
+			   strcmp(dmi_string(dm, data[8]), "08/24/2000")==0)
+			{
+#ifdef CONFIG_APM
+				extern void apm_battery_horked(void);
+			   	apm_battery_horked();			   	
+			   	printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling battery reporting.\n");
+#endif			   	
+			}
+			break;
+#ifdef DUMP_DMI
+		case 1:
+			p=dmi_string(dm,data[4]);
+
+			if(*p && *p!=' ')
+			{
+				printk("System Vendor: %s.\n",p);
+				printk("Product Name: %s.\n",
+					dmi_string(dm, data[5]));
+				printk("Version %s.\n",
+					dmi_string(dm, data[6]));
+				printk("Serial Number %s.\n",
+					dmi_string(dm, data[7]));
+			}
+			break;
+		case 2:
+			p=dmi_string(dm,data[4]);
+
+			if(*p && *p!=' ')
+			{
+				printk("Board Vendor: %s.\n",p);
+				printk("Board Name: %s.\n",
+				dmi_string(dm, data[5]));
+				printk("Board Version: %s.\n",
+					dmi_string(dm, data[6]));
+			}
+			break;
+		case 3:
+			p=dmi_string(dm,data[8]);
+			if(*p && *p!=' ')
+				printk("Asset Tag: %s.\n", p);
+			break;
+#endif			
+	}
+}
+
+int __init dmi_scan_machine(void)
+{
+	return dmi_iterate(dmi_decode);
+}
+
+__initcall(dmi_scan_machine);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)