Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI: Document _OSI and _REV for Linux BIOS writers

Based on a recent session at the Linux Plumber's Conference,
we need to be more clear about how a BIOS should use _OSI
to properly support Linux.

Signed-off-by: Len Brown <len.brown@intel.com>
Reviewed-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Len Brown and committed by
Rafael J. Wysocki
bc184618 e5517c2a

+187
+187
Documentation/acpi/osi.txt
··· 1 + ACPI _OSI and _REV methods 2 + -------------------------- 3 + 4 + An ACPI BIOS can use the "Operating System Interfaces" method (_OSI) 5 + to find out what the operating system supports. Eg. If BIOS 6 + AML code includes _OSI("XYZ"), the kernel's AML interpreter 7 + can evaluate that method, look to see if it supports 'XYZ' 8 + and answer YES or NO to the BIOS. 9 + 10 + The ACPI _REV method returns the "Revision of the ACPI specification 11 + that OSPM supports" 12 + 13 + This document explains how and why the BIOS and Linux should use these methods. 14 + It also explains how and why they are widely misused. 15 + 16 + How to use _OSI 17 + --------------- 18 + 19 + Linux runs on two groups of machines -- those that are tested by the OEM 20 + to be compatible with Linux, and those that were never tested with Linux, 21 + but where Linux was installed to replace the original OS (Windows or OSX). 22 + 23 + The larger group is the systems tested to run only Windows. Not only that, 24 + but many were tested to run with just one specific version of Windows. 25 + So even though the BIOS may use _OSI to query what version of Windows is running, 26 + only a single path through the BIOS has actually been tested. 27 + Experience shows that taking untested paths through the BIOS 28 + exposes Linux to an entire category of BIOS bugs. 29 + For this reason, Linux _OSI defaults must continue to claim compatibility 30 + with all versions of Windows. 31 + 32 + But Linux isn't actually compatible with Windows, and the Linux community 33 + has also been hurt with regressions when Linux adds the latest version of 34 + Windows to its list of _OSI strings. So it is possible that additional strings 35 + will be more thoroughly vetted before shipping upstream in the future. 36 + But it is likely that they will all eventually be added. 37 + 38 + What should an OEM do if they want to support Linux and Windows 39 + using the same BIOS image? Often they need to do something different 40 + for Linux to deal with how Linux is different from Windows. 41 + Here the BIOS should ask exactly what it wants to know: 42 + 43 + _OSI("Linux-OEM-my_interface_name") 44 + where 'OEM' is needed if this is an OEM-specific hook, 45 + and 'my_interface_name' describes the hook, which could be a 46 + quirk, a bug, or a bug-fix. 47 + 48 + In addition, the OEM should send a patch to upstream Linux 49 + via the linux-acpi@vger.kernel.org mailing list. When that patch 50 + is checked into Linux, the OS will answer "YES" when the BIOS 51 + on the OEM's system uses _OSI to ask if the interface is supported 52 + by the OS. Linux distributors can back-port that patch for Linux 53 + pre-installs, and it will be included by all distributions that 54 + re-base to upstream. If the distribution can not update the kernel binary, 55 + they can also add an acpi_osi=Linux-OEM-my_interface_name 56 + cmdline parameter to the boot loader, as needed. 57 + 58 + If the string refers to a feature where the upstream kernel 59 + eventually grows support, a patch should be sent to remove 60 + the string when that support is added to the kernel. 61 + 62 + That was easy. Read on, to find out how to do it wrong. 63 + 64 + Before _OSI, there was _OS 65 + -------------------------- 66 + 67 + ACPI 1.0 specified "_OS" as an 68 + "object that evaluates to a string that identifies the operating system." 69 + 70 + The ACPI BIOS flow would include an evaluation of _OS, and the AML 71 + interpreter in the kernel would return to it a string identifying the OS: 72 + 73 + Windows 98, SE: "Microsoft Windows" 74 + Windows ME: "Microsoft WindowsME:Millenium Edition" 75 + Windows NT: "Microsoft Windows NT" 76 + 77 + The idea was on a platform tasked with running multiple OS's, 78 + the BIOS could use _OS to enable devices that an OS 79 + might support, or enable quirks or bug workarounds 80 + necessary to make the platform compatible with that pre-existing OS. 81 + 82 + But _OS had fundamental problems. First, the BIOS needed to know the name 83 + of every possible version of the OS that would run on it, and needed to know 84 + all the quirks of those OS's. Certainly it would make more sense 85 + for the BIOS to ask *specific* things of the OS, such 86 + "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 for 90 + _OS "Microsoft Windows NT", though it seems somewhat far-fetched 91 + that anybody would install those old operating systems 92 + over what came with the machine. 93 + 94 + Linux answers "Microsoft Windows NT" to please that BIOS idiom. 95 + That is the *only* viable strategy, as that is what modern Windows does, 96 + and so doing otherwise could steer the BIOS down an untested path. 97 + 98 + _OSI is born, and immediately misused 99 + -------------------------------------- 100 + 101 + With _OSI, the *BIOS* provides the string describing an interface, 102 + and asks the OS: "YES/NO, are you compatible with this interface?" 103 + 104 + eg. _OSI("3.0 Thermal Model") would return TRUE if the OS knows how 105 + to deal with the thermal extensions made to the ACPI 3.0 specification. 106 + An old OS that doesn't know about those extensions would answer FALSE, 107 + and a new OS may be able to return TRUE. 108 + 109 + For an OS-specific interface, the ACPI spec said that the BIOS and the OS 110 + were to agree on a string of the form such as "Windows-interface_name". 111 + 112 + But two bad things happened. First, the Windows ecosystem used _OSI 113 + not as designed, but as a direct replacement for _OS -- identifying 114 + the OS version, rather than an OS supported interface. Indeed, right 115 + from the start, the ACPI 3.0 spec itself codified this misuse 116 + in example code using _OSI("Windows 2001"). 117 + 118 + This misuse was adopted and continues today. 119 + 120 + Linux had no choice but to also return TRUE to _OSI("Windows 2001") 121 + and its successors. To do otherwise would virtually guarantee breaking 122 + a BIOS that has been tested only with that _OSI returning TRUE. 123 + 124 + This strategy is problematic, as Linux is never completely compatible with 125 + the latest version of Windows, and sometimes it takes more than a year 126 + to iron out incompatibilities. 127 + 128 + Not to be out-done, the Linux community made things worse by returning TRUE 129 + to _OSI("Linux"). Doing so is even worse than the Windows misuse 130 + of _OSI, as "Linux" does not even contain any version information. 131 + _OSI("Linux") led to some BIOS' malfunctioning due to BIOS writer's 132 + using it in untested BIOS flows. But some OEM's used _OSI("Linux") 133 + in tested flows to support real Linux features. In 2009, Linux 134 + removed _OSI("Linux"), and added a cmdline parameter to restore it 135 + for legacy systems still needed it. Further a BIOS_BUG warning prints 136 + for all BIOS's that invoke it. 137 + 138 + No BIOS should use _OSI("Linux"). 139 + 140 + The result is a strategy for Linux to maximize compatibility with 141 + ACPI BIOS that are tested on Windows machines. There is a real risk 142 + of over-stating that compatibility; but the alternative has often been 143 + catastrophic failure resulting from the BIOS taking paths that 144 + were never validated under *any* OS. 145 + 146 + Do not use _REV 147 + --------------- 148 + 149 + Since _OSI("Linux") went away, some BIOS writers used _REV 150 + to support Linux and Windows differences in the same BIOS. 151 + 152 + _REV was defined in ACPI 1.0 to return the version of ACPI 153 + supported by the OS and the OS AML interpreter. 154 + 155 + Modern Windows returns _REV = 2. Linux used ACPI_CA_SUPPORT_LEVEL, 156 + which would increment, based on the version of the spec supported. 157 + 158 + Unfortunately, _REV was also misused. eg. some BIOS would check 159 + for _REV = 3, and do something for Linux, but when Linux returned 160 + _REV = 4, that support broke. 161 + 162 + In response to this problem, Linux returns _REV = 2 always, 163 + from mid-2015 onward. The ACPI specification will also be updated 164 + to reflect that _REV is deprecated, and always returns 2. 165 + 166 + Apple Mac and _OSI("Darwin") 167 + ---------------------------- 168 + 169 + On Apple's Mac platforms, the ACPI BIOS invokes _OSI("Darwin") 170 + to determine if the machine is running Apple OSX. 171 + 172 + Like Linux's _OSI("*Windows*") strategy, Linux defaults to 173 + answering YES to _OSI("Darwin") to enable full access 174 + to the hardware and validated BIOS paths seen by OSX. 175 + Just like on Windows-tested platforms, this strategy has risks. 176 + 177 + Starting in Linux-3.18, the kernel answered YES to _OSI("Darwin") 178 + for the purpose of enabling Mac Thunderbolt support. Further, 179 + if the kernel noticed _OSI("Darwin") being invoked, it additionally 180 + disabled all _OSI("*Windows*") to keep poorly written Mac BIOS 181 + from going down untested combinations of paths. 182 + 183 + The Linux-3.18 change in default caused power regressions on Mac 184 + laptops, and the 3.18 implementation did not allow changing 185 + the default via cmdline "acpi_osi=!Darwin". Linux-4.7 fixed 186 + the ability to use acpi_osi=!Darwin as a workaround, and 187 + we hope to see Mac Thunderbolt power management support in Linux-4.11.