The LDT fixes in particular fix some potentially random strange behaviour.
[davej-history.git] / arch / i386 / kernel / dmi_scan.c
blob8d5a9efb30b2dfed0935fb7d67e2d7bafda152ec
1 #include <linux/types.h>
2 #include <linux/kernel.h>
3 #include <linux/string.h>
4 #include <linux/init.h>
5 #include <linux/apm_bios.h>
6 #include <asm/io.h>
8 struct dmi_header
10 u8 type;
11 u8 length;
12 u16 handle;
15 static char * __init dmi_string(struct dmi_header *dm, u8 s)
17 u8 *bp=(u8 *)dm;
18 bp+=dm->length;
19 s--;
20 while(s>0)
22 bp+=strlen(bp);
23 bp++;
24 s--;
26 return bp;
29 static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
31 u8 *buf;
32 struct dmi_header *dm;
33 u8 *data;
34 int i=1;
35 int last = 0;
37 buf = ioremap(base, len);
38 if(buf==NULL)
39 return -1;
41 data = buf;
42 while(i<num && (data - buf) < len)
44 dm=(struct dmi_header *)data;
45 if(dm->type < last)
46 break;
47 last = dm->type;
48 decode(dm);
49 data+=dm->length;
50 while(*data || data[1])
51 data++;
52 data+=2;
53 i++;
55 iounmap(buf);
56 return 0;
60 int __init dmi_iterate(void (*decode)(struct dmi_header *))
62 unsigned char buf[20];
63 long fp=0xE0000L;
64 fp -= 16;
66 while( fp < 0xFFFFF)
68 fp+=16;
69 isa_memcpy_fromio(buf, fp, 20);
70 if(memcmp(buf, "_DMI_", 5)==0)
72 u16 num=buf[13]<<8|buf[12];
73 u16 len=buf[7]<<8|buf[6];
74 u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
76 printk(KERN_INFO "DMI %d.%d present.\n",
77 buf[14]>>4, buf[14]&0x0F);
78 printk(KERN_INFO "%d structures occupying %d bytes.\n",
79 buf[13]<<8|buf[12],
80 buf[7]<<8|buf[6]);
81 printk(KERN_INFO "DMI table at 0x%08X.\n",
82 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;
92 * Process a DMI table entry. Right now all we care about are the BIOS
93 * and machine entries. For 2.4 we should pull the smbus controller info
94 * out of here.
97 static void __init dmi_decode(struct dmi_header *dm)
99 u8 *data = (u8 *)dm;
100 char *p;
102 switch(dm->type)
104 case 0:
105 p=dmi_string(dm,data[4]);
107 if(*p && *p!=' ')
109 printk("BIOS Vendor: %s\n", p);
110 printk("BIOS Version: %s\n",
111 dmi_string(dm, data[5]));
112 printk("BIOS Release: %s\n",
113 dmi_string(dm, data[8]));
117 * Check for clue free BIOS implementations who use
118 * the following QA technique
120 * [ Write BIOS Code ]<------
121 * | ^
122 * < Does it Compile >----N--
123 * |Y ^
124 * < Does it Boot Win98 >-N--
125 * |Y
126 * [Ship It]
128 * Phoenix A04 08/24/2000 is known bad (Dell Inspiron 5000e)
129 * Phoenix A07 09/29/2000 is known good (Dell Inspiron 5000)
132 if(strcmp(dmi_string(dm, data[4]), "Phoenix Technologies LTD")==0)
134 if(strcmp(dmi_string(dm, data[5]), "A04")==0
135 && strcmp(dmi_string(dm, data[8]), "08/24/2000")==0)
137 apm_info.get_power_status_broken = 1;
138 printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.\n");
141 break;
142 case 1:
143 p=dmi_string(dm,data[4]);
145 if(*p && *p!=' ')
147 printk("System Vendor: %s.\n",p);
148 printk("Product Name: %s.\n",
149 dmi_string(dm, data[5]));
150 printk("Version %s.\n",
151 dmi_string(dm, data[6]));
152 printk("Serial Number %s.\n",
153 dmi_string(dm, data[7]));
155 break;
156 case 2:
157 p=dmi_string(dm,data[4]);
159 if(*p && *p!=' ')
161 printk("Board Vendor: %s.\n",p);
162 printk("Board Name: %s.\n",
163 dmi_string(dm, data[5]));
164 printk("Board Version: %s.\n",
165 dmi_string(dm, data[6]));
167 break;
168 case 3:
169 p=dmi_string(dm,data[8]);
170 if(*p && *p!=' ')
171 printk("Asset Tag: %s.\n", p);
172 break;
176 static int __init dmi_scan_machine(void)
178 return dmi_iterate(dmi_decode);
181 module_init(dmi_scan_machine);