【UEFI系列】ACPI
文章目录
- 一、APM ACPI
- 二、S state介绍
- 三、ACPI table,ASL,ACPI method
- 1.ACPI table
- 2.ASL
- 四、添加ACPI表
一、APM ACPI
ACPI: Advanced Configuration and Power Management Interface,高级配置和电源管理接口。以前的电源管理规范是APM,现在ACPI已经把它替代了。
ACPI是OSPM(operating system-directed configuration and power management)的重要组成部分。
ACPI system定义了ACPI硬件、ACPI bios、ACPI OS,都follow ACPI的规范。
ACPI规范中,硬件由OS管理控制,bios是一个reporter。
ACPI是一套协议标准,这是OSPM/ACPI global system,图中列出了与OSPM/ACPI相关的软硬件以及之间的关系,描述了各部分的接口。
利用ACPI定义的接口,OS实现功能:
(例如ACPI汇报一个设备,这个设备在OS下由OS driver实现功能)
- system,device和CPU的电源管理
- device和CPU performance management
- 设备的配置/插拔和设置
其他规范:
- system event
- battery management电池管理
- 定义了硬件规范,smbus controller(低速的一种总线,通过它了解设备的信息例如内存信息)
- OSPM如何实现?
OS使用ACPI table中的定义,用ASL(ACPI source language,一种编程语言)控制硬件。
硬件状态变化时,有system event产生,硬件会发SCI(system control interrupt,并非SMI的一个中断)来通知OS,OS执行ASL中定义的method,object等来控制硬件。
二、S state介绍
- 常见的基础知识,S state:Sleep状态。
S0:正常工作的电源状态。
S1:通过 CPU 时钟控制器将 CPU 关闭,但CPU内容不保持、其他的硬件设备仍然正常工作。从s1唤醒到s0,CPU不需要重新从reset vector处执行,唤醒时间最短。PC端可通过键鼠操作快速唤醒。
S2:系统一般很少支持(跟s1状态差不多)。
S3:挂起到内存。运行中的数据写入内存后关闭硬盘,此时除了内存需要电源来保持资料以外,其他的设备、装置全部停止供电。
S4:挂起到硬盘。把内存中的资料完整地保存在硬盘中,然后所有部件停止工作,系统主电源关闭,但是硬盘仍然带电并可以被唤醒。
其实系统设置里这个开启的话,就会是进s4,开机就比较快。关掉的话就是从s5完全关机状态来开机。
S5:完全关机。
windows系统的左下角电源操作显示:分别是S3(睡眠)、S4(休眠,win11现在好像没了)、S5。
- 如何从睡眠的Sx到S0状态
开机键;
RTC(real-time clock),有些是设置时间自动唤醒;
Modem,电话的串口唤醒,南桥会先处理信号;
Lan,网络唤醒,例如网吧里唤醒机器;
鼠标/键盘;
Gpio;
三、ACPI table,ASL,ACPI method
1.ACPI table
- ACPI table的作用
对硬件接口、系统信息、特定功能和method的描述。
OS boot的时候,OSPM找到ACPI table并使用其中的信息。
- ACPI table列举
RSDP:Root System Description Pointer;
根据ACPI GUID在System table中,找到表的entry起始地址。
RSDP表包含了RSDT和XSDT表的起始地址,这2个表可以去确定其他表的位置。
这里看到RSDTAddress是4字节,所以寻址空间在4G以内。
而XSDTAddress是8字节,寻址空间高于4G(本来X也是extended的缩写,表示额外的意思)。
大体结构是这样:
下面这张是RSDT指出来的
可以看到FACS和DSDT比较特殊,不在RSDT和XSDT里放地址,这两个是OS自己产生出来的。
这些header结构都是一样的,内容各自写各自的。
RSDT:Root System Description Table;
RSDT Header是这样的结构:前4字节拿来写标识signature
XSDT:Extended System Description Table;
FADT:Fixed ACPI Description Table;
FACS:Firmware ACPI Control Structure;
FACS是Firmware和OS之间沟通的桥梁,主要包含3个内容:
a. HardWare signature:系统从S4 唤醒时,OS会去读取Hardware signature来验证系统硬件是否发生了改变,若被改动过,则不能LOAD之前的Image信息,而是应该重新执行一次COLD REBOOT。
b. Firmware Waking Vector中主要保存了唤醒系统之后要处理的程序entry。
c. Global Lock:主要用于OS和firmware在访问硬件时同步。
DSDT:Differentiated System Description Table;
DSDT包含了AML的CODE和DATA。它定义了OS在启动过程中如何与硬件交互。DSDT 通常包含系统硬件资源的详细描述、设备节点、方法、事件以及电源管理相关的信息。编译完成后的 DSDT 被加载到系统内存中,并由OS的 ACPI 驱动进行解析。
SSDT:Secondary System Description Table;
- 如何在内存中找到ACPI table
1.先找到RSDP:在E000-F000内存中搜索“RSD PTR ”的signature。
通过RSDP,即可获取到RSDT或者XSDT,进而可以获取所有的ACPI Table。
2.其它locate方式:EFI环境下,根据ACPI的guid在system table中找到ACPI table(其实就是先找RSDP的guid)的entry。
(EFI GUID for ACPI 2.0 or later RSDP structure: 8868e871-e4f1-11d3-bc22-0080c73c8881)
Windows下可以用RW工具查看Acpi Table。
- 用工具dump acpi table
DOS: ACPItbl,pl.exe
Windows:RW
2.ASL
ASL(ACPI Source Language)编译之后得到AML(ACPI machine Language),置于ACPI table中。
ASL用来定义ACPI objects,包括ACPI control methods等,可以控制hardware,读写寄存器等。
Method,类似C语言中的函数,可以被其他Method或者OS调用。详见acpi规范。
简单举列:
声明变量 : Name(Data, 0)
声明函数 : Method (_PIC, 1, NotSerialized)
声明Device: Device(COM3)
描述一段内存:Memory32Fixed(ReadWrite, 0xFED81500, 0x300)
描述一组IO:IO (Decode16, 0x3E8, 0x3E8, 0x01, 0x08)
Device声明通常存在与DSDT和SSDT中。
Device定义中正常包含_HID, _UID等描述设备信息。
_STA用于描述设备状态(status),决定该设备是否可以识别。
_CRS描述当前设备所需资源(current required resource)。
Method:
Method类似C语言的中函数。
若为局部Method,可直接调用;
若为外部Method,需要指定Method对应的路径;
若Method不在同一个Table中,需要使用External的方式进行申明。
_PTS:(比如指令Method (PTS, 1, Serialized)。)OS在做S1、S2、S3、S4 sleep操作的时候会调用_PTS method,将sleep level传入这个method。简单来说就是休眠操作回去调_PTS的相关函数。
ASL什么时候汇报给OS的:BDS,其实shell(相当于处于bds阶段,还在boot过程中)下也可以导出acpi表。这也就是为什么很多时候shell下没问题,但是OS有问题,就是asl语言控制设备的时候出了问题。
四、添加ACPI表
这是EFI_ACPI_TABLE_PROTOCOL的结构,提供了两种方法InstallAcpiTable和UninstallAcpiTable:
struct _EFI_ACPI_TABLE_PROTOCOL {EFI_ACPI_TABLE_INSTALL_ACPI_TABLE InstallAcpiTable;EFI_ACPI_TABLE_UNINSTALL_ACPI_TABLE UninstallAcpiTable;
};
table的结构:
typedef struct {UINT32 Signature;UINT32 Length;UINT8 Revision;UINT8 Checksum;UINT8 OemId[6];UINT64 OemTableId; //一般是放表名的,例如"RamDisk "UINT32 OemRevision;UINT32 CreatorId;UINT32 CreatorRevision;
} EFI_ACPI_DESCRIPTION_HEADER;
具体实例(edkii代码里的)
extern EFI_GUID gEfiAcpiTableProtocolGuid;
UINTN mRamDiskSsdtTableKey;EFI_STATUS Status;EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol = NULL;EFI_ACPI_DESCRIPTION_HEADER *Table;UINTN TableSize;//数据获取Status = GetSectionFromFv (&gEfiCallerIdGuid,EFI_SECTION_RAW,SectionInstance,(VOID **)&Table,&TableSize);//先装protocolStatus = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid,NULL,(VOID **)&mAcpiTableProtocol);//再用protocol里的方法安装tableStatus = mAcpiTableProtocol->InstallAcpiTable (mAcpiTableProtocol,Table,TableSize,&mRamDiskSsdtTableKey);
edkii代码里的table例子:
// ACPI Boot Graphics Resource Table template
EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE mBootGraphicsResourceTableTemplate = {{EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE,sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE),EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_REVISION, // Revision0x00, // Checksum will be updated at runtime//// It is expected that these values will be updated at EntryPoint.//{ 0x00 }, // OEM ID is a 6 bytes long field0x00, // OEM Table ID(8 bytes long)0x00, // OEM Revision0x00, // Creator ID0x00, // Creator Revision},EFI_ACPI_5_0_BGRT_VERSION, // VersionEFI_ACPI_5_0_BGRT_STATUS_VALID, // StatusEFI_ACPI_5_0_BGRT_IMAGE_TYPE_BMP, // Image Type0, // Image Address0, // Image Offset X0 // Image Offset Y
};
可以看到头部都一样,之后的部分是自己定义的结构。