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