Files
lm-sensors/kernel/busses/dmi_scan.c
T
Kyosti Malkki 1cfe63804a (Kyösti) Cleanups
Copy sysctl enums to chip drivers from sensors.h for now,
   as seen in drivers included in 2.5 tree. File no longer included
   from kernel side.

   Apply i2c-proc change in CVS tagged -km2.

   Partial clean and sort of includes everywhere.

   Add i2c-dev.h, as a partial copy from i2c.
   Add to sensors.h from i2c-proc.h to compile things.
   Remove i2c-isa.h.

   Reflect header file changes to lib/ and prog/.


git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@1705 7894878c-1315-0410-8ee3-d5d059ff63e0
2003-01-21 20:01:27 +00:00

236 lines
5.0 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"
#include "dmi_scan.h"
/* for 2.2 kernels */
#ifndef isa_memcpy_fromio
#define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),(b),(c))
#endif
struct dmi_header
{
u8 type;
u8 length;
u16 handle;
};
#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)
{
u8 *data = (u8 *)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;
}
}
void __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");
}
MODULE_DESCRIPTION("SM BIOS DMI Scanner");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(dmi_ident);
EXPORT_SYMBOL(dmi_scan_mach);