Files
lm-sensors/kernel/busses/dmi_scan.c
T
Jean Delvare af741a7b4d Move IBM detection into dmi_scan.c.
Delete dmi_scan.h, now useless.


git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@2423 7894878c-1315-0410-8ee3-d5d059ff63e0
2004-04-07 18:36:19 +00:00

250 lines
5.2 KiB
C

/*
Taken from arch/i386/kernel/dmi_scan.c.
Changes dmi_ident to be non-static so we can access.
*/
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/apm_bios.h>
#include <linux/slab.h>
#include <linux/pm.h>
#include <asm/io.h>
#include <asm/keyboard.h>
#include <asm/system.h>
#include "version.h"
int is_unsafe_smbus;
EXPORT_SYMBOL(is_unsafe_smbus);
struct dmi_header
{
u8 type;
u8 length;
u16 handle;
};
enum
{
DMI_BIOS_VENDOR,
DMI_BIOS_VERSION,
DMI_BIOS_DATE,
DMI_SYS_VENDOR,
DMI_PRODUCT_NAME,
DMI_PRODUCT_VERSION,
DMI_BOARD_VENDOR,
DMI_BOARD_NAME,
DMI_BOARD_VERSION,
DMI_STRING_MAX
};
#define dmi_printk(x)
//#define dmi_printk(x) printk x
static char * __init dmi_string(struct dmi_header *dm, u8 s)
{
u8 *bp=(u8 *)dm;
bp+=dm->length;
if(!s)
return "";
s--;
while(s>0 && *bp)
{
bp+=strlen(bp);
bp++;
s--;
}
return bp;
}
/*
* We have to be cautious here. We have seen BIOSes with DMI pointers
* pointing to completely the wrong place for example
*/
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=0;
buf = ioremap(base, len);
if(buf==NULL)
return -1;
data = buf;
/*
* Stop when we see all the items the table claimed to have
* OR we run off the end of the table (also happens)
*/
while(i<num && data-buf+sizeof(struct dmi_header)<=len)
{
dm=(struct dmi_header *)data;
/*
* We want to know the total length (formated area and strings)
* before decoding to make sure we won't run off the table in
* dmi_decode or dmi_string
*/
data+=dm->length;
while(data-buf<len-1 && (data[0] || data[1]))
data++;
if(data-buf<len-1)
decode(dm);
data+=2;
i++;
}
iounmap(buf);
return 0;
}
inline static int __init dmi_checksum(u8 *buf)
{
u8 sum=0;
int a;
for(a=0; a<15; a++)
sum+=buf[a];
return (sum==0);
}
static int __init dmi_iterate(void (*decode)(struct dmi_header *))
{
u8 buf[15];
u32 fp=0xF0000;
#ifdef CONFIG_SIMNOW
/*
* Skip on x86/64 with simnow. Will eventually go away
* If you see this ifdef in 2.6pre mail me !
*/
return -1;
#endif
while( fp < 0xFFFFF)
{
isa_memcpy_fromio(buf, fp, 15);
if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
{
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];
/*
* DMI version 0.0 means that the real version is taken from
* the SMBIOS version, which we don't know at this point.
*/
if(buf[14]!=0)
dmi_printk((KERN_INFO "DMI %d.%d present.\n",
buf[14]>>4, buf[14]&0x0F));
else
dmi_printk((KERN_INFO "DMI present.\n"));
dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
num, len));
dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
base));
if(dmi_table(base,len, num, decode)==0)
return 0;
}
fp+=16;
}
return -1;
}
char *dmi_ident[DMI_STRING_MAX];
/*
* Save a DMI string
*/
static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
{
char *d = (char*)dm;
char *p = dmi_string(dm, d[string]);
if(p==NULL || *p == 0)
return;
if (dmi_ident[slot])
return;
dmi_ident[slot] = kmalloc(strlen(p)+1, GFP_KERNEL);
if(dmi_ident[slot])
strcpy(dmi_ident[slot], p);
else
printk(KERN_ERR "dmi_save_ident: out of memory.\n");
}
/*
* Process a DMI table entry. Right now all we care about are the BIOS
* and machine entries. For 2.5 we should pull the smbus controller info
* out of here.
*/
static void __init dmi_decode(struct dmi_header *dm)
{
switch(dm->type)
{
case 0:
dmi_printk(("BIOS Vendor: %s\n",
dmi_string(dm, data[4])));
dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
dmi_printk(("BIOS Version: %s\n",
dmi_string(dm, data[5])));
dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
dmi_printk(("BIOS Release: %s\n",
dmi_string(dm, data[8])));
dmi_save_ident(dm, DMI_BIOS_DATE, 8);
break;
case 1:
dmi_printk(("System Vendor: %s\n",
dmi_string(dm, data[4])));
dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
dmi_printk(("Product Name: %s\n",
dmi_string(dm, data[5])));
dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
dmi_printk(("Version: %s\n",
dmi_string(dm, data[6])));
dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
dmi_printk(("Serial Number: %s\n",
dmi_string(dm, data[7])));
break;
case 2:
dmi_printk(("Board Vendor: %s\n",
dmi_string(dm, data[4])));
dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
dmi_printk(("Board Name: %s\n",
dmi_string(dm, data[5])));
dmi_save_ident(dm, DMI_BOARD_NAME, 5);
dmi_printk(("Board Version: %s\n",
dmi_string(dm, data[6])));
dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
break;
}
}
int __init dmi_scan_mach(void)
{
int err;
printk("dmi_scan.o version %s (%s)\n", LM_VERSION, LM_DATE);
err = dmi_iterate(dmi_decode);
if(err)
printk("dmi_scan.o: SM BIOS not found\n");
else
printk("dmi_scan.o: SM BIOS found\n");
if(dmi_ident[DMI_SYS_VENDOR] != NULL
&& strncmp(dmi_ident[DMI_SYS_VENDOR], "IBM", 3) == 0)
is_unsafe_smbus = 1;
return 0;
}
MODULE_DESCRIPTION("SM BIOS DMI Scanner");
MODULE_LICENSE("GPL");
module_init(dmi_scan_mach);