最终找到了 FDAPM。是可以用ACPI关机的(我我想应该是这样的)
想把他的那些搞明白。
可惜我的汇编能力较弱。有很多地方看的迷迷糊糊。
有愿意搞这个的,我们一起研究他的代码。
源代码我这里有。
愿意的跟帖啊。
Gemini 解答
FDAPM(FreeDOS Advanced Power Management)是 FreeDOS 项目中用于电源管理的内核级工具,由 Eric Auer 开发。在 2010 年前后,随着 PC 硬件从传统的 APM(高级电源管理)全面转向 ACPI(高级配置与电源接口),DOS 环境下的关机问题变得复杂。
1. DOS 关机的技术背景
在 DOS 时代,实现软关机主要有两种途径:
- APM (Advanced Power Management): 这是通过 BIOS 中断实现的方案。程序调用
INT 15h, AX=5307h, CX=0003h。如果 BIOS 支持 APM 且已建立连接,关机动作由 BIOS 固件完成。- ACPI (Advanced Configuration and Power Interface): ACPI 不依赖 BIOS 中断,而是要求操作系统直接操作硬件寄存器。由于 DOS 是实模式操作系统,不具备 ACPI 解析器,因此直接通过 DOS 关机需要程序手动解析系统描述表。
2. FDAPM 实现 ACPI 关机的机制
FDAPM 的源代码(通常为汇编语言)实现 ACPI 关机遵循以下工程逻辑:
A. 寻找 RSDP (Root System Description Pointer)
程序首先在物理内存的特定区域(通常是
0E0000h到0FFFFFh之间,以 16 字节对齐)搜索字符串标志"RSD PTR "。这是接入 ACPI 系统的唯一入口。B. 解析表结构
- 从 RSDP 获得 RSDT(Root System Description Table)的物理地址。
- 在 RSDT 中遍历各个表的指针,寻找签名位 "FACP" 的表,即 FADT(Fixed ACPI Description Table)。
- 在 FADT 表中提取关键字段:
PM1a_CNT_BLK:PM1a 控制寄存器块的 I/O 端口地址。PM1b_CNT_BLK:PM1b 控制寄存器块的 I/O 端口地址(如果存在)。C. 获取 SLP_TYP 值
这是 ACPI 关机中最困难的部分。不同的芯片组(Intel, VIA, nVidia, AMD)对于“进入 S5 状态(关机)”所需的
SLP_TYP编码值定义不同。
- 标准做法需要解析 DSDT(Differentiated System Description Table)中的 AML 代码(ACPI 机器语言),这对小型 DOS 工具而言开销过大。
- FDAPM 的处理策略: FDAPM 会尝试从 FADT 中获取信息,或使用已知芯片组的特征值。它会将
SLP_EN位(第 13 位)置 1,并将SLP_TYP值写入PM1a_CNT_BLK对应的端口。3. 为什么 FDAPM 在某些机器上会失效
在 2010 年左右的硬件环境下,FDAPM 关机失败通常源于以下原因:
- 实模式访问限制: 某些新式 BIOS 提供的 ACPI 表位于 1MB 以上的扩展内存中。如果 DOS 环境下没有加载有效的内存管理器(如 HIMEM.SYS)或未开启 A20 地址线,FDAPM 可能无法定位到这些表。
- 硬编码局限性: 早期 FDAPM 版本可能未涵盖所有芯片组的
SLP_TYP定义。- SMI 干扰: 部分硬件要求在进入 S5 状态前通过 SMI(系统管理中断)进行特定握手,而简单的 I/O 端口操作可能无法触发该逻辑,导致挂起而非关机。
4. 关键代码逻辑参考(汇编层级)
在阅读 FDAPM 源码时,应重点关注处理
ACPI_OFF逻辑的函数。其核心操作通常如下:; 伪代码逻辑示例 mov dx, [PM1a_CNT_BLK] ; 加载 I/O 端口地址 mov ax, [SLP_TYP_VAL] ; 加载针对该芯片组的关机类型值 or ax, 2000h ; 设置第 13 位 (SLP_EN) out dx, ax ; 写入端口,触发硬关机若
PM1b_CNT_BLK不为 0,则需要向两个端口同时写入相同的值。5. 建议的技术路径
对于无法关机的特定环境,建议:
- 确保 FDAPM 版本是最新的(Eric Auer 曾多次更新以增加对新芯片组的支持)。
- 检查 BIOS 设置中是否开启了 "APM Support" 或 "Legacy USB Support",这有时会影响实模式下的电源管理行为。
- 若 FDAPM 的 ACPI 模式无效,可以尝试其多种参数方案(如
FDAPM PORE或FDAPM APMOFF),因为部分主板虽然宣称支持 ACPI,但其 BIOS 依然保留了对 APM 调用接口的兼容映射。
