#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/apm_bios.h>
#include <asm/io.h>
struct dmi_header
{
u8 type;
u8 length;
u16 handle;
};
15 static char * __init dmi_string(struct dmi_header *dm, u8 s)
{
u8 *bp=(u8 *)dm;
bp+=dm->length;
s--;
20 while(s>0)
{
bp+=strlen(bp);
bp++;
s--;
}
26 return bp;
}
29 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);
38 if(buf==NULL)
39 return -1;
data = buf;
42 while(i<num && (data - buf) < len)
{
dm=(struct dmi_header *)data;
45 if(dm->type < last)
46 break;
last = dm->type;
decode(dm);
data+=dm->length;
50 while(*data || data[1])
data++;
data+=2;
i++;
}
iounmap(buf);
56 return 0;
}
60 int __init dmi_iterate(void (*decode)(struct dmi_header *))
{
unsigned char buf[20];
long fp=0xE0000L;
fp -= 16;
66 while( fp < 0xFFFFF)
{
fp+=16;
isa_memcpy_fromio(buf, fp, 20);
70 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];
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]);
83 if(dmi_table(base,len, num, decode)==0)
84 return 0;
}
}
87 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.
*/
97 static void __init dmi_decode(struct dmi_header *dm)
{
u8 *data = (u8 *)dm;
char *p;
102 switch(dm->type)
{
104 case 0:
p=dmi_string(dm,data[4]);
107 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]));
}
/*
* 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]
*
* Phoenix A04 08/24/2000 is known bad (Dell Inspiron 5000e)
* Phoenix A07 09/29/2000 is known good (Dell Inspiron 5000)
*/
132 if(strcmp(dmi_string(dm, data[4]), "Phoenix Technologies LTD")==0)
{
if(strcmp(dmi_string(dm, data[5]), "A04")==0
135 && strcmp(dmi_string(dm, data[8]), "08/24/2000")==0)
{
apm_info.get_power_status_broken = 1;
printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.\n");
}
}
141 break;
142 case 1:
p=dmi_string(dm,data[4]);
145 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]));
}
155 break;
156 case 2:
p=dmi_string(dm,data[4]);
159 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]));
}
167 break;
168 case 3:
p=dmi_string(dm,data[8]);
170 if(*p && *p!=' ')
printk("Asset Tag: %s.\n", p);
172 break;
}
}
176 static int __init dmi_scan_machine(void)
{
178 return dmi_iterate(dmi_decode);
}
module_init(dmi_scan_machine);