dmi_scan.c revision ebad6a4230bdb5927495e28bc7837f515bf667a7
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/bootmem.h> 7 8 9static char * __init dmi_string(struct dmi_header *dm, u8 s) 10{ 11 u8 *bp = ((u8 *) dm) + dm->length; 12 char *str = ""; 13 14 if (s) { 15 s--; 16 while (s > 0 && *bp) { 17 bp += strlen(bp) + 1; 18 s--; 19 } 20 21 if (*bp != 0) { 22 str = alloc_bootmem(strlen(bp) + 1); 23 if (str != NULL) 24 strcpy(str, bp); 25 else 26 printk(KERN_ERR "dmi_string: out of memory.\n"); 27 } 28 } 29 30 return str; 31} 32 33/* 34 * We have to be cautious here. We have seen BIOSes with DMI pointers 35 * pointing to completely the wrong place for example 36 */ 37static int __init dmi_table(u32 base, int len, int num, 38 void (*decode)(struct dmi_header *)) 39{ 40 u8 *buf, *data; 41 int i = 0; 42 43 buf = bt_ioremap(base, len); 44 if (buf == NULL) 45 return -1; 46 47 data = buf; 48 49 /* 50 * Stop when we see all the items the table claimed to have 51 * OR we run off the end of the table (also happens) 52 */ 53 while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) { 54 struct dmi_header *dm = (struct dmi_header *)data; 55 /* 56 * We want to know the total length (formated area and strings) 57 * before decoding to make sure we won't run off the table in 58 * dmi_decode or dmi_string 59 */ 60 data += dm->length; 61 while ((data - buf < len - 1) && (data[0] || data[1])) 62 data++; 63 if (data - buf < len - 1) 64 decode(dm); 65 data += 2; 66 i++; 67 } 68 bt_iounmap(buf, len); 69 return 0; 70} 71 72static int __init dmi_checksum(u8 *buf) 73{ 74 u8 sum = 0; 75 int a; 76 77 for (a = 0; a < 15; a++) 78 sum += buf[a]; 79 80 return sum == 0; 81} 82 83static char *dmi_ident[DMI_STRING_MAX]; 84static LIST_HEAD(dmi_devices); 85 86/* 87 * Save a DMI string 88 */ 89static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) 90{ 91 char *p, *d = (char*) dm; 92 93 if (dmi_ident[slot]) 94 return; 95 96 p = dmi_string(dm, d[string]); 97 if (p == NULL) 98 return; 99 100 dmi_ident[slot] = p; 101} 102 103static void __init dmi_save_devices(struct dmi_header *dm) 104{ 105 int i, count = (dm->length - sizeof(struct dmi_header)) / 2; 106 struct dmi_device *dev; 107 108 for (i = 0; i < count; i++) { 109 char *d = ((char *) dm) + (i * 2); 110 111 /* Skip disabled device */ 112 if ((*d & 0x80) == 0) 113 continue; 114 115 dev = alloc_bootmem(sizeof(*dev)); 116 if (!dev) { 117 printk(KERN_ERR "dmi_save_devices: out of memory.\n"); 118 break; 119 } 120 121 dev->type = *d++ & 0x7f; 122 dev->name = dmi_string(dm, *d); 123 dev->device_data = NULL; 124 125 list_add(&dev->list, &dmi_devices); 126 } 127} 128 129static void __init dmi_save_ipmi_device(struct dmi_header *dm) 130{ 131 struct dmi_device *dev; 132 void * data; 133 134 data = alloc_bootmem(dm->length); 135 if (data == NULL) { 136 printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n"); 137 return; 138 } 139 140 memcpy(data, dm, dm->length); 141 142 dev = alloc_bootmem(sizeof(*dev)); 143 if (!dev) { 144 printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n"); 145 return; 146 } 147 148 dev->type = DMI_DEV_TYPE_IPMI; 149 dev->name = "IPMI controller"; 150 dev->device_data = data; 151 152 list_add(&dev->list, &dmi_devices); 153} 154 155/* 156 * Process a DMI table entry. Right now all we care about are the BIOS 157 * and machine entries. For 2.5 we should pull the smbus controller info 158 * out of here. 159 */ 160static void __init dmi_decode(struct dmi_header *dm) 161{ 162 switch(dm->type) { 163 case 0: /* BIOS Information */ 164 dmi_save_ident(dm, DMI_BIOS_VENDOR, 4); 165 dmi_save_ident(dm, DMI_BIOS_VERSION, 5); 166 dmi_save_ident(dm, DMI_BIOS_DATE, 8); 167 break; 168 case 1: /* System Information */ 169 dmi_save_ident(dm, DMI_SYS_VENDOR, 4); 170 dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); 171 dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); 172 dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7); 173 break; 174 case 2: /* Base Board Information */ 175 dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); 176 dmi_save_ident(dm, DMI_BOARD_NAME, 5); 177 dmi_save_ident(dm, DMI_BOARD_VERSION, 6); 178 break; 179 case 10: /* Onboard Devices Information */ 180 dmi_save_devices(dm); 181 break; 182 case 38: /* IPMI Device Information */ 183 dmi_save_ipmi_device(dm); 184 } 185} 186 187void __init dmi_scan_machine(void) 188{ 189 u8 buf[15]; 190 char __iomem *p, *q; 191 192 /* 193 * no iounmap() for that ioremap(); it would be a no-op, but it's 194 * so early in setup that sucker gets confused into doing what 195 * it shouldn't if we actually call it. 196 */ 197 p = ioremap(0xF0000, 0x10000); 198 if (p == NULL) 199 goto out; 200 201 for (q = p; q < p + 0x10000; q += 16) { 202 memcpy_fromio(buf, q, 15); 203 if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) { 204 u16 num = (buf[13] << 8) | buf[12]; 205 u16 len = (buf[7] << 8) | buf[6]; 206 u32 base = (buf[11] << 24) | (buf[10] << 16) | 207 (buf[9] << 8) | buf[8]; 208 209 /* 210 * DMI version 0.0 means that the real version is taken from 211 * the SMBIOS version, which we don't know at this point. 212 */ 213 if (buf[14] != 0) 214 printk(KERN_INFO "DMI %d.%d present.\n", 215 buf[14] >> 4, buf[14] & 0xF); 216 else 217 printk(KERN_INFO "DMI present.\n"); 218 219 if (dmi_table(base,len, num, dmi_decode) == 0) 220 return; 221 } 222 } 223 224out: printk(KERN_INFO "DMI not present.\n"); 225} 226 227 228/** 229 * dmi_check_system - check system DMI data 230 * @list: array of dmi_system_id structures to match against 231 * 232 * Walk the blacklist table running matching functions until someone 233 * returns non zero or we hit the end. Callback function is called for 234 * each successfull match. Returns the number of matches. 235 */ 236int dmi_check_system(struct dmi_system_id *list) 237{ 238 int i, count = 0; 239 struct dmi_system_id *d = list; 240 241 while (d->ident) { 242 for (i = 0; i < ARRAY_SIZE(d->matches); i++) { 243 int s = d->matches[i].slot; 244 if (s == DMI_NONE) 245 continue; 246 if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr)) 247 continue; 248 /* No match */ 249 goto fail; 250 } 251 if (d->callback && d->callback(d)) 252 break; 253 count++; 254fail: d++; 255 } 256 257 return count; 258} 259EXPORT_SYMBOL(dmi_check_system); 260 261/** 262 * dmi_get_system_info - return DMI data value 263 * @field: data index (see enum dmi_filed) 264 * 265 * Returns one DMI data value, can be used to perform 266 * complex DMI data checks. 267 */ 268char *dmi_get_system_info(int field) 269{ 270 return dmi_ident[field]; 271} 272EXPORT_SYMBOL(dmi_get_system_info); 273 274/** 275 * dmi_find_device - find onboard device by type/name 276 * @type: device type or %DMI_DEV_TYPE_ANY to match all device types 277 * @desc: device name string or %NULL to match all 278 * @from: previous device found in search, or %NULL for new search. 279 * 280 * Iterates through the list of known onboard devices. If a device is 281 * found with a matching @vendor and @device, a pointer to its device 282 * structure is returned. Otherwise, %NULL is returned. 283 * A new search is initiated by passing %NULL to the @from argument. 284 * If @from is not %NULL, searches continue from next device. 285 */ 286struct dmi_device * dmi_find_device(int type, const char *name, 287 struct dmi_device *from) 288{ 289 struct list_head *d, *head = from ? &from->list : &dmi_devices; 290 291 for(d = head->next; d != &dmi_devices; d = d->next) { 292 struct dmi_device *dev = list_entry(d, struct dmi_device, list); 293 294 if (((type == DMI_DEV_TYPE_ANY) || (dev->type == type)) && 295 ((name == NULL) || (strcmp(dev->name, name) == 0))) 296 return dev; 297 } 298 299 return NULL; 300} 301EXPORT_SYMBOL(dmi_find_device); 302