1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#define pr_fmt(fmt) "ACPI: " fmt
25
26#include <linux/module.h>
27#include <linux/kernel.h>
28#include <linux/acpi.h>
29#include <linux/dmi.h>
30
31#include "internal.h"
32
33
34#define OSI_STRING_LENGTH_MAX 64
35#define OSI_STRING_ENTRIES_MAX 16
36
37struct acpi_osi_entry {
38 char string[OSI_STRING_LENGTH_MAX];
39 bool enable;
40};
41
42static struct acpi_osi_config {
43 u8 default_disabling;
44 unsigned int linux_enable:1;
45 unsigned int linux_dmi:1;
46 unsigned int linux_cmdline:1;
47 unsigned int darwin_enable:1;
48 unsigned int darwin_dmi:1;
49 unsigned int darwin_cmdline:1;
50} osi_config;
51
52static struct acpi_osi_config osi_config;
53static struct acpi_osi_entry
54osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
55 {"Module Device", true},
56 {"Processor Device", true},
57 {"3.0 _SCP Extensions", true},
58 {"Processor Aggregator Device", true},
59};
60
61static u32 acpi_osi_handler(acpi_string interface, u32 supported)
62{
63 if (!strcmp("Linux", interface)) {
64 pr_notice_once(FW_BUG
65 "BIOS _OSI(Linux) query %s%s\n",
66 osi_config.linux_enable ? "honored" : "ignored",
67 osi_config.linux_cmdline ? " via cmdline" :
68 osi_config.linux_dmi ? " via DMI" : "");
69 }
70 if (!strcmp("Darwin", interface)) {
71 pr_notice_once(
72 "BIOS _OSI(Darwin) query %s%s\n",
73 osi_config.darwin_enable ? "honored" : "ignored",
74 osi_config.darwin_cmdline ? " via cmdline" :
75 osi_config.darwin_dmi ? " via DMI" : "");
76 }
77
78 return supported;
79}
80
81void __init acpi_osi_setup(char *str)
82{
83 struct acpi_osi_entry *osi;
84 bool enable = true;
85 int i;
86
87 if (!acpi_gbl_create_osi_method)
88 return;
89
90 if (str == NULL || *str == '\0') {
91 pr_info("_OSI method disabled\n");
92 acpi_gbl_create_osi_method = FALSE;
93 return;
94 }
95
96 if (*str == '!') {
97 str++;
98 if (*str == '\0') {
99
100 if (!osi_config.default_disabling)
101 osi_config.default_disabling =
102 ACPI_DISABLE_ALL_VENDOR_STRINGS;
103 return;
104 } else if (*str == '*') {
105 osi_config.default_disabling = ACPI_DISABLE_ALL_STRINGS;
106 for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
107 osi = &osi_setup_entries[i];
108 osi->enable = false;
109 }
110 return;
111 } else if (*str == '!') {
112 osi_config.default_disabling = 0;
113 return;
114 }
115 enable = false;
116 }
117
118 for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
119 osi = &osi_setup_entries[i];
120 if (!strcmp(osi->string, str)) {
121 osi->enable = enable;
122 break;
123 } else if (osi->string[0] == '\0') {
124 osi->enable = enable;
125 strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
126 break;
127 }
128 }
129}
130
131static void __init __acpi_osi_setup_darwin(bool enable)
132{
133 osi_config.darwin_enable = !!enable;
134 if (enable) {
135 acpi_osi_setup("!");
136 acpi_osi_setup("Darwin");
137 } else {
138 acpi_osi_setup("!!");
139 acpi_osi_setup("!Darwin");
140 }
141}
142
143static void __init acpi_osi_setup_darwin(bool enable)
144{
145
146 osi_config.darwin_dmi = 0;
147 osi_config.darwin_cmdline = 1;
148 __acpi_osi_setup_darwin(enable);
149}
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180static void __init __acpi_osi_setup_linux(bool enable)
181{
182 osi_config.linux_enable = !!enable;
183 if (enable)
184 acpi_osi_setup("Linux");
185 else
186 acpi_osi_setup("!Linux");
187}
188
189static void __init acpi_osi_setup_linux(bool enable)
190{
191
192 osi_config.linux_dmi = 0;
193 osi_config.linux_cmdline = 1;
194 __acpi_osi_setup_linux(enable);
195}
196
197
198
199
200
201
202
203
204static void __init acpi_osi_setup_late(void)
205{
206 struct acpi_osi_entry *osi;
207 char *str;
208 int i;
209 acpi_status status;
210
211 if (osi_config.default_disabling) {
212 status = acpi_update_interfaces(osi_config.default_disabling);
213 if (ACPI_SUCCESS(status))
214 pr_info("Disabled all _OSI OS vendors%s\n",
215 osi_config.default_disabling ==
216 ACPI_DISABLE_ALL_STRINGS ?
217 " and feature groups" : "");
218 }
219
220 for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
221 osi = &osi_setup_entries[i];
222 str = osi->string;
223 if (*str == '\0')
224 break;
225 if (osi->enable) {
226 status = acpi_install_interface(str);
227 if (ACPI_SUCCESS(status))
228 pr_info("Added _OSI(%s)\n", str);
229 } else {
230 status = acpi_remove_interface(str);
231 if (ACPI_SUCCESS(status))
232 pr_info("Deleted _OSI(%s)\n", str);
233 }
234 }
235}
236
237static int __init osi_setup(char *str)
238{
239 if (str && !strcmp("Linux", str))
240 acpi_osi_setup_linux(true);
241 else if (str && !strcmp("!Linux", str))
242 acpi_osi_setup_linux(false);
243 else if (str && !strcmp("Darwin", str))
244 acpi_osi_setup_darwin(true);
245 else if (str && !strcmp("!Darwin", str))
246 acpi_osi_setup_darwin(false);
247 else
248 acpi_osi_setup(str);
249
250 return 1;
251}
252__setup("acpi_osi=", osi_setup);
253
254bool acpi_osi_is_win8(void)
255{
256 return acpi_gbl_osi_data >= ACPI_OSI_WIN_8;
257}
258EXPORT_SYMBOL(acpi_osi_is_win8);
259
260static void __init acpi_osi_dmi_darwin(bool enable,
261 const struct dmi_system_id *d)
262{
263 pr_notice("DMI detected to setup _OSI(\"Darwin\"): %s\n", d->ident);
264 osi_config.darwin_dmi = 1;
265 __acpi_osi_setup_darwin(enable);
266}
267
268void __init acpi_osi_dmi_linux(bool enable, const struct dmi_system_id *d)
269{
270 pr_notice("DMI detected to setup _OSI(\"Linux\"): %s\n", d->ident);
271 osi_config.linux_dmi = 1;
272 __acpi_osi_setup_linux(enable);
273}
274
275static int __init dmi_enable_osi_darwin(const struct dmi_system_id *d)
276{
277 acpi_osi_dmi_darwin(true, d);
278
279 return 0;
280}
281
282static int __init dmi_enable_osi_linux(const struct dmi_system_id *d)
283{
284 acpi_osi_dmi_linux(true, d);
285
286 return 0;
287}
288
289static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
290{
291 pr_notice("DMI detected: %s\n", d->ident);
292 acpi_osi_setup("!Windows 2006");
293 acpi_osi_setup("!Windows 2006 SP1");
294 acpi_osi_setup("!Windows 2006 SP2");
295
296 return 0;
297}
298
299static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
300{
301 pr_notice("DMI detected: %s\n", d->ident);
302 acpi_osi_setup("!Windows 2009");
303
304 return 0;
305}
306
307static int __init dmi_disable_osi_win8(const struct dmi_system_id *d)
308{
309 pr_notice("DMI detected: %s\n", d->ident);
310 acpi_osi_setup("!Windows 2012");
311
312 return 0;
313}
314
315
316
317
318
319
320
321static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
322 {
323 .callback = dmi_disable_osi_vista,
324 .ident = "Fujitsu Siemens",
325 .matches = {
326 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
327 DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
328 },
329 },
330 {
331
332
333
334
335
336
337
338
339
340 .callback = dmi_disable_osi_vista,
341 .ident = "MSI GX723",
342 .matches = {
343 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
344 DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
345 },
346 },
347 {
348 .callback = dmi_disable_osi_vista,
349 .ident = "Sony VGN-NS10J_S",
350 .matches = {
351 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
352 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"),
353 },
354 },
355 {
356 .callback = dmi_disable_osi_vista,
357 .ident = "Sony VGN-SR290J",
358 .matches = {
359 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
360 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
361 },
362 },
363 {
364 .callback = dmi_disable_osi_vista,
365 .ident = "VGN-NS50B_L",
366 .matches = {
367 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
368 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
369 },
370 },
371 {
372 .callback = dmi_disable_osi_vista,
373 .ident = "VGN-SR19XN",
374 .matches = {
375 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
376 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"),
377 },
378 },
379 {
380 .callback = dmi_disable_osi_vista,
381 .ident = "Toshiba Satellite L355",
382 .matches = {
383 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
384 DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
385 },
386 },
387 {
388 .callback = dmi_disable_osi_win7,
389 .ident = "ASUS K50IJ",
390 .matches = {
391 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
392 DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
393 },
394 },
395 {
396 .callback = dmi_disable_osi_vista,
397 .ident = "Toshiba P305D",
398 .matches = {
399 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
400 DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
401 },
402 },
403 {
404 .callback = dmi_disable_osi_vista,
405 .ident = "Toshiba NB100",
406 .matches = {
407 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
408 DMI_MATCH(DMI_PRODUCT_NAME, "NB100"),
409 },
410 },
411
412
413
414
415
416 {
417 .callback = dmi_disable_osi_win8,
418 .ident = "Dell Inspiron 7737",
419 .matches = {
420 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
421 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"),
422 },
423 },
424 {
425 .callback = dmi_disable_osi_win8,
426 .ident = "Dell Inspiron 7537",
427 .matches = {
428 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
429 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"),
430 },
431 },
432 {
433 .callback = dmi_disable_osi_win8,
434 .ident = "Dell Inspiron 5437",
435 .matches = {
436 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
437 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"),
438 },
439 },
440 {
441 .callback = dmi_disable_osi_win8,
442 .ident = "Dell Inspiron 3437",
443 .matches = {
444 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
445 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"),
446 },
447 },
448 {
449 .callback = dmi_disable_osi_win8,
450 .ident = "Dell Vostro 3446",
451 .matches = {
452 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
453 DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
454 },
455 },
456 {
457 .callback = dmi_disable_osi_win8,
458 .ident = "Dell Vostro 3546",
459 .matches = {
460 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
461 DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"),
462 },
463 },
464
465
466
467
468
469
470
471
472
473
474
475 {
476 .callback = dmi_enable_osi_linux,
477 .ident = "Asus EEE PC 1015PX",
478 .matches = {
479 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
480 DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"),
481 },
482 },
483
484
485
486
487 {
488 .callback = dmi_enable_osi_darwin,
489 .ident = "Apple hardware",
490 .matches = {
491 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
492 },
493 },
494 {
495 .callback = dmi_enable_osi_darwin,
496 .ident = "Apple hardware",
497 .matches = {
498 DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
499 },
500 },
501 {}
502};
503
504static __init void acpi_osi_dmi_blacklisted(void)
505{
506 dmi_check_system(acpi_osi_dmi_table);
507}
508
509int __init early_acpi_osi_init(void)
510{
511 acpi_osi_dmi_blacklisted();
512
513 return 0;
514}
515
516int __init acpi_osi_init(void)
517{
518 acpi_install_interface_handler(acpi_osi_handler);
519 acpi_osi_setup_late();
520
521 return 0;
522}
523