最近的工作中用到了很多ASL的代码,之前一直一知半解的看,发现到用的时候不熟练还是很影响效率。
ASL代码的中文教程几乎没有,为了方便自己以后看,也方便别人检索,这里根据ACPI Source Language (ASL) Tutorial 以及 ACPI Source Language (ASL) Reference,把我平时记的笔记整理成人话。这一篇简单介绍下一些基本的表达式用法。
ASL与AML
ASL - ACPI Source Language AML - ACPI Machine Language
ASL 代码文件通过 iASL compiler 生成 AML字节码文件,每一个table即一个ASL文件,生成一个对应的AML文件包含在Firmware中。
Grammar 语法
ASL的表达式(Statement)声明对象(Object)
Object := ObjectType FixedList VariableList
其中
Operator
是ACPI中规定的操作符,如DefinitionBlock
,Name
,Method
,Scope
FixedList
是一组固定长度的变量,根据不同的Operator
,有不同的长度,也可能为空,写法:(a, b, c),有时尾部的变量可以省略(Default值生效)
VariableList
是一组不定长度的变量,写法:{x, y, z},对于某些Operator
,这里的变量(argument)可以是嵌套的对象。
整体就是有点C语言函数的样子。(虽然长得像但是有很显著的差异)
Operator (FixedVariableA, FixedVariableB, FixedVariableC) {
VariableX,
VariableY,
}
下面介绍一些常用的操作符与其对应的表达式
DefinationBlock - ASL的基础
每个DefinitionBlock
定义一个ACPI table,所有的ASL code都需要写到DefinitionBlock
内(作为VariableList
),一个标准的DefinitionBlock
如下:
DefinitionBlock (
AMLFileName,
TableSignature, // Signature of the AML file (could be DSDT or SSDT) (4-character string)
ComplianceRevision, // A value of 2 or greater enables 64-bit arithmetic; a value of 1 or less enables 32-bit arithmetic (8 bit unsigned integer)
OEMID, // (6-character string)
TableID, // (8-character string)
OEMRevision // (32-bit number)
)
{
//ASL Code
}
注意ComplianceRevision
小于2时,NameSpace
定义的Integer Object为32bit,反之则为64bit。
Name - ASL的“变量”
Name
可以用来定义Integer, String, Buffer, Package等等对象:
// ObjectName 必须小于等于4个字母,可以下划线开头
Name (ObjectName, Object)
Object Types:
• Integer - An unsigned 64-bit or 32-bit integer. Size取决于ComplianceRevision
• String - A null-terminated ASCII string. 字符串
• Buffer - An array of bytes. 类似数组
• Package - An array of ASL objects.
DefinitionBlock ("", DSDT, 2, "", "", 0x0)
{
Name (OBJ0, 0x1234) // Integer (DW or DD)
Name (OBJ1, "Hello world") // String
Name (BUF1, Buffer(3){0x00, 0x01, 0x02}) // Buffer (Byte)
Name (BUF2, Buffer(){0x00, 0x01, 0x02, 0x03}) // Buffer 长度自动初始化
Name (PKG1, Package(3){0x1234, "Hello world", INT1}) // Package
Name (PKG2, Package(){INT1, "Good bye"}) // Package 长度自动初始化
Name (PKG3,
Package(){
Package() {0x00, 0x01, 0x02},
Package() {0x03, 0x04, 0x05}
}) // Package in Package also Package
Name (PKG4, Package(){
"ASL is fun",
Package() {0xff, 0xfe, 0xfd, 0xfc, fb}})
Name (PKG5, Package(){
0x4321,
Buffer() {0x1}
})
}
OperationRegions and Fields - ASL的“内存指针”
OperationRegion (RegionName, RegionSpace, Offset, Length)
Field ( RegionName, AccessType, LockRule, UpdateRule ) {FieldUnitList}
(这个“操作区”,描述成“内存指针”也不是很贴切,总之OperationRegion类似一个指针,Field类似这个指针对应的结构体定义。)
这是ASL中用来访问系统内存或者IO Space的方法。
通常在C语言中有对应的结构体。
DefinitionBlock ("", "DSDT", 2, "", "", 0x1)
{
// (RegionName, RegionSpace, Offset, Length)
OperationRegion(OPR1, SystemMemory, 0x10000, 0x5)
Field (OPR1)
{
FLD1, 8
FLD2, 8
Offset (3), //Start the next field unit at byte offset 3
FLD3, 4
FLD4, 12
}
}
上面表达式生成的OperationRegion如下:
(本图片来自ACPI Source Language (ASL) Tutorial)
注:OperationRegion也是ObjectType的一种
Name Space 作用域
(不确定这么翻译准不准确。)
除了上文中提到Object Type以外,ASL语言还支持很多其他的Object Type,如:
• Device - Device or bus object. 硬件对象
• Object Reference - A reference to an object created by RefOf, Index, or CondRefOf operators. 类似指针
• Method - Control Method (Executable AML function). 类似函数
详细参见: All Data Types
Scope - ASL中的作用域
Scope和其他语言的scope一样,提供了一个作用域,在ASL中独特的是这个作用域需要与实际硬件的Location相关。
Scope (Location) {ObjectList}
Location - Predefined Root Namespaces:
\
: 根节点_SB
: System Bus_GPE
: General Purpose Event_PR
: Processor NameSpace_TZ
: Thermal Zone
注:在创建SSDT的时候通常需要使用Scope来更改namespace location,以便在DSDT定义的NameSpace中创建对象。
Device - ASL中描述硬件的作用域
Device (DeviceName) {TermList}
每个Device下是独立的作用域。
Device可以嵌套Device。一般来讲Device都定义在Scope里面。
下面这段代码定义了System Bus上的UART(COM0)与USB EHCI Host Controller(USB0),其中USB0中包含Root Hub(RHUB)。
// 这段代码来自edk2-platforms\Silicon\Qemu\SbsaQemu\AcpiTables\Dsdt.asl
DefinitionBlock ("DsdtTable.aml", "DSDT",
EFI_ACPI_6_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION,
"LINARO", "SBSAQEMU", FixedPcdGet32 (PcdAcpiDefaultOemRevision)) {
Scope (_SB) {
// UART PL011
Device (COM0) {
Name (_HID, "ARMH0011")
Name (_UID, Zero)
...
}
// USB EHCI Host Controller
Device (USB0) {
Name (_HID, "LNRO0D20")
Name (_CID, "PNP0D20")
...
// Root Hub
Device (RHUB) {
Name (_ADR, 0x00000000) // Address of Root Hub should be 0 as per ACPI 5.0 spec
...
} // USB0_RHUB
} // USB0
NamePath
在ASL中每一个Object都有一个NamePath,这个NamePath也标示出其作用域的范围。
举个例子:
注:NamePath中符号的意义
\
- 根节点
.
- 子节点
^
- 上一层节点
_
- Reserved by Specification
Method 执行函数
Method - ASL的“函数”
Method ( MethodName, NumArgs, SerializeRule, SyncLevel, ReturnType, ParameterTypes ) {TermList}
Method的参数比较多,下面详细介绍一下:
- MethodName:顾名思义
- NumArgs:入参的个数,Method最多可以传递 7 个参数,在Method里用 Arg0~Arg6 表示,不可以自定义。 (Default: 0)
- SerializeRule:当函数声明为 Serialized,内存中仅能存在一个实例(即不可重入)。(Default: NotSerialized)
- SyncLevel: Synchronization level (0 - 15). (Default: 0) (这一块没有深入的了解,目前看到的代码都是0)
- ReturnType: 定义返回值的Object Type. (Default: 不限制)
- ParameterTypes: 定义入参的Object Type,每个入参依次定义。(Default: 不限制)
此外:
- Method最多可以用 8 个局部变量,用 Local0~Local7,不可以自定义,使用前需要初始化。
- ASL methods can be called by other ASL methods or by the OS through the AML interpreter.
- 除了MethodName,其他均为可选参数。
示例:
// In this function
// MethodName -- _DSM
// NumArgs -- 4 (max 7, Arg0 ~ Arg6)
// SerializeRule -- Serialized
// SyncLevel -- 0
// ReturnType -- {BuffObj, PkgObj} // 2 kind possible return types
// ParameterTypes -- {BuffObj, IntObj, IntObj, PkgObj} // 4 input arg types in order
Method (_DSM, 4, Serialized, 0, {BuffObj, PkgObj}, {BuffObj, IntObj, IntObj, PkgObj}) {
...
}
运算符 (Operators)
Math operators | Logical operators | Assignment operators | |||
ASL 2.0 | Legacy ASL | ASL 2.0 | Legacy ASL | ASL 2.0 | Legacy ASL |
Z = X + Y | Add (X, Y, Z) | (X == Y) | LEqual (X, Y) | X = Y | Store (Y, X) |
Z = X / Y | Divide (X, Y, , Z) | (X != Y) | LNotEqual (X, Y) | X += Y | Add (X, Y, X) |
Z = X % Y | Mod (X, Y, Z) | (X < Y) | LLess (X, Y) | X /= Y | Divide (X, Y, , X) |
Z = X * Y | Multiply (X, Y, Z) | (X > Y) | LGreater (X, Y) | X %= Y | Mod (X, Y, X) |
Z = X - Y | Subtract (X, Y, Z) | (X <= Y) | LLessEqual (X, Y) | X *= Y | Multiply (X, Y, X) |
Z = X << Y | ShiftLeft (X, Y, Z) | (X >= Y) | LGreaterEqual (X, Y) | X -= Y | Subtract (X, Y, X) |
Z = X >> Y | ShiftRight (X, Y, Z) | (X && Y) | LAnd (X, Y) | X <<= Y | ShiftLeft (X, Y, X) |
Z = X & Y | And (X, Y, Z) | (X || Y) | LOr (X, Y) | X >>= Y | ShiftRight (X, Y, X) |
Z = X | Y | Or (X, Y, Z) | !X | LNot (X) | X &= Y | And (X, Y, X) |
Z = X ^ Y | Xor (X, Y, Z) | Miscellaneous | X |= Y | Or (X, Y, X) | |
Z = ~X | Not (X, Z) | ASL 2.0 | Legacy ASL | X ^= Y | Xor (X, Y, X) |
X++ | Increment (X) | Z = X[Y] | Index (X, Y, Z) | ||
X– | Decrement (X) |
流程控制 (Control Flow)
ASL的Control Flow与C语言基本一致。包括:
For, While, Break, Continue – 循环
这里举个例:
DefinitionBlock ("", "DSDT", 2, "", "", 0x0)
{
// Lagecy ASL
Method (PRT1, 1) {
Store(Arg0, Local0) //Local0 = Arg0
While (Local0) {
Mod (Local0, 2, Local1) //Local1 = Local0 % 2
If (Local1) {
Printf ("%o is odd", Local0)
} Else {
Printf ("%o is even", Local0)
}
Decrement (Local0) //Local0--;
}
}
// ASL2
Method (PRT2, 1)
{
Local0 = Arg0
For (Local0 = 0, Local0 < Arg0, Local0++)
{
Switch(Local0) {
Case(5) {
PRT1(Local0)
}
Case(10) {
Break
}
Default {
Continue
}
}
Printf ("Now is %o", Local0)
}
}
}
后面还没整理完,下篇文章接着写。