3.3 ACPI表集成


3.3 ACPI 表集成

本节摘要:ACPI 表是固件交给操作系统的"硬件宪法"——不走指令跳转、不靠寄存器传参,而用一组结构严整、跨平台可解析的数据结构把硬件意图白纸黑字写明。本节讲从硬编码到声明式的范式跃迁、RSDP 锚点与表头校验的多重防伪、DSDT/SSDT 的声明式设备模型,以及操作系统从被动读表到主动谈条件的权力转移。

读前必看

读完后你应当能:讲清 ACPI 用"数据声明"顶替"指令探测"的历史缘由;报出 RSDP、XSDT、FADT、DSDT、MADT 各自管什么;解释表头校验和加厂商标识如何叠成防伪体系;描述 DSDT 里的 AML 如何声明设备与控制方法;还原系统与固件经 ACPI 命名空间谈判的完整回合。

一、从硬编码到可声明:一场被逼出来的范式跃迁

要懂 ACPI 为什么必须嵌进 UEFI,得先翻一段少有人记得的冲突史。

BIOS 年代,操作系统对电源管理(S3 休眠)、热插拔、处理器节能态、性能调节乃至中断路由的掌控,全看厂商脸色:有的走端口硬编码,有的靠特定芯片组寄存器序列,有的甚至要求内核为某款南桥塞一段微码补丁。Windows 95 因为没法统一处理各家主板的唤醒向量而大面积蓝屏;早期 Linux 为了伺候某台非标中断配置的服务器,塞进过几百行条件编译。这套"一块硬件配一个系统补丁"的玩法,到了多核、异构、虚拟化与安全启动的年代彻底破产。

ACPI(高级配置与电源接口)就是来终结乱局的。它的核心主张只有一句:硬件能力不该由固件用指令流执行,而该由固件用数据结构声明;操作系统不该猜硬件行为,而该解析硬件意图、据此生成确定性策略。规范本身不规定任何寄存器读写顺序,只定义一组带严格二进制布局、校验机制与语义约束的表:

  • RSDP(根系统描述指针):全局入口锚,整个 ACPI 世界的罗塞塔石碑;
  • XSDT/RSDT(扩展/根系统描述表):表目录,指向其余各表的物理地址;
  • FADT(固定 ACPI 描述表):固定功能中枢,写明中断号、复位寄存器位置、电源控制块地址等不可枚举的硬连线资源;
  • DSDT/SSDT(差异化/辅助系统描述表):AML 字节码容器,装设备树描述、控制方法与命名空间逻辑;
  • MADT(多 APIC 描述表):多处理器中断拓扑图,精确画出本地中断控制器、I/O 中断控制器与中断源的接线;
  • SLIT/SRAT(局部性与资源亲和表):NUMA 亲和性底座,给内存分配与线程调度提供物理拓扑依据。

这些表合成"静态声明加动态解释"的双层结构:静态部分给出不可变的硬件物理事实;动态部分(DSDT/SSDT 里的 AML)允许固件按配置、温度、版本生成差异化行为——比如开着 Secure Boot 就封掉某条调试通路,检测到加密盘就动态注入设备特定方法。

而 UEFI 是这套范式规模化落地的唯一可信载体。老 BIOS 既没有标准化的表加载与验证机制,内存管理也粗放,保证不了 ACPI 表在系统接管前的完整性;UEFI 不但定义了 ACPI 表协议用来安全登记表实例,还靠系统表与内存属性表的配合,保证 ACPI 表所在的内存页在系统起来后仍被正确标记与保护。换句话说,UEFI 不只是"支持"ACPI,而是把 ACPI 表提拔为固件与操作系统之间的第一等公民。

ACPI 表 性质 核心内容 主要消费者
RSDP 静态锚点 签名与目录表指针 引导早期定位
XSDT 静态目录 各表物理地址列表 表发现入口
FADT 静态事实 复位寄存器、电源控制块 电源管理初始化
DSDT/SSDT 动态 AML 设备树与控制方法 设备枚举与策略
MADT 静态拓扑 中断控制器连接图 多核中断初始化
SRAT/SLIT 静态拓扑 NUMA 节点与距离 调度器亲和性

二、结构即语义:可发现、可验证、可组合

ACPI 表绝不是一堆散装数据,而是一套结构严密的协议。设计哲学浓缩为三根互锁的支柱。

可发现性:RSDP——永不迷路的指针。 故事从 RSDP 讲起。它是一个变长的固定结构,必须落在实模式可寻址的特定区间,且满足两条铁律:ASCII 签名严格匹配(含空格共 8 字节);校验和使整个结构按字节求和为零(模 256)。这个看似朴素的设计藏着心思:它不要求固件知道操作系统会从哪扫起,只要求把锚放进约定俗成的安全岛——既躲开常规 ROM 区,又保证实模式 1MB 空间够得着。UEFI 再推一步:经 ACPI 表协议把 RSDP 地址注入系统配置表,系统免扫描、直取可信入口。

可验证性:从校验和到厂商标识的多重防伪。 每张表的表头走通用格式:签名、长度、版本、校验和、厂商标识、厂商表标识、修订号、编译器信息。校验和只罩住本表自身,防传输与内存位翻转;厂商标识与厂商表标识是第二道闸——它们不是随手填的字符串,而是固件厂商在规范体系里注册的合法身份。内核初始化表时会把厂商标识对已知白名单,一旦看到占位符式的标识,就告警并退回保守策略。这已经超出普通校验和,升格为基于身份的信任谈判。

可组合性:DSDT/SSDT——声明式设备模型的积木。 若说 FADT、MADT 是硬件宪法的条文,DSDT 与 SSDT 就是司法解释与判例汇编。它们不直接写寄存器,而是借 AML 字节码定义符号化的设备命名空间:声明系统里存在一座 PCIe 根桥;声明桥下挂着一块 GPU、位于哪条总线哪个设备号;声明这块 GPU 提供设备特定方法可作厂商控制;声明设备当前处于完全可用状态。这段代码一行 I/O 都不做,却把设备拓扑与能力说得明明白白。

UEFI 固件构建 DSDT 时不必再硬编码地址——它可以从 PCIe 配置空间读回枚举结果动态生成相应片段;SSDT 还允许热插拔设备运行时注入新节点。这正是可组合性的精髓:硬件拓扑不再是固件一次性烧死的静态快照,而是可增量更新、可感知上下文、可受策略驱动的活体模型。

⚠️ 常见坑:AML 在固件编译期固化,设备地址或方法名写错不会在编译时报错,而是拖到系统枚举时才以"设备失踪"的面目出现。给新板子调 ACPI,先用内核的表转储工具确认表确实加载了,再看命名空间里有没有这个设备节点,最后才翻方法执行日志——上来就猜寄存器是效率最低的路。

三、权力转移:从被动读表到主动谈判

ACPI 集成的终极价值不在固件侧的构建,而在系统侧的解读与回应。这不是单向交货,而是一份暗藏权力让渡的双向契约。

启动阶段:早期解析与子系统初始化。 内核启动极早期做三件事:定位与映射——从 UEFI 配置表取 RSDP 地址,解析目录表,把所有表按需分配内存并拷贝;基础校验——逐表过校验和与厂商标识;命名空间构建——拉起 AML 解释器,把设备、方法、名称对象装进全局命名空间树。转折点在总线初始化:它遍历命名空间,对每个设备对象触发驱动探测。此过程甚至可以完全绕开传统的配置空间扫描——一块存储设备的硬件标识若已在表里声明,内核会直接装对应驱动,不等总线慢慢发现。这是 ACPI 给系统的"上帝视角":不再瞎扫总线,而是照着固件给的权威设备清单精准投放驱动。

运行时交互:AML 解释器与动态契约。 ACPI 表的活力在运行期才爆发。能力协商方法(OSC)是标本:系统准备接管电源管理时,向根桥设备发起调用,递上装有自身能力位图的缓冲区;固件的 AML 代码收到后可以执行任意逻辑——查安全启动状态、验系统签名、甚至读 TPM 度量值;全部过关就返回成功,把高级错误报告或深层电源状态的控制权授予系统,否则回一个拒绝码,系统退守保守模式。这已经不是读表,而是固件与系统隔着 ACPI 命名空间打的远程过程调用。更妙的是处理器能力声明与性能偏好的双人舞:前者让系统声明支持的调频协议,后者让固件动态告知眼下能给的性能等级——调度器据此实时适配硬件能力,例如高负载时固件主动压低可用等级以免热节流。这种反馈闭环,只有靠稳定的命名空间加可执行 AML 才搭得起来。

安全边界:ACPI 表作为可信环境的延伸。 在现代可信计算架构里,ACPI 表正变成 TPM 与可信执行技术的关键锚点:TPM2 表直接写明 TPM 设备的地址与中断;可信域虚拟固件通过自定义 SSDT 往命名空间里注入条目,向系统公开安全虚拟机的内存加密粒度。UEFI 在其中当公证人:保证表的厂商标识与固件签名证书相符,表内容哈希后存入 TPM 度量寄存器;系统装载 TPM 驱动前先核对度量值——ACPI 表本身成了硬件度量根向系统验证根递送度量值的可信信道。

四、三重张力:静态表、缺沙箱、范式竞争

ACPI 集成虽高度成熟,在云原生、AI 加速器与机密计算面前仍绷着三根弦。

静态表对动态硬件。 DSDT 在固件编译时固化,反映不了热插拔 GPU、动态重配 FPGA 或内存池的实时拓扑。出路已在眼前:新版规范的表协议允许运行时动态注入 SSDT;新版内核支持在启动早期参数阶段替换特定表。ACPI 正从"启动时一次性交付"走向"全生命周期可编程"。

AML 解释器没有沙箱。 传统解释器以最高权限跑在内核态,设备特定方法一旦有逻辑漏洞就是提权通道。学术界的探索方向包括把 AML 字节码编成轻量沙箱模块、放进用户态隔离环境执行、只经预定义接口摸内核能力——这或将重写 ACPI 的执行模型。

与设备树的范式竞争。 ARM64 平台普遍用设备树描述硬件,扁平结构更容易被现代引导器动态生成。但 ACPI 联盟已发布面向 ARM64 的规范,定义通用定时器表、内存分区监控等新表,推动 ACPI 成为横跨 x86 与 ARM 的统一硬件描述语。主流系统都已支持 ACPI 启动,"一套表、多架构"的终局正在成形。

💡 关键直觉:判断一块新硬件走 ACPI 还是设备树,先看它的消费者是谁。跑通用操作系统(Windows、企业级 Linux)的服务器与 PC,走 ACPI——系统要标准化的电源与热管理谈判;固定搭配瘦内核的嵌入式设备,设备树更轻。两者无关对错,只是治理成本的取舍:ACPI 的协商能力,标价就是规范复杂度。

本节速览

  • 范式主张:硬件能力靠数据声明而非指令执行,系统解析意图而非猜测行为——终结"一块硬件一个系统补丁"。
  • 六大核心表:RSDP 锚点、XSDT 目录、FADT 硬连线事实、DSDT/SSDT 动态声明、MADT 中断拓扑、SRAT/SLIT 亲和性。
  • 三支柱:可发现(签名加校验和的锚)、可验证(校验和加厂商标识双保险)、可组合(AML 命名空间活体模型)。
  • 权力转移:系统从被动读表,到隔着命名空间与固件谈条件,再到凭度量值的可信信道。
  • 三重张力:静态对动态、解释器无沙箱、与设备树竞争,分别由动态注入、沙箱化、跨架构统一作答。
  • 硬件精简标志位:FADT 里那颗常被无视的比特,宣告扔掉遗留寄存器、只走方法交互——硬件与软件之间再无暗语,只剩白纸黑字的契约。

第三章到此读完了存储、驱动、声明三份契约。下一章进入全书重心:这些契约如何被串成一条从硬件根一路伸到内核的信任链。

四、把 ACPI 表倒出来逐张点名

ACPI 与 UEFI 的接缝在 EFI_CONFIGURATION_TABLE——固件把 RSDP 的物理地址放进系统表,OS 拿着 RSDP 顺藤摸瓜。整条链可以在 Linux 上完整复现:

$ sudo acpidump | head -14 # RSDP found at 0x7A76F014, length 36 (v2) RSD PTR: OEMID="AMI " OEM-TABLE-2.0=" " revision=02.64 # acpi 00000000.0000.0000 [000000007a76f014] RSDT (v02 AMI ALASKA 01072009 AMI 00010013) RSDT: OEMID="ALASKA" OEM-TABLE-ID="01072009 AMI" revision=01 # acpi 00000000.0000.0000 [000000007a76e088] DSDT (v02 ALASKA A M I 01072009 INTL 20220930) DSDT: OEMID="A M I" OEM-TABLE-ID="01072009 AMI" revision=02 # acpi 00000000.0000.0000 [000000007a7711f0] FACP (v06 AMI ALASKA 01072009 AMI 0000000B) FACP: OEMID="ALASKA" ... PM1a_EVT_BLK=0x1800 PM1a_CNT_BLK=0x1804 # acpi 00000000.0000.0000 [000000007a7870d8] APIC (v06 AMI ALASKA 01072009 AMI 0000000B) MADT: LAPIC NMI addressed to all CPUs, IOAPIC id=8 base=0xFEC00000

RSDT 里的每张表都是固件生成的:DSDT 装着主板级 AML 代码(USB 端口开关、风扇策略),FACP 给出电源管理寄存器块地址,MADT 描述本地 APIC。固件不做电源管理——它只是把这些事实打包递给 OS,这正是"表驱动"的含义。

DSDT 还能反编译成 AML 伪码读,改风扇策略、解锁隐藏选项的黑手段都从这步开始:

$ sudo acpidump -b -d # 导出并反编译 DSDT DSDT copying to file dsdt.dat ... 139118 bytes ACPICA execution: iasl -d dsdt.dat Intel ACPI Component Architecture Disassembler version 20230628 Default address space for region operands: SystemMemory dsdt.dsl 4186: Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings dsdt.dsl 4187: { dsdt.dsl 4188: Name (RBUF, ResourceTemplate () dsdt.dsl 4190: { dsdt.dsl 4191: Memory32Fixed (ReadWrite, dsdt.dsl 4192: 0xFEDC0000, // Address Basis dsdt.dsl 4193: 0x00010000, // Address Length

0xFEDC0000 是这板子 GPIO 控制器的基地址——设备资源不再由跳线或 BIOS 选项决定,而是写在 AML 的 ResourceTemplate 里由 OS 解释执行。第 3 章开头那句"ACPI 是固件交给 OS 的合同",到这一步就完全落地了。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U