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