0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define pr_fmt(fmt) "ACPI: " fmt
0012
0013 #include <linux/module.h>
0014 #include <linux/kernel.h>
0015 #include <linux/acpi.h>
0016 #include <linux/dmi.h>
0017 #include <linux/platform_data/x86/apple.h>
0018
0019 #include "internal.h"
0020
0021
0022 #define OSI_STRING_LENGTH_MAX 64
0023 #define OSI_STRING_ENTRIES_MAX 16
0024
0025 struct acpi_osi_entry {
0026 char string[OSI_STRING_LENGTH_MAX];
0027 bool enable;
0028 };
0029
0030 static struct acpi_osi_config {
0031 u8 default_disabling;
0032 unsigned int linux_enable:1;
0033 unsigned int linux_dmi:1;
0034 unsigned int linux_cmdline:1;
0035 unsigned int darwin_enable:1;
0036 unsigned int darwin_dmi:1;
0037 unsigned int darwin_cmdline:1;
0038 } osi_config;
0039
0040 static struct acpi_osi_config osi_config;
0041 static struct acpi_osi_entry
0042 osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
0043 {"Module Device", true},
0044 {"Processor Device", true},
0045 {"3.0 _SCP Extensions", true},
0046 {"Processor Aggregator Device", true},
0047
0048
0049
0050
0051
0052
0053
0054
0055 {"Linux-Dell-Video", true},
0056
0057
0058
0059
0060
0061
0062
0063 {"Linux-Lenovo-NV-HDMI-Audio", true},
0064
0065
0066
0067
0068
0069
0070 {"Linux-HPI-Hybrid-Graphics", true},
0071 };
0072
0073 static u32 acpi_osi_handler(acpi_string interface, u32 supported)
0074 {
0075 if (!strcmp("Linux", interface)) {
0076 pr_notice_once(FW_BUG
0077 "BIOS _OSI(Linux) query %s%s\n",
0078 osi_config.linux_enable ? "honored" : "ignored",
0079 osi_config.linux_cmdline ? " via cmdline" :
0080 osi_config.linux_dmi ? " via DMI" : "");
0081 }
0082 if (!strcmp("Darwin", interface)) {
0083 pr_notice_once(
0084 "BIOS _OSI(Darwin) query %s%s\n",
0085 osi_config.darwin_enable ? "honored" : "ignored",
0086 osi_config.darwin_cmdline ? " via cmdline" :
0087 osi_config.darwin_dmi ? " via DMI" : "");
0088 }
0089
0090 return supported;
0091 }
0092
0093 void __init acpi_osi_setup(char *str)
0094 {
0095 struct acpi_osi_entry *osi;
0096 bool enable = true;
0097 int i;
0098
0099 if (!acpi_gbl_create_osi_method)
0100 return;
0101
0102 if (str == NULL || *str == '\0') {
0103 pr_info("_OSI method disabled\n");
0104 acpi_gbl_create_osi_method = FALSE;
0105 return;
0106 }
0107
0108 if (*str == '!') {
0109 str++;
0110 if (*str == '\0') {
0111
0112 if (!osi_config.default_disabling)
0113 osi_config.default_disabling =
0114 ACPI_DISABLE_ALL_VENDOR_STRINGS;
0115 return;
0116 } else if (*str == '*') {
0117 osi_config.default_disabling = ACPI_DISABLE_ALL_STRINGS;
0118 for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
0119 osi = &osi_setup_entries[i];
0120 osi->enable = false;
0121 }
0122 return;
0123 } else if (*str == '!') {
0124 osi_config.default_disabling = 0;
0125 return;
0126 }
0127 enable = false;
0128 }
0129
0130 for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
0131 osi = &osi_setup_entries[i];
0132 if (!strcmp(osi->string, str)) {
0133 osi->enable = enable;
0134 break;
0135 } else if (osi->string[0] == '\0') {
0136 osi->enable = enable;
0137 strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
0138 break;
0139 }
0140 }
0141 }
0142
0143 static void __init __acpi_osi_setup_darwin(bool enable)
0144 {
0145 osi_config.darwin_enable = !!enable;
0146 if (enable) {
0147 acpi_osi_setup("!");
0148 acpi_osi_setup("Darwin");
0149 } else {
0150 acpi_osi_setup("!!");
0151 acpi_osi_setup("!Darwin");
0152 }
0153 }
0154
0155 static void __init acpi_osi_setup_darwin(bool enable)
0156 {
0157
0158 osi_config.darwin_dmi = 0;
0159 osi_config.darwin_cmdline = 1;
0160 __acpi_osi_setup_darwin(enable);
0161 }
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192 static void __init __acpi_osi_setup_linux(bool enable)
0193 {
0194 osi_config.linux_enable = !!enable;
0195 if (enable)
0196 acpi_osi_setup("Linux");
0197 else
0198 acpi_osi_setup("!Linux");
0199 }
0200
0201 static void __init acpi_osi_setup_linux(bool enable)
0202 {
0203
0204 osi_config.linux_dmi = 0;
0205 osi_config.linux_cmdline = 1;
0206 __acpi_osi_setup_linux(enable);
0207 }
0208
0209
0210
0211
0212
0213
0214
0215
0216 static void __init acpi_osi_setup_late(void)
0217 {
0218 struct acpi_osi_entry *osi;
0219 char *str;
0220 int i;
0221 acpi_status status;
0222
0223 if (osi_config.default_disabling) {
0224 status = acpi_update_interfaces(osi_config.default_disabling);
0225 if (ACPI_SUCCESS(status))
0226 pr_info("Disabled all _OSI OS vendors%s\n",
0227 osi_config.default_disabling ==
0228 ACPI_DISABLE_ALL_STRINGS ?
0229 " and feature groups" : "");
0230 }
0231
0232 for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
0233 osi = &osi_setup_entries[i];
0234 str = osi->string;
0235 if (*str == '\0')
0236 break;
0237 if (osi->enable) {
0238 status = acpi_install_interface(str);
0239 if (ACPI_SUCCESS(status))
0240 pr_info("Added _OSI(%s)\n", str);
0241 } else {
0242 status = acpi_remove_interface(str);
0243 if (ACPI_SUCCESS(status))
0244 pr_info("Deleted _OSI(%s)\n", str);
0245 }
0246 }
0247 }
0248
0249 static int __init osi_setup(char *str)
0250 {
0251 if (str && !strcmp("Linux", str))
0252 acpi_osi_setup_linux(true);
0253 else if (str && !strcmp("!Linux", str))
0254 acpi_osi_setup_linux(false);
0255 else if (str && !strcmp("Darwin", str))
0256 acpi_osi_setup_darwin(true);
0257 else if (str && !strcmp("!Darwin", str))
0258 acpi_osi_setup_darwin(false);
0259 else
0260 acpi_osi_setup(str);
0261
0262 return 1;
0263 }
0264 __setup("acpi_osi=", osi_setup);
0265
0266 bool acpi_osi_is_win8(void)
0267 {
0268 return acpi_gbl_osi_data >= ACPI_OSI_WIN_8;
0269 }
0270 EXPORT_SYMBOL(acpi_osi_is_win8);
0271
0272 static void __init acpi_osi_dmi_darwin(void)
0273 {
0274 pr_notice("DMI detected to setup _OSI(\"Darwin\"): Apple hardware\n");
0275 osi_config.darwin_dmi = 1;
0276 __acpi_osi_setup_darwin(true);
0277 }
0278
0279 static void __init acpi_osi_dmi_linux(bool enable,
0280 const struct dmi_system_id *d)
0281 {
0282 pr_notice("DMI detected to setup _OSI(\"Linux\"): %s\n", d->ident);
0283 osi_config.linux_dmi = 1;
0284 __acpi_osi_setup_linux(enable);
0285 }
0286
0287 static int __init dmi_enable_osi_linux(const struct dmi_system_id *d)
0288 {
0289 acpi_osi_dmi_linux(true, d);
0290
0291 return 0;
0292 }
0293
0294 static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
0295 {
0296 pr_notice("DMI detected: %s\n", d->ident);
0297 acpi_osi_setup("!Windows 2006");
0298 acpi_osi_setup("!Windows 2006 SP1");
0299 acpi_osi_setup("!Windows 2006 SP2");
0300
0301 return 0;
0302 }
0303
0304 static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
0305 {
0306 pr_notice("DMI detected: %s\n", d->ident);
0307 acpi_osi_setup("!Windows 2009");
0308
0309 return 0;
0310 }
0311
0312 static int __init dmi_disable_osi_win8(const struct dmi_system_id *d)
0313 {
0314 pr_notice("DMI detected: %s\n", d->ident);
0315 acpi_osi_setup("!Windows 2012");
0316
0317 return 0;
0318 }
0319
0320
0321
0322
0323
0324
0325
0326 static const struct dmi_system_id acpi_osi_dmi_table[] __initconst = {
0327 {
0328 .callback = dmi_disable_osi_vista,
0329 .ident = "Fujitsu Siemens",
0330 .matches = {
0331 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
0332 DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
0333 },
0334 },
0335 {
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345 .callback = dmi_disable_osi_vista,
0346 .ident = "MSI GX723",
0347 .matches = {
0348 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
0349 DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
0350 },
0351 },
0352 {
0353 .callback = dmi_disable_osi_vista,
0354 .ident = "Sony VGN-NS10J_S",
0355 .matches = {
0356 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
0357 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"),
0358 },
0359 },
0360 {
0361 .callback = dmi_disable_osi_vista,
0362 .ident = "Sony VGN-SR290J",
0363 .matches = {
0364 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
0365 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
0366 },
0367 },
0368 {
0369 .callback = dmi_disable_osi_vista,
0370 .ident = "VGN-NS50B_L",
0371 .matches = {
0372 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
0373 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
0374 },
0375 },
0376 {
0377 .callback = dmi_disable_osi_vista,
0378 .ident = "VGN-SR19XN",
0379 .matches = {
0380 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
0381 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"),
0382 },
0383 },
0384 {
0385 .callback = dmi_disable_osi_vista,
0386 .ident = "Toshiba Satellite L355",
0387 .matches = {
0388 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
0389 DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
0390 },
0391 },
0392 {
0393 .callback = dmi_disable_osi_win7,
0394 .ident = "ASUS K50IJ",
0395 .matches = {
0396 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
0397 DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
0398 },
0399 },
0400 {
0401 .callback = dmi_disable_osi_vista,
0402 .ident = "Toshiba P305D",
0403 .matches = {
0404 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
0405 DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
0406 },
0407 },
0408 {
0409 .callback = dmi_disable_osi_vista,
0410 .ident = "Toshiba NB100",
0411 .matches = {
0412 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
0413 DMI_MATCH(DMI_PRODUCT_NAME, "NB100"),
0414 },
0415 },
0416
0417
0418
0419
0420
0421 {
0422 .callback = dmi_disable_osi_win8,
0423 .ident = "Dell Inspiron 7737",
0424 .matches = {
0425 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0426 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"),
0427 },
0428 },
0429 {
0430 .callback = dmi_disable_osi_win8,
0431 .ident = "Dell Inspiron 7537",
0432 .matches = {
0433 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0434 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"),
0435 },
0436 },
0437 {
0438 .callback = dmi_disable_osi_win8,
0439 .ident = "Dell Inspiron 5437",
0440 .matches = {
0441 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0442 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"),
0443 },
0444 },
0445 {
0446 .callback = dmi_disable_osi_win8,
0447 .ident = "Dell Inspiron 3437",
0448 .matches = {
0449 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0450 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"),
0451 },
0452 },
0453 {
0454 .callback = dmi_disable_osi_win8,
0455 .ident = "Dell Vostro 3446",
0456 .matches = {
0457 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0458 DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
0459 },
0460 },
0461 {
0462 .callback = dmi_disable_osi_win8,
0463 .ident = "Dell Vostro 3546",
0464 .matches = {
0465 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0466 DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"),
0467 },
0468 },
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480 {
0481 .callback = dmi_enable_osi_linux,
0482 .ident = "Asus EEE PC 1015PX",
0483 .matches = {
0484 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
0485 DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"),
0486 },
0487 },
0488 {}
0489 };
0490
0491 static __init void acpi_osi_dmi_blacklisted(void)
0492 {
0493 dmi_check_system(acpi_osi_dmi_table);
0494
0495
0496 if (x86_apple_machine)
0497 acpi_osi_dmi_darwin();
0498 }
0499
0500 int __init early_acpi_osi_init(void)
0501 {
0502 acpi_osi_dmi_blacklisted();
0503
0504 return 0;
0505 }
0506
0507 int __init acpi_osi_init(void)
0508 {
0509 acpi_install_interface_handler(acpi_osi_handler);
0510 acpi_osi_setup_late();
0511
0512 return 0;
0513 }