Commit 4f705ae3e94ffaafe8d35f71ff4d5c499bb06814
Committed by
Greg Kroah-Hartman
1 parent
0266949205
Exists in
master
and in
7 other branches
[PATCH] DMI: move dmi_scan.c from arch/i386 to drivers/firmware/
dmi_scan.c is arch-independent and is used by i386, x86_64, and ia64. Currently all three arches compile it from arch/i386, which means that ia64 and x86_64 depend on things in arch/i386 that they wouldn't otherwise care about. This is simply "mv arch/i386/kernel/dmi_scan.c drivers/firmware/" (removing trailing whitespace) and the associated Makefile changes. All three architectures already set CONFIG_DMI in their top-level Kconfig files. Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Cc: Andi Kleen <ak@muc.de> Cc: "Luck, Tony" <tony.luck@intel.com> Cc: Andrey Panin <pazke@orbita1.ru> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Showing 6 changed files with 363 additions and 365 deletions Side-by-side Diff
arch/i386/kernel/Makefile
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | |
7 | 7 | obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ |
8 | 8 | ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ |
9 | - pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \ | |
9 | + pci-dma.o i386_ksyms.o i387.o bootflag.o \ | |
10 | 10 | quirks.o i8237.o topology.o alternative.o |
11 | 11 | |
12 | 12 | obj-y += cpu/ |
arch/i386/kernel/dmi_scan.c
1 | -#include <linux/types.h> | |
2 | -#include <linux/string.h> | |
3 | -#include <linux/init.h> | |
4 | -#include <linux/module.h> | |
5 | -#include <linux/dmi.h> | |
6 | -#include <linux/efi.h> | |
7 | -#include <linux/bootmem.h> | |
8 | -#include <linux/slab.h> | |
9 | -#include <asm/dmi.h> | |
10 | - | |
11 | -static char * __init dmi_string(struct dmi_header *dm, u8 s) | |
12 | -{ | |
13 | - u8 *bp = ((u8 *) dm) + dm->length; | |
14 | - char *str = ""; | |
15 | - | |
16 | - if (s) { | |
17 | - s--; | |
18 | - while (s > 0 && *bp) { | |
19 | - bp += strlen(bp) + 1; | |
20 | - s--; | |
21 | - } | |
22 | - | |
23 | - if (*bp != 0) { | |
24 | - str = dmi_alloc(strlen(bp) + 1); | |
25 | - if (str != NULL) | |
26 | - strcpy(str, bp); | |
27 | - else | |
28 | - printk(KERN_ERR "dmi_string: out of memory.\n"); | |
29 | - } | |
30 | - } | |
31 | - | |
32 | - return str; | |
33 | -} | |
34 | - | |
35 | -/* | |
36 | - * We have to be cautious here. We have seen BIOSes with DMI pointers | |
37 | - * pointing to completely the wrong place for example | |
38 | - */ | |
39 | -static int __init dmi_table(u32 base, int len, int num, | |
40 | - void (*decode)(struct dmi_header *)) | |
41 | -{ | |
42 | - u8 *buf, *data; | |
43 | - int i = 0; | |
44 | - | |
45 | - buf = dmi_ioremap(base, len); | |
46 | - if (buf == NULL) | |
47 | - return -1; | |
48 | - | |
49 | - data = buf; | |
50 | - | |
51 | - /* | |
52 | - * Stop when we see all the items the table claimed to have | |
53 | - * OR we run off the end of the table (also happens) | |
54 | - */ | |
55 | - while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) { | |
56 | - struct dmi_header *dm = (struct dmi_header *)data; | |
57 | - /* | |
58 | - * We want to know the total length (formated area and strings) | |
59 | - * before decoding to make sure we won't run off the table in | |
60 | - * dmi_decode or dmi_string | |
61 | - */ | |
62 | - data += dm->length; | |
63 | - while ((data - buf < len - 1) && (data[0] || data[1])) | |
64 | - data++; | |
65 | - if (data - buf < len - 1) | |
66 | - decode(dm); | |
67 | - data += 2; | |
68 | - i++; | |
69 | - } | |
70 | - dmi_iounmap(buf, len); | |
71 | - return 0; | |
72 | -} | |
73 | - | |
74 | -static int __init dmi_checksum(u8 *buf) | |
75 | -{ | |
76 | - u8 sum = 0; | |
77 | - int a; | |
78 | - | |
79 | - for (a = 0; a < 15; a++) | |
80 | - sum += buf[a]; | |
81 | - | |
82 | - return sum == 0; | |
83 | -} | |
84 | - | |
85 | -static char *dmi_ident[DMI_STRING_MAX]; | |
86 | -static LIST_HEAD(dmi_devices); | |
87 | - | |
88 | -/* | |
89 | - * Save a DMI string | |
90 | - */ | |
91 | -static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) | |
92 | -{ | |
93 | - char *p, *d = (char*) dm; | |
94 | - | |
95 | - if (dmi_ident[slot]) | |
96 | - return; | |
97 | - | |
98 | - p = dmi_string(dm, d[string]); | |
99 | - if (p == NULL) | |
100 | - return; | |
101 | - | |
102 | - dmi_ident[slot] = p; | |
103 | -} | |
104 | - | |
105 | -static void __init dmi_save_devices(struct dmi_header *dm) | |
106 | -{ | |
107 | - int i, count = (dm->length - sizeof(struct dmi_header)) / 2; | |
108 | - struct dmi_device *dev; | |
109 | - | |
110 | - for (i = 0; i < count; i++) { | |
111 | - char *d = (char *)(dm + 1) + (i * 2); | |
112 | - | |
113 | - /* Skip disabled device */ | |
114 | - if ((*d & 0x80) == 0) | |
115 | - continue; | |
116 | - | |
117 | - dev = dmi_alloc(sizeof(*dev)); | |
118 | - if (!dev) { | |
119 | - printk(KERN_ERR "dmi_save_devices: out of memory.\n"); | |
120 | - break; | |
121 | - } | |
122 | - | |
123 | - dev->type = *d++ & 0x7f; | |
124 | - dev->name = dmi_string(dm, *d); | |
125 | - dev->device_data = NULL; | |
126 | - | |
127 | - list_add(&dev->list, &dmi_devices); | |
128 | - } | |
129 | -} | |
130 | - | |
131 | -static void __init dmi_save_ipmi_device(struct dmi_header *dm) | |
132 | -{ | |
133 | - struct dmi_device *dev; | |
134 | - void * data; | |
135 | - | |
136 | - data = dmi_alloc(dm->length); | |
137 | - if (data == NULL) { | |
138 | - printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n"); | |
139 | - return; | |
140 | - } | |
141 | - | |
142 | - memcpy(data, dm, dm->length); | |
143 | - | |
144 | - dev = dmi_alloc(sizeof(*dev)); | |
145 | - if (!dev) { | |
146 | - printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n"); | |
147 | - return; | |
148 | - } | |
149 | - | |
150 | - dev->type = DMI_DEV_TYPE_IPMI; | |
151 | - dev->name = "IPMI controller"; | |
152 | - dev->device_data = data; | |
153 | - | |
154 | - list_add(&dev->list, &dmi_devices); | |
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 | -static void __init dmi_decode(struct dmi_header *dm) | |
163 | -{ | |
164 | - switch(dm->type) { | |
165 | - case 0: /* BIOS Information */ | |
166 | - dmi_save_ident(dm, DMI_BIOS_VENDOR, 4); | |
167 | - dmi_save_ident(dm, DMI_BIOS_VERSION, 5); | |
168 | - dmi_save_ident(dm, DMI_BIOS_DATE, 8); | |
169 | - break; | |
170 | - case 1: /* System Information */ | |
171 | - dmi_save_ident(dm, DMI_SYS_VENDOR, 4); | |
172 | - dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); | |
173 | - dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); | |
174 | - dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7); | |
175 | - break; | |
176 | - case 2: /* Base Board Information */ | |
177 | - dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); | |
178 | - dmi_save_ident(dm, DMI_BOARD_NAME, 5); | |
179 | - dmi_save_ident(dm, DMI_BOARD_VERSION, 6); | |
180 | - break; | |
181 | - case 10: /* Onboard Devices Information */ | |
182 | - dmi_save_devices(dm); | |
183 | - break; | |
184 | - case 38: /* IPMI Device Information */ | |
185 | - dmi_save_ipmi_device(dm); | |
186 | - } | |
187 | -} | |
188 | - | |
189 | -static int __init dmi_present(char __iomem *p) | |
190 | -{ | |
191 | - u8 buf[15]; | |
192 | - memcpy_fromio(buf, p, 15); | |
193 | - if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) { | |
194 | - u16 num = (buf[13] << 8) | buf[12]; | |
195 | - u16 len = (buf[7] << 8) | buf[6]; | |
196 | - u32 base = (buf[11] << 24) | (buf[10] << 16) | | |
197 | - (buf[9] << 8) | buf[8]; | |
198 | - | |
199 | - /* | |
200 | - * DMI version 0.0 means that the real version is taken from | |
201 | - * the SMBIOS version, which we don't know at this point. | |
202 | - */ | |
203 | - if (buf[14] != 0) | |
204 | - printk(KERN_INFO "DMI %d.%d present.\n", | |
205 | - buf[14] >> 4, buf[14] & 0xF); | |
206 | - else | |
207 | - printk(KERN_INFO "DMI present.\n"); | |
208 | - if (dmi_table(base,len, num, dmi_decode) == 0) | |
209 | - return 0; | |
210 | - } | |
211 | - return 1; | |
212 | -} | |
213 | - | |
214 | -void __init dmi_scan_machine(void) | |
215 | -{ | |
216 | - char __iomem *p, *q; | |
217 | - int rc; | |
218 | - | |
219 | - if (efi_enabled) { | |
220 | - if (efi.smbios == EFI_INVALID_TABLE_ADDR) | |
221 | - goto out; | |
222 | - | |
223 | - /* This is called as a core_initcall() because it isn't | |
224 | - * needed during early boot. This also means we can | |
225 | - * iounmap the space when we're done with it. | |
226 | - */ | |
227 | - p = dmi_ioremap(efi.smbios, 32); | |
228 | - if (p == NULL) | |
229 | - goto out; | |
230 | - | |
231 | - rc = dmi_present(p + 0x10); /* offset of _DMI_ string */ | |
232 | - dmi_iounmap(p, 32); | |
233 | - if (!rc) | |
234 | - return; | |
235 | - } | |
236 | - else { | |
237 | - /* | |
238 | - * no iounmap() for that ioremap(); it would be a no-op, but | |
239 | - * it's so early in setup that sucker gets confused into doing | |
240 | - * what it shouldn't if we actually call it. | |
241 | - */ | |
242 | - p = dmi_ioremap(0xF0000, 0x10000); | |
243 | - if (p == NULL) | |
244 | - goto out; | |
245 | - | |
246 | - for (q = p; q < p + 0x10000; q += 16) { | |
247 | - rc = dmi_present(q); | |
248 | - if (!rc) | |
249 | - return; | |
250 | - } | |
251 | - } | |
252 | - out: printk(KERN_INFO "DMI not present or invalid.\n"); | |
253 | -} | |
254 | - | |
255 | -/** | |
256 | - * dmi_check_system - check system DMI data | |
257 | - * @list: array of dmi_system_id structures to match against | |
258 | - * | |
259 | - * Walk the blacklist table running matching functions until someone | |
260 | - * returns non zero or we hit the end. Callback function is called for | |
261 | - * each successfull match. Returns the number of matches. | |
262 | - */ | |
263 | -int dmi_check_system(struct dmi_system_id *list) | |
264 | -{ | |
265 | - int i, count = 0; | |
266 | - struct dmi_system_id *d = list; | |
267 | - | |
268 | - while (d->ident) { | |
269 | - for (i = 0; i < ARRAY_SIZE(d->matches); i++) { | |
270 | - int s = d->matches[i].slot; | |
271 | - if (s == DMI_NONE) | |
272 | - continue; | |
273 | - if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr)) | |
274 | - continue; | |
275 | - /* No match */ | |
276 | - goto fail; | |
277 | - } | |
278 | - count++; | |
279 | - if (d->callback && d->callback(d)) | |
280 | - break; | |
281 | -fail: d++; | |
282 | - } | |
283 | - | |
284 | - return count; | |
285 | -} | |
286 | -EXPORT_SYMBOL(dmi_check_system); | |
287 | - | |
288 | -/** | |
289 | - * dmi_get_system_info - return DMI data value | |
290 | - * @field: data index (see enum dmi_filed) | |
291 | - * | |
292 | - * Returns one DMI data value, can be used to perform | |
293 | - * complex DMI data checks. | |
294 | - */ | |
295 | -char *dmi_get_system_info(int field) | |
296 | -{ | |
297 | - return dmi_ident[field]; | |
298 | -} | |
299 | -EXPORT_SYMBOL(dmi_get_system_info); | |
300 | - | |
301 | -/** | |
302 | - * dmi_find_device - find onboard device by type/name | |
303 | - * @type: device type or %DMI_DEV_TYPE_ANY to match all device types | |
304 | - * @desc: device name string or %NULL to match all | |
305 | - * @from: previous device found in search, or %NULL for new search. | |
306 | - * | |
307 | - * Iterates through the list of known onboard devices. If a device is | |
308 | - * found with a matching @vendor and @device, a pointer to its device | |
309 | - * structure is returned. Otherwise, %NULL is returned. | |
310 | - * A new search is initiated by passing %NULL to the @from argument. | |
311 | - * If @from is not %NULL, searches continue from next device. | |
312 | - */ | |
313 | -struct dmi_device * dmi_find_device(int type, const char *name, | |
314 | - struct dmi_device *from) | |
315 | -{ | |
316 | - struct list_head *d, *head = from ? &from->list : &dmi_devices; | |
317 | - | |
318 | - for(d = head->next; d != &dmi_devices; d = d->next) { | |
319 | - struct dmi_device *dev = list_entry(d, struct dmi_device, list); | |
320 | - | |
321 | - if (((type == DMI_DEV_TYPE_ANY) || (dev->type == type)) && | |
322 | - ((name == NULL) || (strcmp(dev->name, name) == 0))) | |
323 | - return dev; | |
324 | - } | |
325 | - | |
326 | - return NULL; | |
327 | -} | |
328 | -EXPORT_SYMBOL(dmi_find_device); | |
329 | - | |
330 | -/** | |
331 | - * dmi_get_year - Return year of a DMI date | |
332 | - * @field: data index (like dmi_get_system_info) | |
333 | - * | |
334 | - * Returns -1 when the field doesn't exist. 0 when it is broken. | |
335 | - */ | |
336 | -int dmi_get_year(int field) | |
337 | -{ | |
338 | - int year; | |
339 | - char *s = dmi_get_system_info(field); | |
340 | - | |
341 | - if (!s) | |
342 | - return -1; | |
343 | - if (*s == '\0') | |
344 | - return 0; | |
345 | - s = strrchr(s, '/'); | |
346 | - if (!s) | |
347 | - return 0; | |
348 | - | |
349 | - s += 1; | |
350 | - year = simple_strtoul(s, NULL, 0); | |
351 | - if (year && year < 100) { /* 2-digit year */ | |
352 | - year += 1900; | |
353 | - if (year < 1996) /* no dates < spec 1.0 */ | |
354 | - year += 100; | |
355 | - } | |
356 | - | |
357 | - return year; | |
358 | -} |
arch/ia64/kernel/Makefile
... | ... | @@ -7,7 +7,7 @@ |
7 | 7 | obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \ |
8 | 8 | irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \ |
9 | 9 | salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \ |
10 | - unwind.o mca.o mca_asm.o topology.o dmi_scan.o | |
10 | + unwind.o mca.o mca_asm.o topology.o | |
11 | 11 | |
12 | 12 | obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o |
13 | 13 | obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o |
... | ... | @@ -30,7 +30,6 @@ |
30 | 30 | obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o |
31 | 31 | obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o |
32 | 32 | mca_recovery-y += mca_drv.o mca_drv_asm.o |
33 | -dmi_scan-y += ../../i386/kernel/dmi_scan.o | |
34 | 33 | |
35 | 34 | # The gate DSO image is built using a special linker script. |
36 | 35 | targets += gate.so gate-syms.o |
arch/x86_64/kernel/Makefile
... | ... | @@ -8,7 +8,7 @@ |
8 | 8 | ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \ |
9 | 9 | x8664_ksyms.o i387.o syscall.o vsyscall.o \ |
10 | 10 | setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \ |
11 | - dmi_scan.o pci-dma.o pci-nommu.o | |
11 | + pci-dma.o pci-nommu.o | |
12 | 12 | |
13 | 13 | obj-$(CONFIG_X86_MCE) += mce.o |
14 | 14 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o |
... | ... | @@ -49,5 +49,4 @@ |
49 | 49 | quirks-y += ../../i386/kernel/quirks.o |
50 | 50 | i8237-y += ../../i386/kernel/i8237.o |
51 | 51 | msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o |
52 | -dmi_scan-y += ../../i386/kernel/dmi_scan.o |
drivers/firmware/Makefile
drivers/firmware/dmi_scan.c
1 | +#include <linux/types.h> | |
2 | +#include <linux/string.h> | |
3 | +#include <linux/init.h> | |
4 | +#include <linux/module.h> | |
5 | +#include <linux/dmi.h> | |
6 | +#include <linux/efi.h> | |
7 | +#include <linux/bootmem.h> | |
8 | +#include <linux/slab.h> | |
9 | +#include <asm/dmi.h> | |
10 | + | |
11 | +static char * __init dmi_string(struct dmi_header *dm, u8 s) | |
12 | +{ | |
13 | + u8 *bp = ((u8 *) dm) + dm->length; | |
14 | + char *str = ""; | |
15 | + | |
16 | + if (s) { | |
17 | + s--; | |
18 | + while (s > 0 && *bp) { | |
19 | + bp += strlen(bp) + 1; | |
20 | + s--; | |
21 | + } | |
22 | + | |
23 | + if (*bp != 0) { | |
24 | + str = dmi_alloc(strlen(bp) + 1); | |
25 | + if (str != NULL) | |
26 | + strcpy(str, bp); | |
27 | + else | |
28 | + printk(KERN_ERR "dmi_string: out of memory.\n"); | |
29 | + } | |
30 | + } | |
31 | + | |
32 | + return str; | |
33 | +} | |
34 | + | |
35 | +/* | |
36 | + * We have to be cautious here. We have seen BIOSes with DMI pointers | |
37 | + * pointing to completely the wrong place for example | |
38 | + */ | |
39 | +static int __init dmi_table(u32 base, int len, int num, | |
40 | + void (*decode)(struct dmi_header *)) | |
41 | +{ | |
42 | + u8 *buf, *data; | |
43 | + int i = 0; | |
44 | + | |
45 | + buf = dmi_ioremap(base, len); | |
46 | + if (buf == NULL) | |
47 | + return -1; | |
48 | + | |
49 | + data = buf; | |
50 | + | |
51 | + /* | |
52 | + * Stop when we see all the items the table claimed to have | |
53 | + * OR we run off the end of the table (also happens) | |
54 | + */ | |
55 | + while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) { | |
56 | + struct dmi_header *dm = (struct dmi_header *)data; | |
57 | + /* | |
58 | + * We want to know the total length (formated area and strings) | |
59 | + * before decoding to make sure we won't run off the table in | |
60 | + * dmi_decode or dmi_string | |
61 | + */ | |
62 | + data += dm->length; | |
63 | + while ((data - buf < len - 1) && (data[0] || data[1])) | |
64 | + data++; | |
65 | + if (data - buf < len - 1) | |
66 | + decode(dm); | |
67 | + data += 2; | |
68 | + i++; | |
69 | + } | |
70 | + dmi_iounmap(buf, len); | |
71 | + return 0; | |
72 | +} | |
73 | + | |
74 | +static int __init dmi_checksum(u8 *buf) | |
75 | +{ | |
76 | + u8 sum = 0; | |
77 | + int a; | |
78 | + | |
79 | + for (a = 0; a < 15; a++) | |
80 | + sum += buf[a]; | |
81 | + | |
82 | + return sum == 0; | |
83 | +} | |
84 | + | |
85 | +static char *dmi_ident[DMI_STRING_MAX]; | |
86 | +static LIST_HEAD(dmi_devices); | |
87 | + | |
88 | +/* | |
89 | + * Save a DMI string | |
90 | + */ | |
91 | +static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) | |
92 | +{ | |
93 | + char *p, *d = (char*) dm; | |
94 | + | |
95 | + if (dmi_ident[slot]) | |
96 | + return; | |
97 | + | |
98 | + p = dmi_string(dm, d[string]); | |
99 | + if (p == NULL) | |
100 | + return; | |
101 | + | |
102 | + dmi_ident[slot] = p; | |
103 | +} | |
104 | + | |
105 | +static void __init dmi_save_devices(struct dmi_header *dm) | |
106 | +{ | |
107 | + int i, count = (dm->length - sizeof(struct dmi_header)) / 2; | |
108 | + struct dmi_device *dev; | |
109 | + | |
110 | + for (i = 0; i < count; i++) { | |
111 | + char *d = (char *)(dm + 1) + (i * 2); | |
112 | + | |
113 | + /* Skip disabled device */ | |
114 | + if ((*d & 0x80) == 0) | |
115 | + continue; | |
116 | + | |
117 | + dev = dmi_alloc(sizeof(*dev)); | |
118 | + if (!dev) { | |
119 | + printk(KERN_ERR "dmi_save_devices: out of memory.\n"); | |
120 | + break; | |
121 | + } | |
122 | + | |
123 | + dev->type = *d++ & 0x7f; | |
124 | + dev->name = dmi_string(dm, *d); | |
125 | + dev->device_data = NULL; | |
126 | + | |
127 | + list_add(&dev->list, &dmi_devices); | |
128 | + } | |
129 | +} | |
130 | + | |
131 | +static void __init dmi_save_ipmi_device(struct dmi_header *dm) | |
132 | +{ | |
133 | + struct dmi_device *dev; | |
134 | + void * data; | |
135 | + | |
136 | + data = dmi_alloc(dm->length); | |
137 | + if (data == NULL) { | |
138 | + printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n"); | |
139 | + return; | |
140 | + } | |
141 | + | |
142 | + memcpy(data, dm, dm->length); | |
143 | + | |
144 | + dev = dmi_alloc(sizeof(*dev)); | |
145 | + if (!dev) { | |
146 | + printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n"); | |
147 | + return; | |
148 | + } | |
149 | + | |
150 | + dev->type = DMI_DEV_TYPE_IPMI; | |
151 | + dev->name = "IPMI controller"; | |
152 | + dev->device_data = data; | |
153 | + | |
154 | + list_add(&dev->list, &dmi_devices); | |
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 | +static void __init dmi_decode(struct dmi_header *dm) | |
163 | +{ | |
164 | + switch(dm->type) { | |
165 | + case 0: /* BIOS Information */ | |
166 | + dmi_save_ident(dm, DMI_BIOS_VENDOR, 4); | |
167 | + dmi_save_ident(dm, DMI_BIOS_VERSION, 5); | |
168 | + dmi_save_ident(dm, DMI_BIOS_DATE, 8); | |
169 | + break; | |
170 | + case 1: /* System Information */ | |
171 | + dmi_save_ident(dm, DMI_SYS_VENDOR, 4); | |
172 | + dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); | |
173 | + dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); | |
174 | + dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7); | |
175 | + break; | |
176 | + case 2: /* Base Board Information */ | |
177 | + dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); | |
178 | + dmi_save_ident(dm, DMI_BOARD_NAME, 5); | |
179 | + dmi_save_ident(dm, DMI_BOARD_VERSION, 6); | |
180 | + break; | |
181 | + case 10: /* Onboard Devices Information */ | |
182 | + dmi_save_devices(dm); | |
183 | + break; | |
184 | + case 38: /* IPMI Device Information */ | |
185 | + dmi_save_ipmi_device(dm); | |
186 | + } | |
187 | +} | |
188 | + | |
189 | +static int __init dmi_present(char __iomem *p) | |
190 | +{ | |
191 | + u8 buf[15]; | |
192 | + memcpy_fromio(buf, p, 15); | |
193 | + if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) { | |
194 | + u16 num = (buf[13] << 8) | buf[12]; | |
195 | + u16 len = (buf[7] << 8) | buf[6]; | |
196 | + u32 base = (buf[11] << 24) | (buf[10] << 16) | | |
197 | + (buf[9] << 8) | buf[8]; | |
198 | + | |
199 | + /* | |
200 | + * DMI version 0.0 means that the real version is taken from | |
201 | + * the SMBIOS version, which we don't know at this point. | |
202 | + */ | |
203 | + if (buf[14] != 0) | |
204 | + printk(KERN_INFO "DMI %d.%d present.\n", | |
205 | + buf[14] >> 4, buf[14] & 0xF); | |
206 | + else | |
207 | + printk(KERN_INFO "DMI present.\n"); | |
208 | + if (dmi_table(base,len, num, dmi_decode) == 0) | |
209 | + return 0; | |
210 | + } | |
211 | + return 1; | |
212 | +} | |
213 | + | |
214 | +void __init dmi_scan_machine(void) | |
215 | +{ | |
216 | + char __iomem *p, *q; | |
217 | + int rc; | |
218 | + | |
219 | + if (efi_enabled) { | |
220 | + if (efi.smbios == EFI_INVALID_TABLE_ADDR) | |
221 | + goto out; | |
222 | + | |
223 | + /* This is called as a core_initcall() because it isn't | |
224 | + * needed during early boot. This also means we can | |
225 | + * iounmap the space when we're done with it. | |
226 | + */ | |
227 | + p = dmi_ioremap(efi.smbios, 32); | |
228 | + if (p == NULL) | |
229 | + goto out; | |
230 | + | |
231 | + rc = dmi_present(p + 0x10); /* offset of _DMI_ string */ | |
232 | + dmi_iounmap(p, 32); | |
233 | + if (!rc) | |
234 | + return; | |
235 | + } | |
236 | + else { | |
237 | + /* | |
238 | + * no iounmap() for that ioremap(); it would be a no-op, but | |
239 | + * it's so early in setup that sucker gets confused into doing | |
240 | + * what it shouldn't if we actually call it. | |
241 | + */ | |
242 | + p = dmi_ioremap(0xF0000, 0x10000); | |
243 | + if (p == NULL) | |
244 | + goto out; | |
245 | + | |
246 | + for (q = p; q < p + 0x10000; q += 16) { | |
247 | + rc = dmi_present(q); | |
248 | + if (!rc) | |
249 | + return; | |
250 | + } | |
251 | + } | |
252 | + out: printk(KERN_INFO "DMI not present or invalid.\n"); | |
253 | +} | |
254 | + | |
255 | +/** | |
256 | + * dmi_check_system - check system DMI data | |
257 | + * @list: array of dmi_system_id structures to match against | |
258 | + * | |
259 | + * Walk the blacklist table running matching functions until someone | |
260 | + * returns non zero or we hit the end. Callback function is called for | |
261 | + * each successfull match. Returns the number of matches. | |
262 | + */ | |
263 | +int dmi_check_system(struct dmi_system_id *list) | |
264 | +{ | |
265 | + int i, count = 0; | |
266 | + struct dmi_system_id *d = list; | |
267 | + | |
268 | + while (d->ident) { | |
269 | + for (i = 0; i < ARRAY_SIZE(d->matches); i++) { | |
270 | + int s = d->matches[i].slot; | |
271 | + if (s == DMI_NONE) | |
272 | + continue; | |
273 | + if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr)) | |
274 | + continue; | |
275 | + /* No match */ | |
276 | + goto fail; | |
277 | + } | |
278 | + count++; | |
279 | + if (d->callback && d->callback(d)) | |
280 | + break; | |
281 | +fail: d++; | |
282 | + } | |
283 | + | |
284 | + return count; | |
285 | +} | |
286 | +EXPORT_SYMBOL(dmi_check_system); | |
287 | + | |
288 | +/** | |
289 | + * dmi_get_system_info - return DMI data value | |
290 | + * @field: data index (see enum dmi_filed) | |
291 | + * | |
292 | + * Returns one DMI data value, can be used to perform | |
293 | + * complex DMI data checks. | |
294 | + */ | |
295 | +char *dmi_get_system_info(int field) | |
296 | +{ | |
297 | + return dmi_ident[field]; | |
298 | +} | |
299 | +EXPORT_SYMBOL(dmi_get_system_info); | |
300 | + | |
301 | +/** | |
302 | + * dmi_find_device - find onboard device by type/name | |
303 | + * @type: device type or %DMI_DEV_TYPE_ANY to match all device types | |
304 | + * @desc: device name string or %NULL to match all | |
305 | + * @from: previous device found in search, or %NULL for new search. | |
306 | + * | |
307 | + * Iterates through the list of known onboard devices. If a device is | |
308 | + * found with a matching @vendor and @device, a pointer to its device | |
309 | + * structure is returned. Otherwise, %NULL is returned. | |
310 | + * A new search is initiated by passing %NULL to the @from argument. | |
311 | + * If @from is not %NULL, searches continue from next device. | |
312 | + */ | |
313 | +struct dmi_device * dmi_find_device(int type, const char *name, | |
314 | + struct dmi_device *from) | |
315 | +{ | |
316 | + struct list_head *d, *head = from ? &from->list : &dmi_devices; | |
317 | + | |
318 | + for(d = head->next; d != &dmi_devices; d = d->next) { | |
319 | + struct dmi_device *dev = list_entry(d, struct dmi_device, list); | |
320 | + | |
321 | + if (((type == DMI_DEV_TYPE_ANY) || (dev->type == type)) && | |
322 | + ((name == NULL) || (strcmp(dev->name, name) == 0))) | |
323 | + return dev; | |
324 | + } | |
325 | + | |
326 | + return NULL; | |
327 | +} | |
328 | +EXPORT_SYMBOL(dmi_find_device); | |
329 | + | |
330 | +/** | |
331 | + * dmi_get_year - Return year of a DMI date | |
332 | + * @field: data index (like dmi_get_system_info) | |
333 | + * | |
334 | + * Returns -1 when the field doesn't exist. 0 when it is broken. | |
335 | + */ | |
336 | +int dmi_get_year(int field) | |
337 | +{ | |
338 | + int year; | |
339 | + char *s = dmi_get_system_info(field); | |
340 | + | |
341 | + if (!s) | |
342 | + return -1; | |
343 | + if (*s == '\0') | |
344 | + return 0; | |
345 | + s = strrchr(s, '/'); | |
346 | + if (!s) | |
347 | + return 0; | |
348 | + | |
349 | + s += 1; | |
350 | + year = simple_strtoul(s, NULL, 0); | |
351 | + if (year && year < 100) { /* 2-digit year */ | |
352 | + year += 1900; | |
353 | + if (year < 1996) /* no dates < spec 1.0 */ | |
354 | + year += 100; | |
355 | + } | |
356 | + | |
357 | + return year; | |
358 | +} |