aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/dmi_scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/dmi_scan.c')
-rw-r--r--arch/i386/kernel/dmi_scan.c123
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
9static char * __init dmi_string(struct dmi_header *dm, u8 s) 11static 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
187void __init dmi_scan_machine(void) 189static 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]; 214void __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");
224out: 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}
301EXPORT_SYMBOL(dmi_find_device); 328EXPORT_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 */
336int 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}