1 | /* $NetBSD: acpi_quirks.c,v 1.20 2011/11/14 02:44:59 jmcneill Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. |
5 | * All rights reserved. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions |
9 | * are met: |
10 | * |
11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 | * SUCH DAMAGE. |
28 | */ |
29 | |
30 | /* |
31 | * Copyright 2002 Wasabi Systems, Inc. |
32 | * All rights reserved. |
33 | * |
34 | * Written by Frank van der Linden for Wasabi Systems, Inc. |
35 | * |
36 | * Redistribution and use in source and binary forms, with or without |
37 | * modification, are permitted provided that the following conditions |
38 | * are met: |
39 | * 1. Redistributions of source code must retain the above copyright |
40 | * notice, this list of conditions and the following disclaimer. |
41 | * 2. Redistributions in binary form must reproduce the above copyright |
42 | * notice, this list of conditions and the following disclaimer in the |
43 | * documentation and/or other materials provided with the distribution. |
44 | * 3. All advertising materials mentioning features or use of this software |
45 | * must display the following acknowledgement: |
46 | * This product includes software developed for the NetBSD Project by |
47 | * Wasabi Systems, Inc. |
48 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse |
49 | * or promote products derived from this software without specific prior |
50 | * written permission. |
51 | * |
52 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND |
53 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
54 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
55 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC |
56 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
57 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
58 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
59 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
60 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
61 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
62 | * POSSIBILITY OF SUCH DAMAGE. |
63 | */ |
64 | |
65 | #include <sys/cdefs.h> |
66 | |
67 | __KERNEL_RCSID(0, "$NetBSD: acpi_quirks.c,v 1.20 2011/11/14 02:44:59 jmcneill Exp $" ); |
68 | |
69 | #include "opt_acpi.h" |
70 | |
71 | #include <sys/param.h> |
72 | |
73 | #include <dev/acpi/acpireg.h> |
74 | #include <dev/acpi/acpivar.h> |
75 | |
76 | #define _COMPONENT ACPI_UTILITIES |
77 | ACPI_MODULE_NAME ("acpi_quirks" ) |
78 | |
79 | #define AQ_GT 0 /* > */ |
80 | #define AQ_LT 1 /* < */ |
81 | #define AQ_GTE 2 /* >= */ |
82 | #define AQ_LTE 3 /* <= */ |
83 | #define AQ_EQ 4 /* == */ |
84 | |
85 | static int acpi_quirks_revcmp(uint32_t, uint32_t, int); |
86 | |
87 | static struct acpi_quirk acpi_quirks[] = { |
88 | |
89 | { ACPI_SIG_FADT, "ASUS " , 0x30303031, AQ_LTE, "CUV4X-D " , |
90 | ACPI_QUIRK_BROKEN }, |
91 | |
92 | { ACPI_SIG_FADT, "PTLTD " , 0x06040000, AQ_LTE, " FACP " , |
93 | ACPI_QUIRK_BROKEN }, |
94 | |
95 | { ACPI_SIG_FADT, "NVIDIA" , 0x06040000, AQ_EQ, "CK8 " , |
96 | ACPI_QUIRK_IRQ0 }, |
97 | |
98 | { ACPI_SIG_FADT, "HP " , 0x06040012, AQ_LTE, "HWPC20F " , |
99 | ACPI_QUIRK_BROKEN }, |
100 | }; |
101 | |
102 | static int |
103 | acpi_quirks_revcmp(uint32_t tabval, uint32_t wanted, int op) |
104 | { |
105 | |
106 | switch (op) { |
107 | |
108 | case AQ_GT: |
109 | return (tabval > wanted) ? 0 : 1; |
110 | |
111 | case AQ_LT: |
112 | return (tabval < wanted) ? 0 : 1; |
113 | |
114 | case AQ_LTE: |
115 | return (tabval <= wanted) ? 0 : 1; |
116 | |
117 | case AQ_GTE: |
118 | return (tabval >= wanted) ? 0 : 1; |
119 | |
120 | case AQ_EQ: |
121 | return (tabval == wanted) ? 0 : 1; |
122 | |
123 | default: |
124 | return 1; |
125 | } |
126 | } |
127 | |
128 | #ifdef ACPI_BLACKLIST_YEAR |
129 | static int |
130 | acpi_quirks_bios_year(void) |
131 | { |
132 | const char *datestr = pmf_get_platform("bios-date" ); |
133 | unsigned long date; |
134 | |
135 | if (datestr == NULL) |
136 | return -1; |
137 | |
138 | date = strtoul(datestr, NULL, 10); |
139 | if (date == 0 || date == ULONG_MAX) |
140 | return -1; |
141 | if (date < 19000000 || date > 99999999) |
142 | return -1; |
143 | return date / 10000; |
144 | } |
145 | #endif |
146 | |
147 | /* |
148 | * Simple function to search the quirk table. Only to be |
149 | * used after AcpiLoadTables() has been successfully called. |
150 | */ |
151 | int |
152 | acpi_find_quirks(void) |
153 | { |
154 | ACPI_TABLE_HEADER fadt, dsdt, xsdt, *hdr; |
155 | struct acpi_quirk *aq; |
156 | ACPI_STATUS rv; |
157 | size_t i, len; |
158 | |
159 | #ifdef ACPI_BLACKLIST_YEAR |
160 | int year = acpi_quirks_bios_year(); |
161 | |
162 | if (year != -1 && year <= ACPI_BLACKLIST_YEAR) |
163 | return ACPI_QUIRK_OLDBIOS; |
164 | #endif |
165 | |
166 | rv = AcpiGetTableHeader(ACPI_SIG_FADT, 0, &fadt); |
167 | |
168 | if (ACPI_FAILURE(rv)) |
169 | (void)memset(&fadt, 0, sizeof(fadt)); |
170 | |
171 | rv = AcpiGetTableHeader(ACPI_SIG_DSDT, 0, &dsdt); |
172 | |
173 | if (ACPI_FAILURE(rv)) |
174 | (void)memset(&dsdt, 0, sizeof(dsdt)); |
175 | |
176 | rv = AcpiGetTableHeader(ACPI_SIG_XSDT, 0, &xsdt); |
177 | |
178 | if (ACPI_FAILURE(rv)) |
179 | (void)memset(&xsdt, 0, sizeof(xsdt)); |
180 | |
181 | for (i = 0; i < __arraycount(acpi_quirks); i++) { |
182 | |
183 | aq = &acpi_quirks[i]; |
184 | |
185 | if (strncmp(aq->aq_tabletype, ACPI_SIG_DSDT, 4) == 0) |
186 | hdr = &dsdt; |
187 | else if (strncmp(aq->aq_tabletype, ACPI_SIG_XSDT, 4) == 0) |
188 | hdr = &xsdt; |
189 | else if (strncmp(aq->aq_tabletype, ACPI_SIG_FADT, 4) == 0) |
190 | hdr = &fadt; |
191 | else { |
192 | continue; |
193 | } |
194 | |
195 | len = strlen(aq->aq_oemid); |
196 | |
197 | if (strncmp(aq->aq_oemid, hdr->OemId, len) != 0) |
198 | continue; |
199 | |
200 | if (acpi_quirks_revcmp(aq->aq_oemrev, |
201 | hdr->OemRevision, aq->aq_cmpop) != 0) |
202 | continue; |
203 | |
204 | len = strlen(aq->aq_tabid); |
205 | |
206 | if (strncmp(aq->aq_tabid, hdr->OemTableId, len) != 0) |
207 | continue; |
208 | |
209 | return aq->aq_quirks; |
210 | } |
211 | |
212 | return 0; |
213 | } |
214 | |
215 | /* |
216 | * Add or delete a string to the list that should return |
217 | * true when _OSI is being queried. The defaults are: |
218 | * |
219 | * "Windows 2000" # Windows 2000 |
220 | * "Windows 2001" # Windows XP |
221 | * "Windows 2001 SP1" # Windows XP SP1 |
222 | * "Windows 2001.1" # Windows Server 2003 |
223 | * "Windows 2001 SP2" # Windows XP SP2 |
224 | * "Windows 2001.1 SP1" # Windows Server 2003 SP1 |
225 | * "Windows 2006" # Windows Vista |
226 | * "Windows 2006.1" # Windows Server 2008 |
227 | * "Windows 2006 SP1" # Windows Vista SP1 |
228 | * "Windows 2006 SP2" # Windows Vista SP2 |
229 | * "Windows 2009" # Windows 7 and Server 2008 |
230 | */ |
231 | int |
232 | acpi_quirks_osi_add(const char *str) |
233 | { |
234 | ACPI_STATUS rv; |
235 | |
236 | if (str == NULL || *str == '\0') |
237 | return EINVAL; |
238 | |
239 | rv = AcpiInstallInterface(__UNCONST(str)); |
240 | |
241 | return (rv != AE_OK) ? EIO : 0; |
242 | } |
243 | |
244 | int |
245 | acpi_quirks_osi_del(const char *str) |
246 | { |
247 | ACPI_STATUS rv; |
248 | |
249 | if (str == NULL || *str == '\0') |
250 | return EINVAL; |
251 | |
252 | rv = AcpiRemoveInterface(__UNCONST(str)); |
253 | |
254 | return (rv != AE_OK) ? EIO : 0; |
255 | } |
256 | |
257 | #if 0 |
258 | static void |
259 | acpi_quirks_osi_linux(void) |
260 | { |
261 | (void)acpi_quirks_osi_add("Linux" ); |
262 | } |
263 | |
264 | static void |
265 | acpi_quirks_osi_vista(void) |
266 | { |
267 | (void)acpi_quirks_osi_del("Windows 2006" ); |
268 | (void)acpi_quirks_osi_del("Windows 2006 SP1" ); |
269 | (void)acpi_quirks_osi_del("Windows 2006 SP2" ); |
270 | } |
271 | #endif |
272 | |