因为Linuxboot项目会或多或少接触到acpi,因此我先把acpi的基础部分想基本过一遍,知道acpi是干啥的,里面的表具体是干啥的放了啥内容怎么进行读取就行。而对于能把acpi表单放在内存哪里以及怎么放的应该会是一件比较难的事情,先学着吧。
如果有一定的基础,学各种东西最快最有效的方法就是参考官方提供的文档,如acpi spec。对于初学者纯小白比如说我,去网上多看acpi的一些其他人的理解及讲解,看看其他人的再加上对应的acpi spec应该是比较好的学习方法。
以下是我的学习笔记:
首先,acpi(Advanced Configuration and Power Interface)是一个电源管理以及硬件设备记录,是在系统启动阶段由BIOS/UEFI收集系统各方面信息并创建的,
acpi的规范和结构大概是这样的:
尽管ACPI访问了软、硬件并且阐述了它们必须如何工作,但是ACPI既不是一个软件规
范,也不是一个硬件规范,而是一个由软、硬件元素组成的接口规范。
关于上述这幅图,acpi规范是这么定义的:
ACPI包含三个运行组件。
● ACPI系统描述表——描述硬件的接口。表的格式限制了在表中可以创建的内容
(例如,一些控制内嵌在固定寄存器块中,而此表指定了寄存器块所在的地址)。
然而,大多数系统描述表允许按照任何方式来创建硬件并且可以描述硬件工作时
所需的任意操作序列。包含定义块的ACPI表可以使用伪代码类型的语句。OS负
责对这些代码进行解释和执行。也就是说,OSPM包含和使用了一个解释器,它
执行采用伪代码语言编码并保存在ACPI表中的程序。被称为AML(ACPI Machine
Language)。
● ACPI寄存器——硬件接口中受限制的部分,通过ACPI系统描述表进行描述(至少
描述ACPI寄存器的位置)。
● ACPI系统固件——此代码启动机器(与遗留BIOS所实现的功能相同)以及实现睡
眠、唤醒和重启等操作所需的接口。与遗留BIOS相比,它很少被调用。ACPI系统
固件也提供了ACPI系统描述表。
那么我们现在知道了apci系统描述表很重要,那我们肯定会去想它有些什么表然后怎么去访问这些表以及表的目录结构是什么样的。
有哪些表
This section specifies the structure of the system description tables:
• Generic Address Structure (GAS)
• Root System Description Pointer (RSDP)
• System Description Table Header
• Root System Description Table (RSDT)
• Extended System Description Table (XSDT)
• Fixed ACPI Description Table (FADT)
• Firmware ACPI Control Structure (FACS)
• Differentiated System Description Table (DSDT)
• Secondary System Description Table (SSDT)
• Multiple APIC Description Table (MADT)
• GIC CPU Interface (GICC) Structure
• Smart Battery Table (SBST)
• Extended System Description Table (XSDT)
• Embedded Controller Boot Resources Table (ECDT)
• System Locality Information Table (SLIT)
• System Resource Affinity Table (SRAT)
• Corrected Platform Error Polling Table (CPEP)
• Maximum System Characteristics Table (MSCT)
• ACPI RAS Feature Table (RASF)
• Memory Power State Table (MPST)
• Platform Memory Topology Table (PMTT)
• Boot Graphics Resource Table (BGRT)
• Firmware Performance Data Table (FPDT)
• Generic Timer Description Table (GTDT)
• NVDIMM Firmware Interface Table (NFIT)
• Heterogeneous Memory Attribute Table (HMAT)
• Platform Debug Trigger Table (PDTT)
• Processor Properties Topology Table (PPTT)
在最新的acpi规范中,一共可以看到这么多表,我这里学习了一下常见的表:RSDP、RSDT、XSDT、FACS、FADT(FACP)、DSDT、SSDT
首先是RSDT和XSDT,
RSDT表全称Root System Description Table,它存放了许多的指针,指向其它的描述系统信息的表。RSDT的结构如下:
typedef struct {
EFI_ACPI_DESCRIPTION_HEADER Header;
UINT32 Entry;
} RSDT_TABLE;
它实际上是一个可变数组,后面可以接很多的表项。而该结构的前面部分又被定义为EFI_ACPI_DESCRIPTION_HEADER:
typedef struct {
UINT32 Signature;
UINT32 Length;
UINT8 Revision;
UINT8 Checksum;
UINT8 OemId[6];
UINT64 OemTableId;
UINT32 OemRevision;
UINT32 CreatorId;
UINT32 CreatorRevision;
} EFI_ACPI_DESCRIPTION_HEADER;
XSDT表全称Extended Root System Description Table,它的作用于RSDT一样,区别在于两者包含的指针地址一个是32位的,一个是64位的。XSDT中包含的描述表头部物理地址可以大于32
位,XSDT表结构如下:
typedef struct {
EFI_ACPI_DESCRIPTION_HEADER Header;
UINT64 Entry;
} XSDT_TABLE;
XSDT(RSDT)指向的第一张表都是FADT,Fixed ACPI Description Table。这个表里面包含了OS需要知道的所有ACPI硬件相关寄存器(ACPI Hardware Register Blocks也就是GPx_BLK等),还包含DSDT,Differentiated System Description Table,该表包含大量的硬件信息。SSDT是DSDT的附加部分。SSDT是DSDT的附加部分,二级表可以不断增加。
而FACS在可读、可写内存中的一个数据结构。BIOS使用此结构来实现固件和OS之间的握手。
FACS通过FADT传递给ACPI兼容OS;
最后是RSDP,Root System Description Pointer。它是一个结构体,其结构如下:
typedef struct {
UINT64 Signature;
UINT8 Checksum;
UINT8 OemId[6];
UINT8 Revision;
UINT32 RsdtAddress;
UINT32 Length;
UINT64 XsdtAddress;
UINT8 ExtendedChecksum;
UINT8 Reserved[3];
} EFI_ACPI_6_1_ROOT_SYSTEM_DESCRIPTION_POINTER;
其中提供了两个主要的物理地址,一个是RSDT表的,另一个是XSDT表的。os系统怎么找到acpi表呢,就是取决于rsdp这个指针,而刚好这个指针可以通过efi system table进行调用。
最后,一个较为完整的Os访问acpi的图如下:
在虚拟机里面进一步得到了确认。