Tuesday, May 1, 2018

ACPI Debugging (1) - ACPI AML Debugger in Ubuntu 18.04

ACPICA is a project that provides an operating system (OS)-independent reference implementation. It also contains a list of utilities such as ASL compiler (iasl), acpiexec (an AML emulator) and so on. However, debugging AML on Linux in real time wasn't provided in ACPICA ... until Linux Kernel 4.13.

The aml-debugger.txt the instruction of how to enable AML debugger, is available at Documentation/acpi/ in Linux kernel source code. In short, two things are required to run AML debugging
  1. Enabling AML debugging (CONFIG_ACPI_DEBUGGER=y & CONFIG_ACPI_DEBUGGER_USER=m) in Linux kernel
  2. Compile an utility, acpidbg from Linux kernel (I uploaded a copy here)
While compiling a custom-build kernel with the above two config is nothing new to kernel developers, it is often inconvenient for firmware developers who need to verify ACPI implementation in their firmware. Fortunately, Ubuntu 18.04 (x64) enables these two config by default, and one can run acpidbg on Ubuntu 18.04 - even on Ubuntu Live from USB too!

Executing acpidbg on Ubuntu 18.04 is very straight-forward

and "help" shows a list supported commands

acpidbg is particularly handy when one needs to evaluate any ACPI AML objects during runtime - especially the ones that changes under different conditions. This may be best explained by some examples below:

Example - Determine implementation for AC power status. This includes 1) find _PSR object, 2) evaluate _PSR when AC is disconnected, and 3) evaluate _PSR when AC is connected.

acpidbg also works with more complex returns such as packages.
Example - Determine battery information and status. This include 1) find _BIF and _BST objects, 2) evaluate _BIF and _BST objects (note _BST changes dynamically).

acpidbg can decode bit fields in the return to save some time on counting bits. Please try to run acpidbg on any _PLD objects and you will understand what I mean :).

Wednesday, November 22, 2017

[Presentation] Firmware Test Suite - Uses, Development, Contribution and GPL

I did a presentation of "Firmware Test Suite - Uses, Development, Contribution and GPL" in UEFI Plugfest in Taipei on Nov 1 2017. The presentation is shared @ slideshare and can be viewed below:

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/lfdk1.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. :-)