188 lines · plain
1.. SPDX-License-Identifier: GPL-2.02 3==========================4ACPI _OSI and _REV methods5==========================6 7An ACPI BIOS can use the "Operating System Interfaces" method (_OSI)8to find out what the operating system supports. Eg. If BIOS9AML code includes _OSI("XYZ"), the kernel's AML interpreter10can evaluate that method, look to see if it supports 'XYZ'11and answer YES or NO to the BIOS.12 13The ACPI _REV method returns the "Revision of the ACPI specification14that OSPM supports"15 16This document explains how and why the BIOS and Linux should use these methods.17It also explains how and why they are widely misused.18 19How to use _OSI20===============21 22Linux runs on two groups of machines -- those that are tested by the OEM23to be compatible with Linux, and those that were never tested with Linux,24but where Linux was installed to replace the original OS (Windows or OSX).25 26The larger group is the systems tested to run only Windows. Not only that,27but many were tested to run with just one specific version of Windows.28So even though the BIOS may use _OSI to query what version of Windows is running,29only a single path through the BIOS has actually been tested.30Experience shows that taking untested paths through the BIOS31exposes Linux to an entire category of BIOS bugs.32For this reason, Linux _OSI defaults must continue to claim compatibility33with all versions of Windows.34 35But Linux isn't actually compatible with Windows, and the Linux community36has also been hurt with regressions when Linux adds the latest version of37Windows to its list of _OSI strings. So it is possible that additional strings38will be more thoroughly vetted before shipping upstream in the future.39But it is likely that they will all eventually be added.40 41What should an OEM do if they want to support Linux and Windows42using the same BIOS image? Often they need to do something different43for Linux to deal with how Linux is different from Windows.44 45In this case, the OEM should create custom ASL to be executed by the46Linux kernel and changes to Linux kernel drivers to execute this custom47ASL. The easiest way to accomplish this is to introduce a device specific48method (_DSM) that is called from the Linux kernel.49 50In the past the kernel used to support something like:51_OSI("Linux-OEM-my_interface_name")52where 'OEM' is needed if this is an OEM-specific hook,53and 'my_interface_name' describes the hook, which could be a54quirk, a bug, or a bug-fix.55 56However this was discovered to be abused by other BIOS vendors to change57completely unrelated code on completely unrelated systems. This prompted58an evaluation of all of its uses. This uncovered that they aren't needed59for any of the original reasons. As such, the kernel will not respond to60any custom Linux-* strings by default.61 62That was easy. Read on, to find out how to do it wrong.63 64Before _OSI, there was _OS65==========================66 67ACPI 1.0 specified "_OS" as an68"object that evaluates to a string that identifies the operating system."69 70The ACPI BIOS flow would include an evaluation of _OS, and the AML71interpreter in the kernel would return to it a string identifying the OS:72 73Windows 98, SE: "Microsoft Windows"74Windows ME: "Microsoft WindowsME:Millennium Edition"75Windows NT: "Microsoft Windows NT"76 77The idea was on a platform tasked with running multiple OS's,78the BIOS could use _OS to enable devices that an OS79might support, or enable quirks or bug workarounds80necessary to make the platform compatible with that pre-existing OS.81 82But _OS had fundamental problems. First, the BIOS needed to know the name83of every possible version of the OS that would run on it, and needed to know84all the quirks of those OS's. Certainly it would make more sense85for the BIOS to ask *specific* things of the OS, such86"do you support a specific interface", and thus in ACPI 3.0,87_OSI was born to replace _OS.88 89_OS was abandoned, though even today, many BIOS look for90_OS "Microsoft Windows NT", though it seems somewhat far-fetched91that anybody would install those old operating systems92over what came with the machine.93 94Linux answers "Microsoft Windows NT" to please that BIOS idiom.95That is the *only* viable strategy, as that is what modern Windows does,96and so doing otherwise could steer the BIOS down an untested path.97 98_OSI is born, and immediately misused99=====================================100 101With _OSI, the *BIOS* provides the string describing an interface,102and asks the OS: "YES/NO, are you compatible with this interface?"103 104eg. _OSI("3.0 Thermal Model") would return TRUE if the OS knows how105to deal with the thermal extensions made to the ACPI 3.0 specification.106An old OS that doesn't know about those extensions would answer FALSE,107and a new OS may be able to return TRUE.108 109For an OS-specific interface, the ACPI spec said that the BIOS and the OS110were to agree on a string of the form such as "Windows-interface_name".111 112But two bad things happened. First, the Windows ecosystem used _OSI113not as designed, but as a direct replacement for _OS -- identifying114the OS version, rather than an OS supported interface. Indeed, right115from the start, the ACPI 3.0 spec itself codified this misuse116in example code using _OSI("Windows 2001").117 118This misuse was adopted and continues today.119 120Linux had no choice but to also return TRUE to _OSI("Windows 2001")121and its successors. To do otherwise would virtually guarantee breaking122a BIOS that has been tested only with that _OSI returning TRUE.123 124This strategy is problematic, as Linux is never completely compatible with125the latest version of Windows, and sometimes it takes more than a year126to iron out incompatibilities.127 128Not to be out-done, the Linux community made things worse by returning TRUE129to _OSI("Linux"). Doing so is even worse than the Windows misuse130of _OSI, as "Linux" does not even contain any version information.131_OSI("Linux") led to some BIOS' malfunctioning due to BIOS writer's132using it in untested BIOS flows. But some OEM's used _OSI("Linux")133in tested flows to support real Linux features. In 2009, Linux134removed _OSI("Linux"), and added a cmdline parameter to restore it135for legacy systems still needed it. Further a BIOS_BUG warning prints136for all BIOS's that invoke it.137 138No BIOS should use _OSI("Linux").139 140The result is a strategy for Linux to maximize compatibility with141ACPI BIOS that are tested on Windows machines. There is a real risk142of over-stating that compatibility; but the alternative has often been143catastrophic failure resulting from the BIOS taking paths that144were never validated under *any* OS.145 146Do not use _REV147===============148 149Since _OSI("Linux") went away, some BIOS writers used _REV150to support Linux and Windows differences in the same BIOS.151 152_REV was defined in ACPI 1.0 to return the version of ACPI153supported by the OS and the OS AML interpreter.154 155Modern Windows returns _REV = 2. Linux used ACPI_CA_SUPPORT_LEVEL,156which would increment, based on the version of the spec supported.157 158Unfortunately, _REV was also misused. eg. some BIOS would check159for _REV = 3, and do something for Linux, but when Linux returned160_REV = 4, that support broke.161 162In response to this problem, Linux returns _REV = 2 always,163from mid-2015 onward. The ACPI specification will also be updated164to reflect that _REV is deprecated, and always returns 2.165 166Apple Mac and _OSI("Darwin")167============================168 169On Apple's Mac platforms, the ACPI BIOS invokes _OSI("Darwin")170to determine if the machine is running Apple OSX.171 172Like Linux's _OSI("*Windows*") strategy, Linux defaults to173answering YES to _OSI("Darwin") to enable full access174to the hardware and validated BIOS paths seen by OSX.175Just like on Windows-tested platforms, this strategy has risks.176 177Starting in Linux-3.18, the kernel answered YES to _OSI("Darwin")178for the purpose of enabling Mac Thunderbolt support. Further,179if the kernel noticed _OSI("Darwin") being invoked, it additionally180disabled all _OSI("*Windows*") to keep poorly written Mac BIOS181from going down untested combinations of paths.182 183The Linux-3.18 change in default caused power regressions on Mac184laptops, and the 3.18 implementation did not allow changing185the default via cmdline "acpi_osi=!Darwin". Linux-4.7 fixed186the ability to use acpi_osi=!Darwin as a workaround, and187we hope to see Mac Thunderbolt power management support in Linux-4.11.188