透過 initrd 升級 ACPI 表

這是關於什麼

如果 ACPI_TABLE_UPGRADE 編譯選項為 true,則可以透過使用經過檢測、修改、更新的版本升級 BIOS 提供的 ACPI 表,或安裝全新的 ACPI 表,來升級由 ACPI 表定義的 ACPI 執行環境。

在將 initrd 與核心構建成單個映象時,ACPI_TABLE_OVERRIDE_VIA_BUILTIN_INITRD 選項也應為 true,此功能才能正常工作。

有關所有可升級/安裝的 ACPI 表的完整列表,請檢視 drivers/acpi/tables.c 中 char *table_sigs[MAX_ACPI_SIGNATURE]; 的定義。

iasl (Intel 的 ACPI 編譯器和反彙編器) 所知的所有 ACPI 表都應該可以被覆蓋,除了

  • ACPI_SIG_RSDP (有 6 位元組的簽名)

  • ACPI_SIG_FACS (沒有普通的 ACPI 表頭)

這兩者也可以實現。

這是用來做什麼的

如果您發現了一個非常嚴重的 bug,以至於 Linux 核心不接受其變通方案,請向您的平臺/BIOS 供應商投訴。此功能允許您在您的平臺/BIOS 供應商釋出升級的 BIOS 二進位制檔案之前,升級有 bug 的表。

此功能可供平臺/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 Browns 的 pmtools 中找到:ftp://kernel.linux.club.tw/pub/linux/kernel/people/lenb/acpi/utils/pmtools/acpidump

此工具也是 SUSE 上 acpica 包的一部分。另外,在最新的核心中,可以透過 sysfs 檢索使用的 ACPI 表:/sys/firmware/acpi/tables