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