Monday, July 10, 2017

Changes of the _OSI object in ACPI spec 6.1a & 6.2 and in Linux

ACPI _OSI is the most controversial object in my opinions. Not only _OSI was not welcomed by Linux kernel but also it has been discussed multiple times in ACPI Spec Work Group (ASWG) meetings. Many spec contributers tried to remove _OSI from ACPI spec, but the impacts were too great to depreciate _OSI...

Until _OSI is now redefined in ACPI 6.1a & ACPI 6.2 as below



Still confused? Let's take a look at "Table 5-163 Predefined Operating System Vendor String Prefixes" in ACPI 6.1a below:

Operating System Vendor String Prefix Description
“FreeBSD” <FeatureGroupString> Free BSD OS features/interfaces
“HP-UX” <FeatureGroupString> HP Unix Operating Environment OS features/interfaces
“Linux” <FeatureGroupString> GNU/Linux Operating system OS features/interfaces
“OpenVMS” <FeatureGroupString> HP OpenVMS Operating Environment OS features/interfaces
“Windows” <FeatureGroupString> Microsoft Windows OS features/interfaces

While <FeatureGroupString> looks like something new, this addition is backward-compatible - it is very common to see "Windows 2009" (Windows 7), "Windows 2013" (Windows 8.1) and "Windows 2015" (Windows 10). 2009, 2013 and 2015 are sets of new features provided by each new Windows OS and is more than a name of each new OS. Does this make sense?

In fact, the main purpose of this _OSI change is to clarify "_OSI is not to be used to detect operating systems but feature sets supported by operating systems" - these aren't my words but the words of spec contributers in ASWG's meetings. In other words, please stop complaining why OSI("Linux") doesn't work - this usage is never the intention of ACPI spec.

While _OSI("Linux") does NOT  work in Linux kernel by default, kernel maintainers now agree Linux isn't always compatible with Windows and using _OSI("Windows xxxx") isn't the best idea. Each OEM can define different "Linux <FeatureGroupString>" in their ACPI BIOS, and OEM can submit patches so new strings will be recognized by Linux kernel.

The string should be in the format "Linux-OEM-my_interface_name" as defined here. I would guess a valid string can be something like "Linux-Dell-SuperVGA" or "Linux-HP-CrystalAudio" (I made them up, and they aren't recognized by Linux kernel). The kernel document discusses the history and the rules, and BIOS engineers should not abuse this mechanism - if you want to a workaround, create a new string for it, ex. "Linux-Dell-VGA-Workaround" and submit a new patch to Linux kernel. DO NOT use unrelated OEM strings for other purposes.

The new _OSI is introduced for very short time and no ACPI BIOS uses new Linux strings yet. It is our hope this can provide better compatibilities between ACPI BIOS and non-Windows OS's. If anyone has any feedbacks or concerns about this new _OSI thing, I am happy to answer or forward to ACPI Work Group for more discussion.

Friday, July 7, 2017

Why cannot ACPI _REV object be used to detect Linux anymore?

Linux community is never a fan of distinguishing Windows & Linux in BIOS (see my 2012's blog Why does Linux Say It Is not Linux in _OSI("Linux")?). However, many BIOS engineers seem to see the needs of to workaround BIOS bugs for Linux regardlessly. After realising _OSI("Linux") cannot be used by default, some creative BIOS engineers figured ACPI's _REV object could be used for this purpose some years ago, based on the following facts:

1. _REV definition in ACPI spec 5.1


2. Windows returns 2 & Linux returns ACPI revision


While it is obvious it was Windows which did not follow ACPI spec, nothing can stop BIOS engineers from mis-using _REV as a mechanism to detect Linux in BIOS ASL codes.

It did not take long when ACPI Spec Work Group (ASWG), the owner and the publisher of ACPI spec, realised that many systems are mis-using _REV objects in their firmware. Eventually a spec contributer submitted a change to _REV object in ACPI 6.0 and later, and the _REV object is now defined as below:



After ACPI 6.0 was published, the corresponding changes are also made to Linux kernel - the evaluation of _REV now returns 2 in kernel 4.1 and later (for example, Ubuntu 15.10 with kernel 4.2).

In order to provide backward compatibility, a new kernel parameter "acpi_rev_override" was introduced for those who still want to use _REV = 5 in their BIOS ASL code, but most of major Linux distributions do not include this kernel parameter by default, and it should be used with cautions.

If you are using one of the systems with _REV in the firmware, you can develop a kernel patch to add your system to the _REV quirk list acpi_rev_dmi_table in drivers/acpi/blacklist.c as below, like the patch I submitted.

static struct dmi_system_id acpi_rev_dmi_table[] __initdata = {
        {
         .callback = dmi_enable_rev_override,
         .ident = "DELL XPS 13 (2015)",
         .matches = {
                      DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
                      DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343"),
                },
        },
        ...
  • DMI_SYS_VENDOR can be identified by sudo dmidecode -s system-manufacturer 
  • DMI_PRODUCT_NAME can be identified by sudo dmidecode -s system-product-name.

Thursday, June 4, 2015

Uitlity: Reading and Writing PCI, IO and memory with Linux Firmware Debug Kit (lfdk) in Linux

Many BIOS engineers are familiar with ru.exe in DOS and R/W everything in Windows.  One frequently asked question is whether there is an equivalent utility in Linux.  The answer is "sort of".

Linux Firmware Debug Kit (lfdk) provides read/write functions to PCI[1], IO and memory spaces.

lfdk's deb package is available but it is outdated. I usually download [3] and compile source code, and run ldfk manually in a terminal (ctrl + alt + T if you are running Ubuntu +Unity) as below:

  1. sudo apt-get install -f git libncurses-dev
  2. git clone https://github.com/alexhungce/lfdk.git
  3. cd lfdk
  4. make
  5. cd bin
  6. sudo insmod ./lfdd_drv.ko
  7. sudo ./lfdk

A familiar screen will pop up


The navigation  is to use arrow keys and hotkeys L, M and I to different spaces as instructed on the bottom of the lfdk.



[1] Built-in lspci command can be used to read PCI configuration space, too
[2] This is tested in Ubuntu Linux 12.04 to 15.04.
[3] One can also download the source code from sourceforge.net above.

Monday, November 11, 2013

[Presentation] BIOS, Linux and Firmware Test Suite in-between

I was invited to present "BIOS, Linux and Firmware Test Suite in-between" in Debian Taiwan's MiniDeb Conf in Taipei, Taiwan on Nov 9, 2013. The presentation is shared @ slideshare and can be viewed below:



Firmware Test Suite is an ongoing project that targets to automate firmware and hardware related tests. It receives some attentions from various parties including hardware, software and system vendors. (I also presented the similar topic in UEFI Plugfest in Sept, 2013, and the presentation slides are available @ http://uefi.org/learning_center/presentationsandvideos).

Friday, August 30, 2013

Info Session: Improving BIOS Compatibility on Linux

I had a chance to present a BIOS-related topic "Improving BIOS Compatibility on Linux" in workplace, and the presentation is publicly available. Hope it may interest someone. :-)



Tuesday, July 2, 2013

ACPI AC Adapter (2) - How does Linux handle it?

ACPI AC Adapter Implementation in Linux Kernel

ACPI AC Adapter (1) introduced the theory of interfaces between BIOS and an OS, but a real example is always more convincing than anything else.

SysFs Node

In Linux, one can find out whether a laptop PC has AC plugged in by "cat /sys/class/power_supply/online". Linux ACPI AC driver evaluates _PSR and returns 1 for "AC is online" and 0 for "AC is offline". The sysfs node is also used by user-space applications.

Supported Objects

Surprisingly (or not), not all control methods defined in ACPI AC are supported. In fact, only _PSR is evaluated in Linux ACPI AC driver.

As ACPI covers very broad and rich features, kernel developers may find some of them "uninteresting". For example. _PSR is required, in software's perspective, to know whether AC is online, but which parts of a system is powered (i.e. _PCL) may not be that useful for laptop PCs (which AC usually powers everything). In some other cases, few BIOS implements _PIF and there is hardly any reason that someone decides to add _PIF supports to Linux.

AC Events



It is very interesting to see how an driver responds to ACPI events. In the above source code it is obvious that the driver behaves the same for all events equals 0x80, 0x00, 0x01. It also responds the same to all other ACPI events with an additional error message.

For example, it was seen that some BIOSes issue Notify(AC, 0x81) when AC adapter is plugged or plugged. Apparently Linux kernel does not think 0x81 is a valid event (nor can I find any 0x81 for AC in ACPI); however, Linux still behaves as well with Notify(AC, 0x80).

Suspend and Resume



Another interesting part in ACPI AC driver is acpi_ac_resume called when a system resumes from suspend or hiberation. It compares the "before" and "after" _PSR and issues an uEvent if they are different. This implies BIOSes need not to issue a Notify(AC, 0x80) during waking up to save some CPU cycles; however, this may be specific to Linux. As there is no rule in ACPI spec, one may want to verify the behaviors of the target OSes (ex. Windows).

References

Linux kernel source code (3.10): ACPI AC adpater driver in drivers/acpi/ac.c

Sunday, June 23, 2013

ACPI AC Adapter (1) - Introduction

In ACPI Control Method Battery (2), we see how ACPI's definition for control method battery and read the data in Ubuntu Linux. However, battery does not usually go alone - ACPI AC Adapter always goes with it.

AC Adapter Interface

Unlike the complexity of a control method battery, AC adapter is much simpler and three objects are mandatory:
  • _HID (Hardware ID) - needs to be ACPI0003
  • _PSR (Power Source) - indicates whether AC is online
  • _PCL(1) (Power Consumer List) - refers what is powered by AC

Below is a sample for AC adapter that returns whether AC is online from an EC register in _PSR:



Plugging and Unplugging AC Adapter

When AC adapter is plugged or unplugged, BIOS needs to issue a notification event as the example:



It is worth noting that only 0x80 is needed. Some BIOS will also issue Notify(_SB.AC, 0x81) that is not only redundant but also incorrect. Some BIOS also issues Notify(_SB.BAT, 0x80) and Notify(_SB.BAT, 0x81). While OS is smart enough to know that battery status is also changed, one may argument that issuing notification to battery is correct and at least won't break anything.

In my opinions, it is not incorrect to issue Notify(_SB.BAT, 0x80) as Battery State in _BST is definitely changed to discharging, assuming only one AC source and one battery are present in a system; however, issuing Notify(_SB.BAT, 0x81) and asking OS to re-enumerate _BIF/_BIX is only a waste of CPU cycles.

What is ACPI AC Adapter Affecting?

It is definitely not surprising to know the little AC icon in OS's taskbar uses the return value of AC._PSR - that's  the only way that an OS knows whether a system is powered by an AC adapter. But... what else?

It is true that hardware state is different from powered-by-AC to powered-by-battery - at least from the viewpoint of the power circuit; however, this is only small part of the system board and we often see much more difference and affecting the system. When a system is powered by AC source, it is, in most cases, running at performance mode - CPU can spend more time in maximum frequency, power-saving features are less aggressive, fan runs at higher speed, and the panel may be brighter. All of these can be changed when OS finds out AC is offline from AC._PSR.

The implication? If one sees stability issues without AC only, playing around _PSR may help identify whether it is the power circuit or is an OS beahviours, i.e. one device and its driver are too aggressive with its power-saving features. One way to distinguish whether it is always reports 1 in _PSR - if the problem persists, it is the power circuit (hardware) that causes the problem. I have seem a number of times that bad-quality power components that hang the system and many other times that a device or its driver failed the system. This technique always helps a quick and good direction to real problems.

Next...

How does Linux kernel handle ACPI AC adapter?

Note

  1. It seems _PCL is defined but is not used in Linux kernel.

References

  • ACPI Specification 5.0 - Sec. 10.3
  • ACPI Specification 5.0 - Table 5-121
  • Linux kernel source code (3.10)