Monday, February 13, 2012

Why does Linux Say It Is not Linux in _OSI("Linux")?

First, let me explain what _OSI is.

Section 5.7.2 of ACPI specification defines it as below:
_OSI (Operating System Interfaces)

This object provides the platform with the ability to query OSPM to determine the set of ACPI related interfaces, behaviors, or features that the operating system supports.
_OSI provides the platform with the ability to support new operating system versions and their associated features when they become available. OSPM can choose to expose new functionality based on the _OSI argument string. That is, OSPM can use the strings passed into _OSI to ensure compatibility between older platforms and newer operating systems by maintaining known compatible behavior for a platform.

In theory, BIOS can use _OSI to provide different functionality for different operating systems to a specific platform.

Now, the answer to the question "Why does Linux Say It Is not Linux in _OSI("Linux")?" is - because Linux kernel wants to provide better quality and user-experiences.

Why is the differentiation is not desirable for Linux? Linux source code (drivers/acpi/osl.c) gives a history how the design decision was made as below:

 * The story of _OSI(Linux)
 * From pre-history through Linux-2.6.22,
 * Linux responded TRUE upon a BIOS OSI(Linux) query.
 * Unfortunately, reference BIOS writers got wind of this
 * and put OSI(Linux) in their example code, quickly exposing
 * this string as ill-conceived and opening the door to
 * an un-bounded number of BIOS incompatibilities.
 * For example, OSI(Linux) was used on resume to re-POST a
 * video card on one system, because Linux at that time
 * could not do a speedy restore in its native driver.
 * But then upon gaining quick native restore capability,
 * Linux has no way to tell the BIOS to skip the time-consuming
 * POST -- putting Linux at a permanent performance disadvantage.
 * On another system, the BIOS writer used OSI(Linux)
 * to infer native OS support for IPMI!  On other systems,
 * OSI(Linux) simply got in the way of Linux claiming to
 * be compatible with other operating systems, exposing
 * BIOS issues such as skipped device initialization.
 * So "Linux" turned out to be a really poor chose of
 * OSI string, and from Linux-2.6.23 onward we respond FALSE.
 * BIOS writers should NOT query _OSI(Linux) on future systems.
 * Linux will complain on the console when it sees it, and return FALSE.
 * To get Linux to return TRUE for your system  will require
 * a kernel source update to add a DMI entry,
 * or boot with "acpi_osi=Linux"

ACPICA User Guide and Programmer Reference also has a similar discussion in Section "Why ACPICA responds TRUE to _OSI (Windows)"
ACPICA responds TRUE to all known Windows strings because ACPICA attempts to be fully compatible with the Windows implementation of ACPI. On the other hand, ACPICA responds FALSE to other operating system strings (such as “Linux”, “FreeBSD”, or “HP-UX”) because doing so has been seen to often cause serious problems. For example, on many platforms, the only path through the ASL code that has been fully tested by the manufacturer is in fact the path for “Windows”. By responding TRUE to other operating system strings, the ASL may execute paths that have had only limited or even no evaluation.

To summarize, returning FALSE in _OSI("Linux") forces better software quality from two perspectives.

1. Not to "workaround" kernel errors in BIOS code - if Linux bugs are found, it should be updated to Linux kernel developers to have them fixed. 
2. To ensure Linux kernel executes code path that is well-tested - the same path Windows would execute. 

In the case of that _OSI("Linux") is really needed, it can be forced with kernel parameter acpi_osi=Linux as in the above comments.

Some OEM/ODM ship their systems with acpi_osi=Linux in their customized images; however, the solution has a downside. If a particular bug is not fixed in future kernel, or it is not a kernel bug but a hardware compatibility bug and cannot be fixed, a clean Linux installation by an end-user without adding this parameters will expose this bug. 

Instead, a better solution would be to have a BIOS setup option for workaround. If the bug is fixed, an end-user can  disable the workaround. A clean installation without acpi_osi=Linux will not expose the bug, either.

_OSI Strings in Ubuntu 

_OSI does not return true for a specific string.  Instead, it returns true for a list of strings.  As in Windows, _OSI in Linux returns true up to a Windows version.  For example, kernel 3.13 (used in Ubuntu 14.04) would report _OSI = true for Windows 7 (ex. "Windows 2012" and all versions before.  The below table lists Windows versions and their supports in Ubuntu Linux

_OSI argument Windows version Supported in Ubuntu
Windows 2000 Windows 2000 Pre-Dapper 6.06 LTS
Windows 2001 Windows XP Pre-Dapper 6.06 LTS
Windows 2001 Windows XP SP1 Pre-Dapper 6.06 LTS
Windows 2001.1 Windows Server 2003 Pre-Dapper 6.06 LTS

Windows 2001 SP2
Windows XP SP2 Pre-Dapper 6.06 LTS

Windows 2001.1 SP1

Windows 2001.1 SP1

Hardy 8.04 LTS

Windows 2006

Windows Vista

Hardy 8.04 LTS

Windows 2006.1

Windows Server 2008

Lucid 10.04 LTS

Windows 2006 SP1

Windows Vista SP1

Lucid 10.04 LTS

Windows 2006 SP2

Windows Vista SP2

Natty 11.04

Windows 2009

Windows 7 and Server 2008 R2

Lucid 10.04 LTS

Windows 2012

Windows 8 and Server 2012

Raring 13.04

Windows 2013

Windows 8.1 and Server 2012 R2

Utopic 14.10

Windows 2015

Windows 10

Wily 15.10

No comments:

Post a Comment