1 /* 2 * blacklist.c 3 * 4 * Check to see if the given machine has a known bad ACPI BIOS 5 * or if the BIOS is too old. 6 * 7 * Copyright (C) 2004 Len Brown <len.brown@intel.com> 8 * Copyright (C) 2002 Andy Grover <andrew.grover@intel.com> 9 * 10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or (at 15 * your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, but 18 * WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License along 23 * with this program; if not, write to the Free Software Foundation, Inc., 24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 25 * 26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 */ 28 29 30 #include <linux/kernel.h> 31 #include <linux/module.h> 32 #include <linux/init.h> 33 #include <linux/acpi.h> 34 #include <acpi/acpi_bus.h> 35 #include <linux/dmi.h> 36 37 enum acpi_blacklist_predicates 38 { 39 all_versions, 40 less_than_or_equal, 41 equal, 42 greater_than_or_equal, 43 }; 44 45 struct acpi_blacklist_item 46 { 47 char oem_id[7]; 48 char oem_table_id[9]; 49 u32 oem_revision; 50 acpi_table_type table; 51 enum acpi_blacklist_predicates oem_revision_predicate; 52 char *reason; 53 u32 is_critical_error; 54 }; 55 56 /* 57 * POLICY: If *anything* doesn't work, put it on the blacklist. 58 * If they are critical errors, mark it critical, and abort driver load. 59 */ 60 static struct acpi_blacklist_item acpi_blacklist[] __initdata = 61 { 62 /* Compaq Presario 1700 */ 63 {"PTLTD ", " DSDT ", 0x06040000, ACPI_DSDT, less_than_or_equal, "Multiple problems", 1}, 64 /* Sony FX120, FX140, FX150? */ 65 {"SONY ", "U0 ", 0x20010313, ACPI_DSDT, less_than_or_equal, "ACPI driver problem", 1}, 66 /* Compaq Presario 800, Insyde BIOS */ 67 {"INT440", "SYSFexxx", 0x00001001, ACPI_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1}, 68 /* IBM 600E - _ADR should return 7, but it returns 1 */ 69 {"IBM ", "TP600E ", 0x00000105, ACPI_DSDT, less_than_or_equal, "Incorrect _ADR", 1}, 70 {"ASUS\0\0", "P2B-S ", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1}, 71 72 {""} 73 }; 74 75 76 #if CONFIG_ACPI_BLACKLIST_YEAR 77 78 static int __init 79 blacklist_by_year(void) 80 { 81 int year; 82 char *s = dmi_get_system_info(DMI_BIOS_DATE); 83 84 if (!s) 85 return 0; 86 if (!*s) 87 return 0; 88 89 s = strrchr(s, '/'); 90 if (!s) 91 return 0; 92 93 s += 1; 94 95 year = simple_strtoul(s,NULL,0); 96 97 if (year < 100) { /* 2-digit year */ 98 year += 1900; 99 if (year < 1996) /* no dates < spec 1.0 */ 100 year += 100; 101 } 102 103 if (year < CONFIG_ACPI_BLACKLIST_YEAR) { 104 printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), " 105 "acpi=force is required to enable ACPI\n", 106 year, CONFIG_ACPI_BLACKLIST_YEAR); 107 return 1; 108 } 109 return 0; 110 } 111 #else 112 static inline int blacklist_by_year(void) { return 0; } 113 #endif 114 115 int __init 116 acpi_blacklisted(void) 117 { 118 int i = 0; 119 int blacklisted = 0; 120 struct acpi_table_header *table_header; 121 122 while (acpi_blacklist[i].oem_id[0] != '\0') 123 { 124 if (acpi_get_table_header_early(acpi_blacklist[i].table, &table_header)) { 125 i++; 126 continue; 127 } 128 129 if (strncmp(acpi_blacklist[i].oem_id, table_header->oem_id, 6)) { 130 i++; 131 continue; 132 } 133 134 if (strncmp(acpi_blacklist[i].oem_table_id, table_header->oem_table_id, 8)) { 135 i++; 136 continue; 137 } 138 139 if ((acpi_blacklist[i].oem_revision_predicate == all_versions) 140 || (acpi_blacklist[i].oem_revision_predicate == less_than_or_equal 141 && table_header->oem_revision <= acpi_blacklist[i].oem_revision) 142 || (acpi_blacklist[i].oem_revision_predicate == greater_than_or_equal 143 && table_header->oem_revision >= acpi_blacklist[i].oem_revision) 144 || (acpi_blacklist[i].oem_revision_predicate == equal 145 && table_header->oem_revision == acpi_blacklist[i].oem_revision)) { 146 147 printk(KERN_ERR PREFIX "Vendor \"%6.6s\" System \"%8.8s\" " 148 "Revision 0x%x has a known ACPI BIOS problem.\n", 149 acpi_blacklist[i].oem_id, 150 acpi_blacklist[i].oem_table_id, 151 acpi_blacklist[i].oem_revision); 152 153 printk(KERN_ERR PREFIX "Reason: %s. This is a %s error\n", 154 acpi_blacklist[i].reason, 155 (acpi_blacklist[i].is_critical_error ? "non-recoverable" : "recoverable")); 156 157 blacklisted = acpi_blacklist[i].is_critical_error; 158 break; 159 } 160 else { 161 i++; 162 } 163 } 164 165 blacklisted += blacklist_by_year(); 166 167 return blacklisted; 168 } 169 170