root/lm-sensors/trunk/kernel/busses/dmi_scan.c @ 1478

Revision 1478, 5.0 KB (checked in by mds, 11 years ago)

Move dmi detection code from i2c-piix4 to new dmi_scan.c.

This permits better kernel patching into kernels that
already have dmi_scan.c.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2        Taken from arch/i386/kernel/dmi_scan.c.
3        Changes dmi_ident to be non-static so we can access.
4*/
5
6#include <linux/module.h>
7#include <linux/config.h>
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <linux/string.h>
11#include <linux/init.h>
12#include <linux/apm_bios.h>
13#include <linux/slab.h>
14#include <asm/io.h>
15#include <linux/pm.h>
16#include <asm/keyboard.h>
17#include <asm/system.h>
18#include <linux/bootmem.h>
19#include "version.h"
20#include "dmi_scan.h"
21
22struct dmi_header
23{
24        u8      type;
25        u8      length;
26        u16     handle;
27};
28
29#define dmi_printk(x)
30//#define dmi_printk(x) printk x
31
32static char * __init dmi_string(struct dmi_header *dm, u8 s)
33{
34        u8 *bp=(u8 *)dm;
35        bp+=dm->length;
36        if(!s)
37                return "";
38        s--;
39        while(s>0)
40        {
41                bp+=strlen(bp);
42                bp++;
43                s--;
44        }
45        return bp;
46}
47
48/*
49 *      We have to be cautious here. We have seen BIOSes with DMI pointers
50 *      pointing to completely the wrong place for example
51 */
52 
53static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
54{
55        u8 *buf;
56        struct dmi_header *dm;
57        u8 *data;
58        int i=1;
59               
60        buf = ioremap(base, len);
61        if(buf==NULL)
62                return -1;
63
64        data = buf;
65
66        /*
67         *      Stop when we see al the items the table claimed to have
68         *      OR we run off the end of the table (also happens)
69         */
70 
71        while(i<num && (data - buf) < len)
72        {
73                dm=(struct dmi_header *)data;
74       
75                /*
76                 *      Avoid misparsing crud if the length of the last
77                 *      record is crap
78                 */
79                if((data-buf+dm->length) >= len)
80                        break;
81                decode(dm);             
82                data+=dm->length;
83                /*
84                 *      Don't go off the end of the data if there is
85                 *      stuff looking like string fill past the end
86                 */
87                while((data-buf) < len && (*data || data[1]))
88                        data++;
89                data+=2;
90                i++;
91        }
92        iounmap(buf);
93        return 0;
94}
95
96
97static int __init dmi_iterate(void (*decode)(struct dmi_header *))
98{
99        unsigned char buf[20];
100        long fp=0xE0000L;
101        fp -= 16;
102
103#ifdef CONFIG_SIMNOW
104        /*
105         *      Skip on x86/64 with simnow. Will eventually go away
106         *      If you see this ifdef in 2.6pre mail me !
107         */
108        return -1;
109#endif
110       
111        while( fp < 0xFFFFF)
112        {
113                fp+=16;
114                isa_memcpy_fromio(buf, fp, 20);
115                if(memcmp(buf, "_DMI_", 5)==0)
116                {
117                        u16 num=buf[13]<<8|buf[12];
118                        u16 len=buf[7]<<8|buf[6];
119                        u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
120
121                        dmi_printk((KERN_INFO "DMI %d.%d present.\n",
122                                buf[14]>>4, buf[14]&0x0F));
123                        dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
124                                buf[13]<<8|buf[12],
125                                buf[7]<<8|buf[6]));
126                        dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
127                                buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]));
128                        if(dmi_table(base,len, num, decode)==0)
129                                return 0;
130                }
131        }
132        return -1;
133}
134
135
136char *dmi_ident[DMI_STRING_MAX];
137
138/*
139 *      Save a DMI string
140 */
141 
142static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
143{
144        char *d = (char*)dm;
145        char *p = dmi_string(dm, d[string]);
146        if(p==NULL || *p == 0)
147                return;
148        if (dmi_ident[slot])
149                return;
150        dmi_ident[slot] = kmalloc(strlen(p)+1, GFP_KERNEL);
151        if(dmi_ident[slot])
152                strcpy(dmi_ident[slot], p);
153        else
154                printk(KERN_ERR "dmi_save_ident: out of memory.\n");
155}
156
157/*
158 *      Process a DMI table entry. Right now all we care about are the BIOS
159 *      and machine entries. For 2.5 we should pull the smbus controller info
160 *      out of here.
161 */
162
163static void __init dmi_decode(struct dmi_header *dm)
164{
165        u8 *data = (u8 *)dm;
166        char *p;
167       
168        switch(dm->type)
169        {
170                case  0:
171                        p=dmi_string(dm,data[4]);
172                        if(*p)
173                        {
174                                dmi_printk(("BIOS Vendor: %s\n", p));
175                                dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
176                                dmi_printk(("BIOS Version: %s\n", 
177                                        dmi_string(dm, data[5])));
178                                dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
179                                dmi_printk(("BIOS Release: %s\n",
180                                        dmi_string(dm, data[8])));
181                                dmi_save_ident(dm, DMI_BIOS_DATE, 8);
182                        }
183                        break;
184                       
185                case 1:
186                        p=dmi_string(dm,data[4]);
187                        if(*p)
188                        {
189                                dmi_printk(("System Vendor: %s.\n",p));
190                                dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
191                                dmi_printk(("Product Name: %s.\n",
192                                        dmi_string(dm, data[5])));
193                                dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
194                                dmi_printk(("Version %s.\n",
195                                        dmi_string(dm, data[6])));
196                                dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
197                                dmi_printk(("Serial Number %s.\n",
198                                        dmi_string(dm, data[7])));
199                        }
200                        break;
201                case 2:
202                        p=dmi_string(dm,data[4]);
203                        if(*p)
204                        {
205                                dmi_printk(("Board Vendor: %s.\n",p));
206                                dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
207                                dmi_printk(("Board Name: %s.\n",
208                                        dmi_string(dm, data[5])));
209                                dmi_save_ident(dm, DMI_BOARD_NAME, 5);
210                                dmi_printk(("Board Version: %s.\n",
211                                        dmi_string(dm, data[6])));
212                                dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
213                        }
214                        break;
215                case 3:
216                        p=dmi_string(dm,data[8]);
217                        if(*p && *p!=' ')
218                                dmi_printk(("Asset Tag: %s.\n", p));
219                        break;
220        }
221}
222
223void __init dmi_scan_machine(void)
224{
225        int err;
226        printk("dmi_scan.o version %s (%s)\n", LM_VERSION, LM_DATE);
227        err = dmi_iterate(dmi_decode);
228        if(err)
229                printk("dmi_scan.o: SM BIOS not found\n");
230        else
231                printk("dmi_scan.o: SM BIOS found\n");
232}
233
234#ifdef MODULE
235MODULE_DESCRIPTION("SM BIOS DMI Scanner");
236#ifdef MODULE_LICENSE
237MODULE_LICENSE("GPL");
238#endif
239EXPORT_SYMBOL(dmi_ident);
240EXPORT_SYMBOL(dmi_scan_machine);
241int init_module(void)
242{
243        return 0;
244}
245
246int cleanup_module(void)
247{
248        return 0;
249}
250
251#endif
Note: See TracBrowser for help on using the browser.