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