关于DSDT在ACPI中的实现
ACPI定义了两种数据结构,它们在系统固件和操作系统之间共享:数据表和定义块。这两种数据结构是固件和操作系统之间的主要通信机制。其中DSDT由一个系统描述表头和定义块格式的数据组成。
表头信息如下:
struct acpi_table_header {
char signature[ACPI_NAME_SIZE]; /* ASCII table signature */
u32 length; /* Length of table in bytes, including this header */
u8 revision; /* ACPI Specification minor version number */
u8 checksum; /* To make sum of entire table == 0 */
char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */
u32 oem_revision; /* OEM revision number */
char asl_compiler_id[ACPI_NAME_SIZE]; /* ASCII ASL compiler vendor ID */
u32 asl_compiler_revision; /* ASL compiler version */
};
这些信息在ASL代码块编译过程中,由编译器根据asl代码中提供的信息填入到aml字节码的头部。以便os解析名称空间过程中使用。
定义块由ACPI源语言(ASL)代码编写实现,描述了设备对象和设备控制方法,ASL编译器将ASL翻译成ACPI机器语言(AML)字节码。AML是ACPI AML解释器处理的语言,加载定义块之后,这些数据将作为名称空间的名称对象。
ASL语法:
1、DSDT入口
DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,OEMID, TableID, OEMRevision){
TermList // A list of ASL terms
}
DefinitionBlock参数列表:
• AMLFileName — ASL编译为AML文件的输出文件名,可为NULL,为NULL时,则系统自动生成
• TableSignature — DSDT或SSDT
• ComplianceRevision — 为1时标识32位架构 为2时标识64位架构
• OEMID — original equipment manufacturer (OEM) ID
• TableID — 表ID
• OEMRevision — OEM的版本号
2、名称对象
Name (ObjectName, Object)
在ACPI Namespace中的名称对象,ObjectName对象名称,Object为value
3、ASL语言中的数据类型
• Integer — 32位或者64位的值
• String — 字符串
• Buffer — 字节数组
• Package — ASL对象的数组
• Object Reference — 对象的索引
• Method — 控制方法
4、数据buff和包:buffers and package
Name (BUF1, Buffer(3){0x00, 0x01, 0x02})
Name (BUF2, Buffer(){0x00, 0x01, 0x02, 0x03})每个逗号的数在0x00 and 0xff之间
Name (PKG3, Package(){
Package() {0x00, 0x01, 0x02},
Package() {0x03, 0x04, 0x05}
})//与C中的结构体类似
5、操作区域及字段域:Operation Regions and Fields
OperationRegion(OPR1, SystemMemory, 0x10000, 0x5)
OPR1: 名称
SystemMemory:类型 系统内存
0x10000: 基地址
0x5: 长度
Field (OPR1) //定义了OperationRegion这块5字节内存的分布情况
6、Scopes描述设备
Device (DEV1)
{
Name (INT1, 0x1234)
Name (STR1, "This string is inside of DEV1's scope")
Name (BUF1, Buffer() {0x00, 0x04, 0x6f})
Name (PKG1, Package() {OBJ0, OBJ1})
}
7、名称空间中预定义对象
_HID 标识设备的硬件id
_CRS(current resource setting)标识当前资源的设置
8、可执行的ASL(control method)
DefinitionBlock ("", "DSDT", 2, "", "", 0x1)
{
Name (INT1, 0x1234) // define INT1 to be 0x1234
Method (MTH1)
{
INT1 = 0x00 // store 0x00 to INT1
}
}
控制方法MTH1将会把INT1这个值置1,控制方法可以引用存在于其作用域之外的任何命名对象。
Method (MethodName, NumArgs, SerializeRule)
{
TermList // A list of ASL terms and expressions
}
• MethodName — 控制方法的名称
• NumArgs — 参数个数,包括arg0到arg6.
• SerializeRule — 说明该控件方法是否可以由多个线程输入
方法最多允许有7个参数和8个局部变量。参数被引用为Arg0到Arg6,局部变量被引用为local0到local7。ASL方法可以由其他ASL方法调用,也可以由OS通过AML解释器调用。
DefinitionBlock ("", "DSDT", 2, "", "", 0x0)
{
Name (STR1, "it is a wonderful day")
Method (GRT1)
{
printf ("Hello world, %o", STR1)
}
}//ASL的基本操作,输出字符串
由于ASL的底层特性,通常可以方便地操作缓冲区内的位,方法是将一个名称分配给一个位区域,并将该区域作为一个命名对象执行操作。这将避免程序员不断索引缓冲区元素。
CreateWordField将一个命名对象取双字域。这允许使用一种简单的方法来处理两个相邻的BUFF元素。同样重要的是,CreateWordField操作符可以将名称DWRD添加到ACPI名称空间中。
CreateWordField (SourceBuffer, ByteIndex, FieldName)
• SourceBuffer — 取双字域的buff
• ByteIndex — 从buff开始的位置偏移
• FieldName — 取出双字域的名称
取各种长度的域
• CreateBitField—Length: 1 bit
• CreateByteField—Length: 1 byte
• CreateWordField—Length: 2 bytes
• CreateDWordField—Length: 4 bytes
• CreateQWordField—Length: 8 bytes
• CreateField—Length: 任意长度
下面是asl通过buffer描述一个I/O资源:
DefinitionBlock ("", "DSDT", 2, "", "", 0x0)
{
Name (RES1, buffer(){
0x47, 0x01, 0x62, 0x00, 0x62, 0x00, 0x00, 0x01,
0x47, 0x01, 0x66, 0x00, 0x66, 0x00, 0x00, 0x01,
0x79, 0x00
})
}
当驱动程序希望通过ACPI了解设备的配置时,它会为一个已命名对象调用AML解释器,该对象可能被分配到一个类似于BUF1的缓冲区。在上面的例子中手工编程可能会导致错误,因为这种表示法缺乏语义意义。如果需要描述设备资源,则使用ResourceTemplate宏。通过使用ResourceTemplate宏,可以这样编码缓冲区:
DefinitionBlock ("", "DSDT", 2, "", "", 0x0)
{
Name (RES2,
ResourceTemplate(){
IO(Decode16, 0x62, 0x62, 0, 1)
IO(Decode16, 0x66, 0x66, 0, 1)
})
}
当编译后,RES2将会编译成和RES1一样的数据结构。
若要读取或写入RES2的元素,请创建取字域并写入位字段。在上面的例子中,第一个IO宏的第二个参数可以这样写:
DefinitionBlock ("", "DSDT", 2, "", "", 0x0)
{
Name (RES2,
ResourceTemplate(){
IO(Decode16, 0x62, 0x62, 0, 1, IOP1)
IO(Decode16, 0x66, 0x66, 0, 1, IOP2)
})
Method (WRRT, arg1)
{
CreateWordField (RES2, \IOP1._MIN, MINF)
MINF = 0x1234 // This will write 0x1234
// to the second field in IOP1.
}
}
有时,有必要在运行时更改现有资源模板中描述符的参数(在控制方法执行期间)。为了方便实现这一点,描述符宏可选地包含一个名称声明,稍后可以使用该名称声明引用描述符。当使用描述符声明名称时,ASL编译器将自动在给定名称下创建字段名,以引用描述符中的各个字段。
以上为ASL的一些简单语法,在一般asl文件中,包含大量宏定义来实现某些对象的描述,这里就不一一描述,详细可参考acpi规范了解。