/arch/i386/kernel/dmi_scan.c

https://bitbucket.org/evzijst/gittest · C · 487 lines · 338 code · 69 blank · 80 comment · 40 complexity · 3ce2cf3715450886fe83387bfd37c34d MD5 · raw file

  1. #include <linux/types.h>
  2. #include <linux/kernel.h>
  3. #include <linux/string.h>
  4. #include <linux/init.h>
  5. #include <linux/module.h>
  6. #include <linux/slab.h>
  7. #include <linux/acpi.h>
  8. #include <asm/io.h>
  9. #include <linux/pm.h>
  10. #include <asm/system.h>
  11. #include <linux/dmi.h>
  12. #include <linux/bootmem.h>
  13. struct dmi_header
  14. {
  15. u8 type;
  16. u8 length;
  17. u16 handle;
  18. };
  19. #undef DMI_DEBUG
  20. #ifdef DMI_DEBUG
  21. #define dmi_printk(x) printk x
  22. #else
  23. #define dmi_printk(x)
  24. #endif
  25. static char * __init dmi_string(struct dmi_header *dm, u8 s)
  26. {
  27. u8 *bp=(u8 *)dm;
  28. bp+=dm->length;
  29. if(!s)
  30. return "";
  31. s--;
  32. while(s>0 && *bp)
  33. {
  34. bp+=strlen(bp);
  35. bp++;
  36. s--;
  37. }
  38. return bp;
  39. }
  40. /*
  41. * We have to be cautious here. We have seen BIOSes with DMI pointers
  42. * pointing to completely the wrong place for example
  43. */
  44. static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
  45. {
  46. u8 *buf;
  47. struct dmi_header *dm;
  48. u8 *data;
  49. int i=0;
  50. buf = bt_ioremap(base, len);
  51. if(buf==NULL)
  52. return -1;
  53. data = buf;
  54. /*
  55. * Stop when we see all the items the table claimed to have
  56. * OR we run off the end of the table (also happens)
  57. */
  58. while(i<num && data-buf+sizeof(struct dmi_header)<=len)
  59. {
  60. dm=(struct dmi_header *)data;
  61. /*
  62. * We want to know the total length (formated area and strings)
  63. * before decoding to make sure we won't run off the table in
  64. * dmi_decode or dmi_string
  65. */
  66. data+=dm->length;
  67. while(data-buf<len-1 && (data[0] || data[1]))
  68. data++;
  69. if(data-buf<len-1)
  70. decode(dm);
  71. data+=2;
  72. i++;
  73. }
  74. bt_iounmap(buf, len);
  75. return 0;
  76. }
  77. inline static int __init dmi_checksum(u8 *buf)
  78. {
  79. u8 sum=0;
  80. int a;
  81. for(a=0; a<15; a++)
  82. sum+=buf[a];
  83. return (sum==0);
  84. }
  85. static int __init dmi_iterate(void (*decode)(struct dmi_header *))
  86. {
  87. u8 buf[15];
  88. char __iomem *p, *q;
  89. /*
  90. * no iounmap() for that ioremap(); it would be a no-op, but it's
  91. * so early in setup that sucker gets confused into doing what
  92. * it shouldn't if we actually call it.
  93. */
  94. p = ioremap(0xF0000, 0x10000);
  95. if (p == NULL)
  96. return -1;
  97. for (q = p; q < p + 0x10000; q += 16) {
  98. memcpy_fromio(buf, q, 15);
  99. if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
  100. {
  101. u16 num=buf[13]<<8|buf[12];
  102. u16 len=buf[7]<<8|buf[6];
  103. u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
  104. /*
  105. * DMI version 0.0 means that the real version is taken from
  106. * the SMBIOS version, which we don't know at this point.
  107. */
  108. if(buf[14]!=0)
  109. printk(KERN_INFO "DMI %d.%d present.\n",
  110. buf[14]>>4, buf[14]&0x0F);
  111. else
  112. printk(KERN_INFO "DMI present.\n");
  113. dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
  114. num, len));
  115. dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
  116. base));
  117. if(dmi_table(base,len, num, decode)==0)
  118. return 0;
  119. }
  120. }
  121. return -1;
  122. }
  123. static char *dmi_ident[DMI_STRING_MAX];
  124. /*
  125. * Save a DMI string
  126. */
  127. static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
  128. {
  129. char *d = (char*)dm;
  130. char *p = dmi_string(dm, d[string]);
  131. if(p==NULL || *p == 0)
  132. return;
  133. if (dmi_ident[slot])
  134. return;
  135. dmi_ident[slot] = alloc_bootmem(strlen(p)+1);
  136. if(dmi_ident[slot])
  137. strcpy(dmi_ident[slot], p);
  138. else
  139. printk(KERN_ERR "dmi_save_ident: out of memory.\n");
  140. }
  141. /*
  142. * Ugly compatibility crap.
  143. */
  144. #define dmi_blacklist dmi_system_id
  145. #define NO_MATCH { DMI_NONE, NULL}
  146. #define MATCH DMI_MATCH
  147. /*
  148. * Toshiba keyboard likes to repeat keys when they are not repeated.
  149. */
  150. static __init int broken_toshiba_keyboard(struct dmi_blacklist *d)
  151. {
  152. printk(KERN_WARNING "Toshiba with broken keyboard detected. If your keyboard sometimes generates 3 keypresses instead of one, see http://davyd.ucc.asn.au/projects/toshiba/README\n");
  153. return 0;
  154. }
  155. #ifdef CONFIG_ACPI_SLEEP
  156. static __init int reset_videomode_after_s3(struct dmi_blacklist *d)
  157. {
  158. /* See acpi_wakeup.S */
  159. extern long acpi_video_flags;
  160. acpi_video_flags |= 2;
  161. return 0;
  162. }
  163. #endif
  164. #ifdef CONFIG_ACPI_BOOT
  165. extern int acpi_force;
  166. static __init __attribute__((unused)) int dmi_disable_acpi(struct dmi_blacklist *d)
  167. {
  168. if (!acpi_force) {
  169. printk(KERN_NOTICE "%s detected: acpi off\n",d->ident);
  170. disable_acpi();
  171. } else {
  172. printk(KERN_NOTICE
  173. "Warning: DMI blacklist says broken, but acpi forced\n");
  174. }
  175. return 0;
  176. }
  177. /*
  178. * Limit ACPI to CPU enumeration for HT
  179. */
  180. static __init __attribute__((unused)) int force_acpi_ht(struct dmi_blacklist *d)
  181. {
  182. if (!acpi_force) {
  183. printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident);
  184. disable_acpi();
  185. acpi_ht = 1;
  186. } else {
  187. printk(KERN_NOTICE
  188. "Warning: acpi=force overrules DMI blacklist: acpi=ht\n");
  189. }
  190. return 0;
  191. }
  192. #endif
  193. #ifdef CONFIG_ACPI_PCI
  194. static __init int disable_acpi_irq(struct dmi_blacklist *d)
  195. {
  196. if (!acpi_force) {
  197. printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n",
  198. d->ident);
  199. acpi_noirq_set();
  200. }
  201. return 0;
  202. }
  203. static __init int disable_acpi_pci(struct dmi_blacklist *d)
  204. {
  205. if (!acpi_force) {
  206. printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n",
  207. d->ident);
  208. acpi_disable_pci();
  209. }
  210. return 0;
  211. }
  212. #endif
  213. /*
  214. * Process the DMI blacklists
  215. */
  216. /*
  217. * This will be expanded over time to force things like the APM
  218. * interrupt mask settings according to the laptop
  219. */
  220. static __initdata struct dmi_blacklist dmi_blacklist[]={
  221. { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
  222. MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
  223. NO_MATCH, NO_MATCH, NO_MATCH
  224. } },
  225. #ifdef CONFIG_ACPI_SLEEP
  226. { reset_videomode_after_s3, "Toshiba Satellite 4030cdt", { /* Reset video mode after returning from ACPI S3 sleep */
  227. MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
  228. NO_MATCH, NO_MATCH, NO_MATCH
  229. } },
  230. #endif
  231. #ifdef CONFIG_ACPI_BOOT
  232. /*
  233. * If your system is blacklisted here, but you find that acpi=force
  234. * works for you, please contact acpi-devel@sourceforge.net
  235. */
  236. /*
  237. * Boxes that need ACPI disabled
  238. */
  239. { dmi_disable_acpi, "IBM Thinkpad", {
  240. MATCH(DMI_BOARD_VENDOR, "IBM"),
  241. MATCH(DMI_BOARD_NAME, "2629H1G"),
  242. NO_MATCH, NO_MATCH }},
  243. /*
  244. * Boxes that need acpi=ht
  245. */
  246. { force_acpi_ht, "FSC Primergy T850", {
  247. MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
  248. MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
  249. NO_MATCH, NO_MATCH }},
  250. { force_acpi_ht, "DELL GX240", {
  251. MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
  252. MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
  253. NO_MATCH, NO_MATCH }},
  254. { force_acpi_ht, "HP VISUALIZE NT Workstation", {
  255. MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
  256. MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
  257. NO_MATCH, NO_MATCH }},
  258. { force_acpi_ht, "Compaq Workstation W8000", {
  259. MATCH(DMI_SYS_VENDOR, "Compaq"),
  260. MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
  261. NO_MATCH, NO_MATCH }},
  262. { force_acpi_ht, "ASUS P4B266", {
  263. MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
  264. MATCH(DMI_BOARD_NAME, "P4B266"),
  265. NO_MATCH, NO_MATCH }},
  266. { force_acpi_ht, "ASUS P2B-DS", {
  267. MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
  268. MATCH(DMI_BOARD_NAME, "P2B-DS"),
  269. NO_MATCH, NO_MATCH }},
  270. { force_acpi_ht, "ASUS CUR-DLS", {
  271. MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
  272. MATCH(DMI_BOARD_NAME, "CUR-DLS"),
  273. NO_MATCH, NO_MATCH }},
  274. { force_acpi_ht, "ABIT i440BX-W83977", {
  275. MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
  276. MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
  277. NO_MATCH, NO_MATCH }},
  278. { force_acpi_ht, "IBM Bladecenter", {
  279. MATCH(DMI_BOARD_VENDOR, "IBM"),
  280. MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
  281. NO_MATCH, NO_MATCH }},
  282. { force_acpi_ht, "IBM eServer xSeries 360", {
  283. MATCH(DMI_BOARD_VENDOR, "IBM"),
  284. MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
  285. NO_MATCH, NO_MATCH }},
  286. { force_acpi_ht, "IBM eserver xSeries 330", {
  287. MATCH(DMI_BOARD_VENDOR, "IBM"),
  288. MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
  289. NO_MATCH, NO_MATCH }},
  290. { force_acpi_ht, "IBM eserver xSeries 440", {
  291. MATCH(DMI_BOARD_VENDOR, "IBM"),
  292. MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
  293. NO_MATCH, NO_MATCH }},
  294. #endif // CONFIG_ACPI_BOOT
  295. #ifdef CONFIG_ACPI_PCI
  296. /*
  297. * Boxes that need ACPI PCI IRQ routing disabled
  298. */
  299. { disable_acpi_irq, "ASUS A7V", {
  300. MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
  301. MATCH(DMI_BOARD_NAME, "<A7V>"),
  302. /* newer BIOS, Revision 1011, does work */
  303. MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
  304. NO_MATCH }},
  305. /*
  306. * Boxes that need ACPI PCI IRQ routing and PCI scan disabled
  307. */
  308. { disable_acpi_pci, "ASUS PR-DLS", { /* _BBN 0 bug */
  309. MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
  310. MATCH(DMI_BOARD_NAME, "PR-DLS"),
  311. MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
  312. MATCH(DMI_BIOS_DATE, "03/21/2003") }},
  313. { disable_acpi_pci, "Acer TravelMate 36x Laptop", {
  314. MATCH(DMI_SYS_VENDOR, "Acer"),
  315. MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
  316. NO_MATCH, NO_MATCH
  317. } },
  318. #endif
  319. { NULL, }
  320. };
  321. /*
  322. * Process a DMI table entry. Right now all we care about are the BIOS
  323. * and machine entries. For 2.5 we should pull the smbus controller info
  324. * out of here.
  325. */
  326. static void __init dmi_decode(struct dmi_header *dm)
  327. {
  328. #ifdef DMI_DEBUG
  329. u8 *data = (u8 *)dm;
  330. #endif
  331. switch(dm->type)
  332. {
  333. case 0:
  334. dmi_printk(("BIOS Vendor: %s\n",
  335. dmi_string(dm, data[4])));
  336. dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
  337. dmi_printk(("BIOS Version: %s\n",
  338. dmi_string(dm, data[5])));
  339. dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
  340. dmi_printk(("BIOS Release: %s\n",
  341. dmi_string(dm, data[8])));
  342. dmi_save_ident(dm, DMI_BIOS_DATE, 8);
  343. break;
  344. case 1:
  345. dmi_printk(("System Vendor: %s\n",
  346. dmi_string(dm, data[4])));
  347. dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
  348. dmi_printk(("Product Name: %s\n",
  349. dmi_string(dm, data[5])));
  350. dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
  351. dmi_printk(("Version: %s\n",
  352. dmi_string(dm, data[6])));
  353. dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
  354. dmi_printk(("Serial Number: %s\n",
  355. dmi_string(dm, data[7])));
  356. break;
  357. case 2:
  358. dmi_printk(("Board Vendor: %s\n",
  359. dmi_string(dm, data[4])));
  360. dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
  361. dmi_printk(("Board Name: %s\n",
  362. dmi_string(dm, data[5])));
  363. dmi_save_ident(dm, DMI_BOARD_NAME, 5);
  364. dmi_printk(("Board Version: %s\n",
  365. dmi_string(dm, data[6])));
  366. dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
  367. break;
  368. }
  369. }
  370. void __init dmi_scan_machine(void)
  371. {
  372. int err = dmi_iterate(dmi_decode);
  373. if(err == 0)
  374. dmi_check_system(dmi_blacklist);
  375. else
  376. printk(KERN_INFO "DMI not present.\n");
  377. }
  378. /**
  379. * dmi_check_system - check system DMI data
  380. * @list: array of dmi_system_id structures to match against
  381. *
  382. * Walk the blacklist table running matching functions until someone
  383. * returns non zero or we hit the end. Callback function is called for
  384. * each successfull match. Returns the number of matches.
  385. */
  386. int dmi_check_system(struct dmi_system_id *list)
  387. {
  388. int i, count = 0;
  389. struct dmi_system_id *d = list;
  390. while (d->ident) {
  391. for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
  392. int s = d->matches[i].slot;
  393. if (s == DMI_NONE)
  394. continue;
  395. if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
  396. continue;
  397. /* No match */
  398. goto fail;
  399. }
  400. if (d->callback && d->callback(d))
  401. break;
  402. count++;
  403. fail: d++;
  404. }
  405. return count;
  406. }
  407. EXPORT_SYMBOL(dmi_check_system);
  408. /**
  409. * dmi_get_system_info - return DMI data value
  410. * @field: data index (see enum dmi_filed)
  411. *
  412. * Returns one DMI data value, can be used to perform
  413. * complex DMI data checks.
  414. */
  415. char * dmi_get_system_info(int field)
  416. {
  417. return dmi_ident[field];
  418. }