跳转至内容

DSDT

来自 ArchWiki

DSDT(Differentiated System Description Table,差异化系统描述表)是ACPI规范的一部分。它提供了关于给定系统支持的电源事件的信息。ACPI表由制造商通过固件提供。Linux的一个常见问题是缺少ACPI功能,例如:风扇不转、合上盖子屏幕不关闭等。这可能源于DSDT是专门为Windows设计的,可以在安装后进行修补。本文的目标是分析和重建一个错误的DSDT,以便内核可以覆盖默认的DSDT。

基本上,DSDT表是在ACPI(电源管理)事件上运行的代码。

注意 Linux ACPI[失效链接 2023-09-16—HTTP 404]项目的目标是让Linux在未修改的固件上正常工作。如果您在现代内核上仍然发现此类变通方法是必要的,那么您应该考虑提交一个bug报告

开始之前

硬件制造商可能已经发布了更新的固件,修复了与ACPI相关的问题。安装更新的固件通常比此方法更可取,因为它避免了重复工作。

此过程确实会干扰您安装中的一些相当基础的代码。您将需要对所做的更改绝对确定。您也可以考虑事先克隆您的磁盘

即使在尝试自行修复DSDT之前,您也可以尝试几种不同的快捷方式。

让内核报告一个Windows版本

使用变量acpi_os_name作为内核参数。例如:

acpi_os_name="Microsoft Windows NT"

要添加一个已识别的操作系统接口,请使用变量acpi_osi

acpi_osi="Linux"

要仅使用一个操作系统接口,请添加acpi_osi=!。这会告诉固件只有一个支持的操作系统,因此这通常是推荐的解决方案。

acpi_osi=! acpi_osi="Windows 2022"

要删除一个接口,请在字符串的开头使用感叹号。

acpi_osi="!Windows 2012"

其他要测试的字符串

  • "Microsoft Windows XP"
  • "Microsoft Windows 2000"
  • "Microsoft Windows 2000.1"
  • "Microsoft Windows ME: Millennium Edition"
  • "Microsoft WindowsME: Millennium Edition"
  • "Windows 2001"
  • "Windows 2006"
  • "Windows 2009"
  • "Windows 2012"
  • "Windows 2015"
  • "Windows 2020"
提示 虽然不推荐,但您可以尝试 "Linux"。

出于好奇,您可以按照以下步骤提取您的DSDT并搜索.dsl文件。只需grep "Windows"看看有什么结果。

寻找一个已修复的DSDT

DSDT文件最初是用ACPI源语言(.asl/.dsl文件)编写的。使用编译器,它可以生成一个'ACPI Machine Language'文件(.aml)或一个十六进制表(.hex)。要将该文件集成到您的Arch安装中,您需要获取一个已编译的.aml文件 — 这意味着是自行编译还是信任互联网上的陌生人,由您自行决定。如果您确实从互联网上下载了一个文件,它很可能是一个压缩的.asl文件。因此,您需要解压缩它并进行编译。这样做的好处是您不必自己研究特定的代码修复。

拥有与您相同笔记本电脑的Arch用户:他们是极少数中的极少数。尝试浏览其他发行版/Linux论坛,了解关于同一型号的讨论。他们很可能遇到了相同的问题,并且因为用户数量多,或者因为他们技术娴熟 — 有人已经制作了一个可用的DSDT,甚至可能提供预编译的版本(再次声明,使用风险自负)。搜索引擎是您最好的工具。尝试保持简短:'型号名称' + 'dsdt' 可能会产生结果。

自行重新编译

您在此过程中最好的资源将是ACPI Spec主页Linux ACPI Project[失效链接 2023-09-16—HTTP 404],它取代了acpi.sourceforge.net上发生的活动。简而言之,您可以使用Intel的ASL编译器将系统的DSDT表转换为源代码,定位/修复错误,然后重新编译。

您需要安装acpica来修改代码。

原始代码是用什么编译的? 检查您的系统DSDT是使用Intel还是Microsoft编译器编译的。

# dmesg | grep DSDT
ACPI: DSDT 00000000bf7e5000 0A35F (v02 Intel  CALPELLA 06040000 INTL 20060912)
ACPI: EC: Look up EC in DSDT

如果使用的是Microsoft的编译器,缩写INTL将是MSFT。在示例中,反编译/重新编译DSDT时有5个错误。经过一些谷歌搜索和深入研究ACPI规范后,其中两个很容易修复。三个错误是由于编译器版本不同造成的,而且后来发现,ACPICA在启动时会处理这些问题。内核的ACPICA组件可以处理编译DSDT时出现的大多数微小错误。所以,如果您的系统正常工作,请不要为编译错误而烦恼。

提取二进制ACPI表

# cat /sys/firmware/acpi/tables/DSDT > dsdt.dat

将ACPI表反汇编为.dsl文件

$ iasl -d dsdt.dat

尝试从.dsl文件创建一个十六进制AML表(用C语言)

$ iasl -tc dsdt.dsl

检查创建十六进制AML表时输出的任何错误并修复它们。例如:

dsdt.dsl   6727:                         Name (_PLD, Buffer (0x10)  
Error    4105 -          Invalid object type for reserved name ^  (found BUFFER, requires Package)

在发生错误的位置(第6727行)修改文件。

(_PLD, Package(1) {Buffer (0x10)
{
    ...
}})

增加OEM版本。否则,内核将不会应用修改后的ACPI表。例如,在增加OEM版本之前:

DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000000)

增加OEM版本之后:

DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000001)

修复所有错误并增加OEM版本后,再次创建十六进制AML表。

$ iasl -tc dsdt.dsl

您可能想尝试选项-ic,用于C include文件以插入内核源代码。如果没有错误和警告,您就可以开始了。

使用修改后的代码

警告 每次BIOS更新后,您都需要重新修复DSDT并重复这些步骤!

至少有两种方法可以使用自定义DSDT:

  • 创建一个未压缩的CPIO归档,该归档在启动早期由内核加载。
  • 将其编译到内核中。

使用mkinitcpio的acpi_override钩子

mkinitcpio提供了一个acpi_override钩子,它会获取在/usr/initcpio/acpi_override//etc/initcpio/acpi_override/中找到的所有.aml文件,并将它们放入/kernel/firmware/acpi/目录下的早期未压缩CPIO归档中。这避免了手动创建单独的CPIO归档或更改引导加载程序配置的需要,因为mkinitcpio将未压缩的CPIO归档与主initramfs映像一起打包成一个文件。

首先,创建/etc/initcpio/acpi_override目录并将所有需要的.aml文件复制到其中。例如:

# mkdir /etc/initcpio/acpi_override
# cp dsdt.aml /etc/initcpio/acpi_override/

acpi_override添加到/etc/mkinitcpio.conf中的HOOKS数组。

/etc/mkinitcpio.conf
HOOKS=(... acpi_override)

最后,重新生成initramfs并重新启动。

使用CPIO归档

这种方法的优点是您无需重新编译内核,并且更新内核也不会导致需要重复这些步骤。

此方法要求启用ACPI_TABLE_UPGRADE=y内核配置(对于linux软件包为true)。有关详细信息,请参阅[1]

首先,创建以下文件夹结构:

$ mkdir -p kernel/firmware/acpi

将已修复的ACPI表复制到刚创建的kernel/firmware/acpi文件夹中,例如:

$ cp dsdt.aml ssdt1.aml kernel/firmware/acpi

在包含新创建的kernel/文件夹的同一目录下运行:

$ find kernel | cpio -H newc --create > acpi_override

这将创建包含已修复ACPI表的CPIO归档。将归档复制到boot目录。

# cp acpi_override /boot

最后,配置引导加载程序以加载您的CPIO归档,例如Microcode#Microcode in a separate initramfs file中的示例。

现在只剩下重新启动并验证结果了。

编译到内核中

您需要熟悉编译自己的内核。最直接的方法是使用“传统”方法。编译DSDT后,iasl会生成两个文件:dsdt.hexdsdt.aml

使用menuconfig

  • 禁用“仅选择不需要编译时外部固件的驱动程序”。位于“设备驱动程序 -> 通用驱动程序选项”。
  • 启用“包含自定义DSDT”并指定已修复DSDT文件的绝对路径(dsdt.hex,而不是dsdt.aml)。位于“电源管理和ACPI选项 -> ACPI(高级配置和电源接口)支持”。

使用GRUB加载AML

如果您使用GRUB,您可以使用一个更简单的方法。将上面创建的.aml文件复制到您的启动分区。

# cp dsdt_patch.aml /boot

然后在您的GRUB配置中添加以下行:

acpi /dsdt_patch.aml

例如,您可以将此添加到/etc/grub.d/40_custom,不要忘记之后生成您的GRUB配置。

使用dracut加载AML

如果您使用Dracut,您可以简单地将上面创建的.aml文件复制到一个指定的位置。必须创建一个相应的配置文件/etc/dracut.conf.d/acpi-fix.conf

acpi_override="yes"
acpi_table_dir="/usr/local/lib/firmware/acpi"

验证覆盖是否成功

查找确认覆盖的消息,例如:

# dmesg | grep ACPI
[    0.000000] ACPI: Override [DSDT-   A M I], this is unsafe: tainting kernel
[    0.000000] ACPI: DSDT 00000000be9b1190 Logical table override, new table: ffffffff81865af0
[    0.000000] ACPI: DSDT ffffffff81865af0 0BBA3 (v02 ALASKA    A M I 000000F3 INTL 20130517)

参见

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.