通过 initrd 升级 ACPI 表

这是关于什么的

如果 ACPI_TABLE_UPGRADE 编译选项为真,则可以通过升级 BIOS 提供的 ACPI 表,使用一个经过修改的、更新版本的工具,或者安装全新的 ACPI 表,来升级由 ACPI 表定义的 ACPI 执行环境。

当在单个映像中构建带有内核的 initrd 时,选项 ACPI_TABLE_OVERRIDE_VIA_BUILTIN_INITRD 也应该为真,此功能才能正常工作。

有关可以升级/安装的 ACPI 表的完整列表,请查看 drivers/acpi/tables.c 中的 char *table_sigs[MAX_ACPI_SIGNATURE]; 定义。

iasl(Intel 的 ACPI 编译器和反汇编器)知道的所有 ACPI 表都应该是可覆盖的,除了

  • ACPI_SIG_RSDP(具有 6 个字节的签名)

  • ACPI_SIG_FACS(没有普通的 ACPI 表头)

两者也可以实现。

这是为了什么

如果您发现一个如此严重的错误,以至于 Linux 内核不接受该错误的解决方法,请向您的平台/BIOS 供应商投诉。此功能允许您在您的平台/BIOS 供应商发布升级后的 BIOS 二进制文件之前升级有错误的表。

平台/BIOS 供应商可以使用此功能来提供 Linux 兼容的环境,而无需修改底层平台固件。

此功能还提供了一个强大的功能,可以通过修改旧平台提供的 ACPI 表或插入新的 ACPI 表,轻松调试和测试 ACPI BIOS 表与 Linux 内核的兼容性。

它可以在任何内核中启用,并且应该启用,因为没有工具化的 initrd 不会发生功能更改。

它是如何工作的

# Extract the machine's ACPI tables:
cd /tmp
acpidump >acpidump
acpixtract -a acpidump
# Disassemble, modify and recompile them:
iasl -d *.dat
# For example add this statement into a _PRT (PCI Routing Table) function
# of the DSDT:
Store("HELLO WORLD", debug)
# And increase the OEM Revision. For example, before modification:
DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000000)
# After modification:
DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000001)
iasl -sa dsdt.dsl
# Add the raw ACPI tables to an uncompressed cpio archive.
# They must be put into a /kernel/firmware/acpi directory inside the cpio
# archive. Note that if the table put here matches a platform table
# (similar Table Signature, and similar OEMID, and similar OEM Table ID)
# with a more recent OEM Revision, the platform table will be upgraded by
# this table. If the table put here doesn't match a platform table
# (dissimilar Table Signature, or dissimilar OEMID, or dissimilar OEM Table
# ID), this table will be appended.
mkdir -p kernel/firmware/acpi
cp dsdt.aml kernel/firmware/acpi
# A maximum of "NR_ACPI_INITRD_TABLES (64)" tables are currently allowed
# (see osl.c):
iasl -sa facp.dsl
iasl -sa ssdt1.dsl
cp facp.aml kernel/firmware/acpi
cp ssdt1.aml kernel/firmware/acpi
# The uncompressed cpio archive must be the first. Other, typically
# compressed cpio archives, must be concatenated on top of the uncompressed
# one. Following command creates the uncompressed cpio archive and
# concatenates the original initrd on top:
find kernel | cpio -H newc --create > /boot/instrumented_initrd
cat /boot/initrd >>/boot/instrumented_initrd
# reboot with increased acpi debug level, e.g. boot params:
acpi.debug_level=0x2 acpi.debug_layer=0xFFFFFFFF
# and check your syslog:
[    1.268089] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
[    1.272091] [ACPI Debug]  String [0x0B] "HELLO WORLD"

iasl 能够反汇编和重新编译很多不同的静态 ACPI 表。

在哪里检索用户空间工具

iasl 和 acpixtract 是 Intel 的 ACPICA 项目的一部分:https://acpica.org/

并且应该由发行版打包(例如在 SUSE 上的 acpica 包中)。

acpidump 可以在 Len Brown 的 pmtools 中找到:ftp://linuxkernel.org.cn/pub/linux/kernel/people/lenb/acpi/utils/pmtools/acpidump

此工具也是 SUSE 上 acpica 包的一部分。或者,使用的 ACPI 表可以通过最新内核中的 sysfs 检索:/sys/firmware/acpi/tables