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