11cf70ae6SChangbin Du.. SPDX-License-Identifier: GPL-2.0 21cf70ae6SChangbin Du 31cf70ae6SChangbin Du========================== 41cf70ae6SChangbin DuACPI _OSI and _REV methods 51cf70ae6SChangbin Du========================== 61cf70ae6SChangbin Du 71cf70ae6SChangbin DuAn ACPI BIOS can use the "Operating System Interfaces" method (_OSI) 81cf70ae6SChangbin Duto find out what the operating system supports. Eg. If BIOS 91cf70ae6SChangbin DuAML code includes _OSI("XYZ"), the kernel's AML interpreter 101cf70ae6SChangbin Ducan evaluate that method, look to see if it supports 'XYZ' 111cf70ae6SChangbin Duand answer YES or NO to the BIOS. 121cf70ae6SChangbin Du 131cf70ae6SChangbin DuThe ACPI _REV method returns the "Revision of the ACPI specification 141cf70ae6SChangbin Duthat OSPM supports" 151cf70ae6SChangbin Du 161cf70ae6SChangbin DuThis document explains how and why the BIOS and Linux should use these methods. 171cf70ae6SChangbin DuIt also explains how and why they are widely misused. 181cf70ae6SChangbin Du 191cf70ae6SChangbin DuHow to use _OSI 201cf70ae6SChangbin Du=============== 211cf70ae6SChangbin Du 221cf70ae6SChangbin DuLinux runs on two groups of machines -- those that are tested by the OEM 231cf70ae6SChangbin Duto be compatible with Linux, and those that were never tested with Linux, 241cf70ae6SChangbin Dubut where Linux was installed to replace the original OS (Windows or OSX). 251cf70ae6SChangbin Du 261cf70ae6SChangbin DuThe larger group is the systems tested to run only Windows. Not only that, 271cf70ae6SChangbin Dubut many were tested to run with just one specific version of Windows. 281cf70ae6SChangbin DuSo even though the BIOS may use _OSI to query what version of Windows is running, 291cf70ae6SChangbin Duonly a single path through the BIOS has actually been tested. 301cf70ae6SChangbin DuExperience shows that taking untested paths through the BIOS 311cf70ae6SChangbin Duexposes Linux to an entire category of BIOS bugs. 321cf70ae6SChangbin DuFor this reason, Linux _OSI defaults must continue to claim compatibility 331cf70ae6SChangbin Duwith all versions of Windows. 341cf70ae6SChangbin Du 351cf70ae6SChangbin DuBut Linux isn't actually compatible with Windows, and the Linux community 361cf70ae6SChangbin Duhas also been hurt with regressions when Linux adds the latest version of 371cf70ae6SChangbin DuWindows to its list of _OSI strings. So it is possible that additional strings 381cf70ae6SChangbin Duwill be more thoroughly vetted before shipping upstream in the future. 391cf70ae6SChangbin DuBut it is likely that they will all eventually be added. 401cf70ae6SChangbin Du 411cf70ae6SChangbin DuWhat should an OEM do if they want to support Linux and Windows 421cf70ae6SChangbin Duusing the same BIOS image? Often they need to do something different 431cf70ae6SChangbin Dufor Linux to deal with how Linux is different from Windows. 441cf70ae6SChangbin Du 452f190ac2SMario LimoncielloIn this case, the OEM should create custom ASL to be executed by the 462f190ac2SMario LimoncielloLinux kernel and changes to Linux kernel drivers to execute this custom 472f190ac2SMario LimoncielloASL. The easiest way to accomplish this is to introduce a device specific 482f190ac2SMario Limonciellomethod (_DSM) that is called from the Linux kernel. 492f190ac2SMario Limonciello 502f190ac2SMario LimoncielloIn the past the kernel used to support something like: 511cf70ae6SChangbin Du_OSI("Linux-OEM-my_interface_name") 521cf70ae6SChangbin Duwhere 'OEM' is needed if this is an OEM-specific hook, 531cf70ae6SChangbin Duand 'my_interface_name' describes the hook, which could be a 541cf70ae6SChangbin Duquirk, a bug, or a bug-fix. 551cf70ae6SChangbin Du 562f190ac2SMario LimoncielloHowever this was discovered to be abused by other BIOS vendors to change 572f190ac2SMario Limonciellocompletely unrelated code on completely unrelated systems. This prompted 58*d56b699dSBjorn Helgaasan evaluation of all of its uses. This uncovered that they aren't needed 592f190ac2SMario Limonciellofor any of the original reasons. As such, the kernel will not respond to 602f190ac2SMario Limoncielloany custom Linux-* strings by default. 611cf70ae6SChangbin Du 621cf70ae6SChangbin DuThat was easy. Read on, to find out how to do it wrong. 631cf70ae6SChangbin Du 641cf70ae6SChangbin DuBefore _OSI, there was _OS 651cf70ae6SChangbin Du========================== 661cf70ae6SChangbin Du 671cf70ae6SChangbin DuACPI 1.0 specified "_OS" as an 681cf70ae6SChangbin Du"object that evaluates to a string that identifies the operating system." 691cf70ae6SChangbin Du 701cf70ae6SChangbin DuThe ACPI BIOS flow would include an evaluation of _OS, and the AML 711cf70ae6SChangbin Duinterpreter in the kernel would return to it a string identifying the OS: 721cf70ae6SChangbin Du 731cf70ae6SChangbin DuWindows 98, SE: "Microsoft Windows" 7411ca0d6bSColin Ian KingWindows ME: "Microsoft WindowsME:Millennium Edition" 751cf70ae6SChangbin DuWindows NT: "Microsoft Windows NT" 761cf70ae6SChangbin Du 771cf70ae6SChangbin DuThe idea was on a platform tasked with running multiple OS's, 781cf70ae6SChangbin Duthe BIOS could use _OS to enable devices that an OS 791cf70ae6SChangbin Dumight support, or enable quirks or bug workarounds 801cf70ae6SChangbin Dunecessary to make the platform compatible with that pre-existing OS. 811cf70ae6SChangbin Du 821cf70ae6SChangbin DuBut _OS had fundamental problems. First, the BIOS needed to know the name 831cf70ae6SChangbin Duof every possible version of the OS that would run on it, and needed to know 841cf70ae6SChangbin Duall the quirks of those OS's. Certainly it would make more sense 851cf70ae6SChangbin Dufor the BIOS to ask *specific* things of the OS, such 861cf70ae6SChangbin Du"do you support a specific interface", and thus in ACPI 3.0, 871cf70ae6SChangbin Du_OSI was born to replace _OS. 881cf70ae6SChangbin Du 891cf70ae6SChangbin Du_OS was abandoned, though even today, many BIOS look for 901cf70ae6SChangbin Du_OS "Microsoft Windows NT", though it seems somewhat far-fetched 911cf70ae6SChangbin Duthat anybody would install those old operating systems 921cf70ae6SChangbin Duover what came with the machine. 931cf70ae6SChangbin Du 941cf70ae6SChangbin DuLinux answers "Microsoft Windows NT" to please that BIOS idiom. 951cf70ae6SChangbin DuThat is the *only* viable strategy, as that is what modern Windows does, 961cf70ae6SChangbin Duand so doing otherwise could steer the BIOS down an untested path. 971cf70ae6SChangbin Du 981cf70ae6SChangbin Du_OSI is born, and immediately misused 991cf70ae6SChangbin Du===================================== 1001cf70ae6SChangbin Du 1011cf70ae6SChangbin DuWith _OSI, the *BIOS* provides the string describing an interface, 1021cf70ae6SChangbin Duand asks the OS: "YES/NO, are you compatible with this interface?" 1031cf70ae6SChangbin Du 1041cf70ae6SChangbin Dueg. _OSI("3.0 Thermal Model") would return TRUE if the OS knows how 1051cf70ae6SChangbin Duto deal with the thermal extensions made to the ACPI 3.0 specification. 1061cf70ae6SChangbin DuAn old OS that doesn't know about those extensions would answer FALSE, 1071cf70ae6SChangbin Duand a new OS may be able to return TRUE. 1081cf70ae6SChangbin Du 1091cf70ae6SChangbin DuFor an OS-specific interface, the ACPI spec said that the BIOS and the OS 1101cf70ae6SChangbin Duwere to agree on a string of the form such as "Windows-interface_name". 1111cf70ae6SChangbin Du 1121cf70ae6SChangbin DuBut two bad things happened. First, the Windows ecosystem used _OSI 1131cf70ae6SChangbin Dunot as designed, but as a direct replacement for _OS -- identifying 1141cf70ae6SChangbin Duthe OS version, rather than an OS supported interface. Indeed, right 1151cf70ae6SChangbin Dufrom the start, the ACPI 3.0 spec itself codified this misuse 1161cf70ae6SChangbin Duin example code using _OSI("Windows 2001"). 1171cf70ae6SChangbin Du 1181cf70ae6SChangbin DuThis misuse was adopted and continues today. 1191cf70ae6SChangbin Du 1201cf70ae6SChangbin DuLinux had no choice but to also return TRUE to _OSI("Windows 2001") 1211cf70ae6SChangbin Duand its successors. To do otherwise would virtually guarantee breaking 1221cf70ae6SChangbin Dua BIOS that has been tested only with that _OSI returning TRUE. 1231cf70ae6SChangbin Du 1241cf70ae6SChangbin DuThis strategy is problematic, as Linux is never completely compatible with 1251cf70ae6SChangbin Duthe latest version of Windows, and sometimes it takes more than a year 1261cf70ae6SChangbin Duto iron out incompatibilities. 1271cf70ae6SChangbin Du 1281cf70ae6SChangbin DuNot to be out-done, the Linux community made things worse by returning TRUE 1291cf70ae6SChangbin Duto _OSI("Linux"). Doing so is even worse than the Windows misuse 1301cf70ae6SChangbin Duof _OSI, as "Linux" does not even contain any version information. 1311cf70ae6SChangbin Du_OSI("Linux") led to some BIOS' malfunctioning due to BIOS writer's 1321cf70ae6SChangbin Duusing it in untested BIOS flows. But some OEM's used _OSI("Linux") 1331cf70ae6SChangbin Duin tested flows to support real Linux features. In 2009, Linux 1341cf70ae6SChangbin Duremoved _OSI("Linux"), and added a cmdline parameter to restore it 1351cf70ae6SChangbin Dufor legacy systems still needed it. Further a BIOS_BUG warning prints 1361cf70ae6SChangbin Dufor all BIOS's that invoke it. 1371cf70ae6SChangbin Du 1381cf70ae6SChangbin DuNo BIOS should use _OSI("Linux"). 1391cf70ae6SChangbin Du 1401cf70ae6SChangbin DuThe result is a strategy for Linux to maximize compatibility with 1411cf70ae6SChangbin DuACPI BIOS that are tested on Windows machines. There is a real risk 1421cf70ae6SChangbin Duof over-stating that compatibility; but the alternative has often been 1431cf70ae6SChangbin Ducatastrophic failure resulting from the BIOS taking paths that 1441cf70ae6SChangbin Duwere never validated under *any* OS. 1451cf70ae6SChangbin Du 1461cf70ae6SChangbin DuDo not use _REV 1471cf70ae6SChangbin Du=============== 1481cf70ae6SChangbin Du 1491cf70ae6SChangbin DuSince _OSI("Linux") went away, some BIOS writers used _REV 1501cf70ae6SChangbin Duto support Linux and Windows differences in the same BIOS. 1511cf70ae6SChangbin Du 1521cf70ae6SChangbin Du_REV was defined in ACPI 1.0 to return the version of ACPI 1531cf70ae6SChangbin Dusupported by the OS and the OS AML interpreter. 1541cf70ae6SChangbin Du 1551cf70ae6SChangbin DuModern Windows returns _REV = 2. Linux used ACPI_CA_SUPPORT_LEVEL, 1561cf70ae6SChangbin Duwhich would increment, based on the version of the spec supported. 1571cf70ae6SChangbin Du 1581cf70ae6SChangbin DuUnfortunately, _REV was also misused. eg. some BIOS would check 1591cf70ae6SChangbin Dufor _REV = 3, and do something for Linux, but when Linux returned 1601cf70ae6SChangbin Du_REV = 4, that support broke. 1611cf70ae6SChangbin Du 1621cf70ae6SChangbin DuIn response to this problem, Linux returns _REV = 2 always, 1631cf70ae6SChangbin Dufrom mid-2015 onward. The ACPI specification will also be updated 1641cf70ae6SChangbin Duto reflect that _REV is deprecated, and always returns 2. 1651cf70ae6SChangbin Du 1661cf70ae6SChangbin DuApple Mac and _OSI("Darwin") 1671cf70ae6SChangbin Du============================ 1681cf70ae6SChangbin Du 1691cf70ae6SChangbin DuOn Apple's Mac platforms, the ACPI BIOS invokes _OSI("Darwin") 1701cf70ae6SChangbin Duto determine if the machine is running Apple OSX. 1711cf70ae6SChangbin Du 1721cf70ae6SChangbin DuLike Linux's _OSI("*Windows*") strategy, Linux defaults to 1731cf70ae6SChangbin Duanswering YES to _OSI("Darwin") to enable full access 1741cf70ae6SChangbin Duto the hardware and validated BIOS paths seen by OSX. 1751cf70ae6SChangbin DuJust like on Windows-tested platforms, this strategy has risks. 1761cf70ae6SChangbin Du 1771cf70ae6SChangbin DuStarting in Linux-3.18, the kernel answered YES to _OSI("Darwin") 1781cf70ae6SChangbin Dufor the purpose of enabling Mac Thunderbolt support. Further, 1791cf70ae6SChangbin Duif the kernel noticed _OSI("Darwin") being invoked, it additionally 1801cf70ae6SChangbin Dudisabled all _OSI("*Windows*") to keep poorly written Mac BIOS 1811cf70ae6SChangbin Dufrom going down untested combinations of paths. 1821cf70ae6SChangbin Du 1831cf70ae6SChangbin DuThe Linux-3.18 change in default caused power regressions on Mac 1841cf70ae6SChangbin Dulaptops, and the 3.18 implementation did not allow changing 1851cf70ae6SChangbin Duthe default via cmdline "acpi_osi=!Darwin". Linux-4.7 fixed 1861cf70ae6SChangbin Duthe ability to use acpi_osi=!Darwin as a workaround, and 1871cf70ae6SChangbin Duwe hope to see Mac Thunderbolt power management support in Linux-4.11. 188