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

Revision 1582, 5.1 KB (checked in by khali, 11 years ago)

Apply dmi_scan fixes from Linux kernel 2.5.43

  • 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 && *bp)
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=0;
59               
60        buf = ioremap(base, len);
61        if(buf==NULL)
62                return -1;
63
64        data = buf;
65
66        /*
67         *      Stop when we see all 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+sizeof(struct dmi_header)<=len)
72        {
73                dm=(struct dmi_header *)data;
74                /*
75                 *  We want to know the total length (formated area and strings)
76                 *  before decoding to make sure we won't run off the table in
77                 *  dmi_decode or dmi_string
78                 */
79                data+=dm->length;
80                while(data-buf<len-1 && (data[0] || data[1]))
81                        data++;
82                if(data-buf<len-1)
83                        decode(dm);
84                data+=2;
85                i++;
86        }
87        iounmap(buf);
88        return 0;
89}
90
91
92inline static int __init dmi_checksum(u8 *buf)
93{
94        u8 sum=0;
95        int a;
96       
97        for(a=0; a<15; a++)
98                sum+=buf[a];
99        return (sum==0);
100}
101
102static int __init dmi_iterate(void (*decode)(struct dmi_header *))
103{
104        u8 buf[15];
105        u32 fp=0xF0000;
106
107#ifdef CONFIG_SIMNOW
108        /*
109         *      Skip on x86/64 with simnow. Will eventually go away
110         *      If you see this ifdef in 2.6pre mail me !
111         */
112        return -1;
113#endif
114       
115        while( fp < 0xFFFFF)
116        {
117                isa_memcpy_fromio(buf, fp, 15);
118                if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
119                {
120                        u16 num=buf[13]<<8|buf[12];
121                        u16 len=buf[7]<<8|buf[6];
122                        u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
123
124                        /*
125                         * DMI version 0.0 means that the real version is taken from
126                         * the SMBIOS version, which we don't know at this point.
127                         */
128                        if(buf[14]!=0)
129                                dmi_printk((KERN_INFO "DMI %d.%d present.\n",
130                                        buf[14]>>4, buf[14]&0x0F));
131                        else
132                                dmi_printk((KERN_INFO "DMI present.\n"));
133                        dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
134                                num, len));
135                        dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
136                                base));
137                        if(dmi_table(base,len, num, decode)==0)
138                                return 0;
139                }
140                fp+=16;
141        }
142        return -1;
143}
144
145
146char *dmi_ident[DMI_STRING_MAX];
147
148/*
149 *      Save a DMI string
150 */
151 
152static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
153{
154        char *d = (char*)dm;
155        char *p = dmi_string(dm, d[string]);
156        if(p==NULL || *p == 0)
157                return;
158        if (dmi_ident[slot])
159                return;
160        dmi_ident[slot] = kmalloc(strlen(p)+1, GFP_KERNEL);
161        if(dmi_ident[slot])
162                strcpy(dmi_ident[slot], p);
163        else
164                printk(KERN_ERR "dmi_save_ident: out of memory.\n");
165}
166
167/*
168 *      Process a DMI table entry. Right now all we care about are the BIOS
169 *      and machine entries. For 2.5 we should pull the smbus controller info
170 *      out of here.
171 */
172
173static void __init dmi_decode(struct dmi_header *dm)
174{
175        u8 *data = (u8 *)dm;
176       
177        switch(dm->type)
178        {
179                case  0:
180                        dmi_printk(("BIOS Vendor: %s\n",
181                                dmi_string(dm, data[4])));
182                        dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
183                        dmi_printk(("BIOS Version: %s\n", 
184                                dmi_string(dm, data[5])));
185                        dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
186                        dmi_printk(("BIOS Release: %s\n",
187                                dmi_string(dm, data[8])));
188                        dmi_save_ident(dm, DMI_BIOS_DATE, 8);
189                        break;
190                case 1:
191                        dmi_printk(("System Vendor: %s\n",
192                                dmi_string(dm, data[4])));
193                        dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
194                        dmi_printk(("Product Name: %s\n",
195                                dmi_string(dm, data[5])));
196                        dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
197                        dmi_printk(("Version: %s\n",
198                                dmi_string(dm, data[6])));
199                        dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
200                        dmi_printk(("Serial Number: %s\n",
201                                dmi_string(dm, data[7])));
202                        break;
203                case 2:
204                        dmi_printk(("Board Vendor: %s\n",
205                                dmi_string(dm, data[4])));
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                        break;
214        }
215}
216
217void __init dmi_scan_mach(void)
218{
219        int err;
220        printk("dmi_scan.o version %s (%s)\n", LM_VERSION, LM_DATE);
221        err = dmi_iterate(dmi_decode);
222        if(err)
223                printk("dmi_scan.o: SM BIOS not found\n");
224        else
225                printk("dmi_scan.o: SM BIOS found\n");
226}
227
228#ifdef MODULE
229MODULE_DESCRIPTION("SM BIOS DMI Scanner");
230#ifdef MODULE_LICENSE
231MODULE_LICENSE("GPL");
232#endif
233EXPORT_SYMBOL(dmi_ident);
234EXPORT_SYMBOL(dmi_scan_mach);
235int init_module(void)
236{
237        return 0;
238}
239
240int cleanup_module(void)
241{
242        return 0;
243}
244
245#endif
Note: See TracBrowser for help on using the browser.