diff options
Diffstat (limited to 'arch/i386/kernel/dmi_scan.c')
-rw-r--r-- | arch/i386/kernel/dmi_scan.c | 123 |
1 files changed, 90 insertions, 33 deletions
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c index 6a93d75db431..5efceebc48dc 100644 --- a/arch/i386/kernel/dmi_scan.c +++ b/arch/i386/kernel/dmi_scan.c | |||
@@ -3,8 +3,10 @@ | |||
3 | #include <linux/init.h> | 3 | #include <linux/init.h> |
4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
5 | #include <linux/dmi.h> | 5 | #include <linux/dmi.h> |
6 | #include <linux/efi.h> | ||
6 | #include <linux/bootmem.h> | 7 | #include <linux/bootmem.h> |
7 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
9 | #include <asm/dmi.h> | ||
8 | 10 | ||
9 | static char * __init dmi_string(struct dmi_header *dm, u8 s) | 11 | static char * __init dmi_string(struct dmi_header *dm, u8 s) |
10 | { | 12 | { |
@@ -106,7 +108,7 @@ static void __init dmi_save_devices(struct dmi_header *dm) | |||
106 | struct dmi_device *dev; | 108 | struct dmi_device *dev; |
107 | 109 | ||
108 | for (i = 0; i < count; i++) { | 110 | for (i = 0; i < count; i++) { |
109 | char *d = ((char *) dm) + (i * 2); | 111 | char *d = (char *)(dm + 1) + (i * 2); |
110 | 112 | ||
111 | /* Skip disabled device */ | 113 | /* Skip disabled device */ |
112 | if ((*d & 0x80) == 0) | 114 | if ((*d & 0x80) == 0) |
@@ -184,47 +186,72 @@ static void __init dmi_decode(struct dmi_header *dm) | |||
184 | } | 186 | } |
185 | } | 187 | } |
186 | 188 | ||
187 | void __init dmi_scan_machine(void) | 189 | static int __init dmi_present(char __iomem *p) |
188 | { | 190 | { |
189 | u8 buf[15]; | 191 | u8 buf[15]; |
190 | char __iomem *p, *q; | 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]; | ||
191 | 198 | ||
192 | /* | 199 | /* |
193 | * no iounmap() for that ioremap(); it would be a no-op, but it's | 200 | * DMI version 0.0 means that the real version is taken from |
194 | * so early in setup that sucker gets confused into doing what | 201 | * the SMBIOS version, which we don't know at this point. |
195 | * it shouldn't if we actually call it. | 202 | */ |
196 | */ | 203 | if (buf[14] != 0) |
197 | p = ioremap(0xF0000, 0x10000); | 204 | printk(KERN_INFO "DMI %d.%d present.\n", |
198 | if (p == NULL) | 205 | buf[14] >> 4, buf[14] & 0xF); |
199 | goto out; | 206 | else |
200 | 207 | printk(KERN_INFO "DMI present.\n"); | |
201 | for (q = p; q < p + 0x10000; q += 16) { | 208 | if (dmi_table(base,len, num, dmi_decode) == 0) |
202 | memcpy_fromio(buf, q, 15); | 209 | return 0; |
203 | if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) { | 210 | } |
204 | u16 num = (buf[13] << 8) | buf[12]; | 211 | return 1; |
205 | u16 len = (buf[7] << 8) | buf[6]; | 212 | } |
206 | u32 base = (buf[11] << 24) | (buf[10] << 16) | | 213 | |
207 | (buf[9] << 8) | buf[8]; | 214 | void __init dmi_scan_machine(void) |
208 | 215 | { | |
209 | /* | 216 | char __iomem *p, *q; |
210 | * DMI version 0.0 means that the real version is taken from | 217 | int rc; |
211 | * the SMBIOS version, which we don't know at this point. | 218 | |
212 | */ | 219 | if (efi_enabled) { |
213 | if (buf[14] != 0) | 220 | if (efi.smbios == EFI_INVALID_TABLE_ADDR) |
214 | printk(KERN_INFO "DMI %d.%d present.\n", | 221 | goto out; |
215 | buf[14] >> 4, buf[14] & 0xF); | 222 | |
216 | else | 223 | /* This is called as a core_initcall() because it isn't |
217 | printk(KERN_INFO "DMI present.\n"); | 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; | ||
218 | 245 | ||
219 | if (dmi_table(base,len, num, dmi_decode) == 0) | 246 | for (q = p; q < p + 0x10000; q += 16) { |
247 | rc = dmi_present(q); | ||
248 | if (!rc) | ||
220 | return; | 249 | return; |
221 | } | 250 | } |
222 | } | 251 | } |
223 | 252 | out: printk(KERN_INFO "DMI not present or invalid.\n"); | |
224 | out: printk(KERN_INFO "DMI not present or invalid.\n"); | ||
225 | } | 253 | } |
226 | 254 | ||
227 | |||
228 | /** | 255 | /** |
229 | * dmi_check_system - check system DMI data | 256 | * dmi_check_system - check system DMI data |
230 | * @list: array of dmi_system_id structures to match against | 257 | * @list: array of dmi_system_id structures to match against |
@@ -299,3 +326,33 @@ struct dmi_device * dmi_find_device(int type, const char *name, | |||
299 | return NULL; | 326 | return NULL; |
300 | } | 327 | } |
301 | EXPORT_SYMBOL(dmi_find_device); | 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 | } | ||