4. ACPI表结构解析

在ACPI定制开发中,所有ACPI表都遵循同一套底层结构规范:先有一个固定36字节的表头(Table Header),再跟随表体(Table Body)。理解表头格式与校验和计算,是判断一张表是否合法、能否被操作系统解析的第一步;而理解DSDT、SSDT、FACP、APIC/MADT等常见表的字段含义,则是后续做补丁、重命名、热补丁注入的基础。

一、核心原理:36字节表头是ACPI表的“身份证”

ACPI规范定义的通用表头由9个字段组成,总长度固定为36字节。无论这张表是DSDT、SSDT还是FACP,前36字节的布局完全一致。操作系统在扫描RSDT/XSDT时,正是依靠表头中的Signature和Length来定位并遍历每一张表。

偏移 长度 字段名 含义说明
0x004Signature表签名,如"DSDT"、"SSDT"、"FACP"、"APIC"
0x044Length整张表的总字节数,含表头
0x081RevisionACPI规范修订版本,如0x02、0x06
0x091Checksum全表字节累加后低8位应为0
0x0A6OEMID原始设备制造商标识
0x108OEM Table ID厂商自定义表标识
0x184OEM Revision厂商表版本号
0x1C4Creator ID生成工具厂商标识
0x204Creator Revision生成工具版本号

其中Signature和Length是最关键的两个字段。Signature决定了表的类型和解析方式,Length决定了表的边界。如果Length写错,操作系统可能读到下一张表的数据,导致解析异常甚至启动失败。

二、校验和计算:8位累加和为0

ACPI表的校验和规则非常简洁:将整张表的所有字节按无符号8位累加,结果对256取模后必须等于0。也就是说,表头中的Checksum字段本身也参与累加,它的作用就是把总和“补齐”到0。

校验和计算逻辑(伪代码):
sum = 0
for byte in table[0 .. Length-1]:
    sum = (sum + byte) & 0xFF
assert sum == 0

修复方法:
sum = 0
for byte in table[0 .. Length-1]:
    sum = (sum + byte) & 0xFF
table[9] = (table[9] - sum) & 0xFF

在Linux下可以用acpidump导出表,再用iasl反编译;在Windows下常用RWEverything或ACPI Toolkit查看。修改任何字段后,必须重新计算Checksum,否则系统会报“ACPI table checksum error”并可能忽略该表。

常见误区:只修改表体数据却忘记更新Checksum,或者修改了Length却没有同步调整表体长度。这两种情况都会导致表被操作系统判定为非法。

三、常见表类型与字段含义

不同Signature对应不同表体结构,下面列出开发中最常接触的几类:

  • DSDT(Differentiated System Description Table):系统主描述表,包含AML字节码,定义设备树、电源管理、GPIO等。每台机器通常只有一张。
  • SSDT(Secondary System Description Table):辅助描述表,可有多张,常用于补充设备定义或做热补丁注入。
  • FACP(Fixed ACPI Description Table):固定ACPI描述表,提供电源管理寄存器、FADT标志、睡眠状态等关键信息。
  • APIC/MADT(Multiple APIC Description Table):描述中断控制器拓扑,包括CPU本地APIC、IOAPIC、中断源覆盖等。

以FACP为例,其表体前几个字段包括Firmware Control、DSDT地址、Preferred PM Profile等;而APIC表体则包含Local APIC Address、Flags以及一系列APIC结构体。开发中做DSDT/SSDT补丁时,最常操作的是AML层面的Device、Method、Scope等对象,而不是直接改表头。

四、案例场景:用iasl反编译并检查表头

假设我们从一台笔记本导出了DSDT.aml,想确认它的表头是否正确。可以使用如下命令:

# 反编译DSDT
iasl -d DSDT.aml

# 查看表头信息(部分输出)
/*
 * Intel ACPI Component Architecture
 * AML/ASL+ Disassembler version 20230628
 * Copyright (c) 2000 - 2023 Intel Corporation
 *
 * Disassembling to symbolic ASL+ operators
 *
 * Name: DSDT
 * Length: 0x0001F2A3
 * Revision: 0x02
 * Checksum: 0x5C
 * OEM ID: "LENOVO"
 * OEM Table ID: "TP-X1"
 * OEM Revision: 0x00001000
 * Creator ID: "INTL"
 * Creator Revision: 0x20230628
 */

如果Checksum显示为0x00且Length与实际文件大小一致,说明表头基本正常。若Checksum非0,则需用工具重新计算。在OpenCore或Clover引导中,ACPI补丁会在加载前自动修正校验和,但手工修改的AML文件仍建议自行校验。

实操建议:每次修改DSDT/SSDT后,先用iasl反编译确认无语法错误,再用acpidump或RWEverything检查Checksum,最后才放入EFI/OC/ACPI目录。

五、复盘与排障要点

当系统出现ACPI相关报错时,可以按以下顺序排查:

  1. 确认表头Signature是否正确,是否被错误重命名。
  2. 检查Length是否与实际文件长度一致。
  3. 重新计算Checksum,确保累加和为0。
  4. 确认OEMID/OEM Table ID是否与目标机型匹配,避免补丁未生效。
  5. 用iasl反编译,检查AML中是否存在未定义引用或语法错误。

掌握表头格式、校验和计算以及常见表类型字段含义,是从“会用工具”走向“能定位问题”的关键一步。后续做SSDT热补丁、设备重命名、电源管理注入时,这些底层知识会反复用到。

ACPI表通用结构:36字节表头 + 表体 Table Header(固定36字节) Signature 0x00 / 4B Length 0x04 / 4B Revision 0x08 / 1B Checksum 0x09 / 1B OEMID 0x0A / 6B OEM Table ID 0x10 / 8B OEM Revision (0x18/4B) Creator ID (0x1C/4B) Creator Revision (0x20/4B) Table Body(长度 = Length - 36) DSDT / SSDT AML字节码 FACP 电源管理寄存器 APIC / MADT 中断控制器拓扑 其他表 HPET / MCFG等 校验和规则:全表字节累加 & 0xFF == 0 Checksum字段参与累加,修改任意字节后必须重新计算 工具:iasl -d 反编译 | acpidump 导出 | RWEverything 查看