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