查看: 18016|回复: 36

[原创内容] 自己动手写DSDT系列教程1-ASL(ACPI Source Language)基础篇

[复制链接]
suhetao 发表于 2011-11-21 11:16 | 显示全部楼层 |阅读模式
快御云安全
    写在前面的话,鄙人不是一个主板BIOS开发工作者,以下对ASL的理解仅仅来源于http://www.acpi.info/上的ACPI Specification文档。因此难免会出现不少错误的理解,以及错误的观点,希望大家谅解以及纠正。
    首先,不得不说一下DSDT(Differentiated System Description Table)。什么是DSDT呢?其实它属于ACPI其中的一个表格,而ACPI是Advanced Configuration & Power Interface的缩写,高级配置和电源接口,从文字上就可以理解ACPI是一系列的接口,这个接口包含了很多表格,所以DSDT即是其中的一张表格同时也是一些接口。所以不难想象ACPI主要的功能就是提供操作系统一些服务以及提供一些讯息给操作系统使用。DSDT自然也不例外。ACPI的一个特色就是专有一门语言来编写ACPI的那些表格。它就是ASL(ACPI Source Language)也就是这盘文章的主角,ASL经过编译器编译后,就变成了AML(ACPI Machine Language),然后由操作系统来执行。既然ASL是一门语言,那就有它的准则。

ASL准则:
1、变量命名不超过4个字符,且不能以数字开头。联想一下看到过的DSDT代码看看,绝对不会超过。
2、Scope形成作用域,概念类似于数学中的集合{}。有且仅有一个根作用域,所以DSDT都以
  1. DefinitionBlock ("xxxx", "DSDT", 0x02, "xxxx", "xxxx", xxxx)
  2. {
复制代码

开始,同时以
  1. }
复制代码
结束。这个就是根作用域。xxxx参数依次表示输出文件名、OEMID、表ID、OEM版本。第三个参数根据第二个参数指定,如上面所示。如果是"DSDT"就一定是0x02,其他参数都可以自由修改。
3、以“_”字符开头的函数和变量都是系统保留的,这就是为什么反编译某些AML以后得到的ASL出现_T_X,重新编译的时候会出现警告。
4、Method定义函数,函数可以定义在Device下或者Scope下,但是不能脱离Scope定义单独的函数,所以不会有这种情况出现。
  1. Method (xxxx, 0, NotSerialized)
  2. {
  3. ......
  4. }
  5. DefinitionBlock ("xxxx", "DSDT", 0x02, "xxxx", "xxxx", xxxx)
  6. {
  7. ......
  8. }
复制代码
5、根作用域下有\_GPE,\_PR,\_SB,\_SI,\_TZ五个作用域。\_GPE就是ACPI的事件处理,\_PR处理器,\_SB所有的设备和总线。\_SI系统指示灯。_TZ热区,用于读取某些温度。不同属性的东西放在对应的作用域下。例如:
设备Device (PCI0)放在Scope (\_SB)里面
  1. Scope (\_SB)
  2. {
  3.     Device (PCI0)
  4.     {
  5.         ....
  6.     }
  7.     ....
  8. }
复制代码
CPU相关的信息放在Scope (_PR)
  1. Scope (_PR)
  2. {
  3.     Processor (CPU0, 0x00, 0x00000410, 0x06)
  4.     {
  5.         ....
  6.     }
  7.     ....
  8. }
复制代码
Scope (_GPE)放着相关的事件处理
  1. Scope (_GPE)
  2. {
  3.     Method (_L0D, 0, NotSerialized)
  4.     {
  5.         ....
  6.     }
  7.     ....
  8. }
复制代码
乍一看不是函数吗?当然函数也可以放在这里。但是请注意函数名“_”开头,是系统保留的函数。
6、Device(xxxx)也可看做是一个作用域
7、符号“\”引用根作用域,“^”引用上级作用域
8、ASL中没有运算符,+-*/=是不会出现了,但是有等价的函数。
9、函数最多可以传递8个参数,在函数里用Arg0~Arg7表示,不可以自定义。
10、函数最多可以用8个局部变量,用Local0~Local7,不用定义,但是需要初始化才能使用,也就是一定要有一次赋值操作。

ASL常用的数据类型:
Integer(整数)、String(字符串)、Event(事件)、Buffer(数组)、Package(对象集合)
ASL定义变量:
例如:
Name(TEST,0)//定义一个整数
Name(MSTR,"ASL")//定义一个字符串
  1. Name (_PRW, Package (0x02)
  2.                 {
  3.                     0x0D,
  4.                     0x03
  5.                 })
复制代码
//定义一个Package
可以发现定义变量的时候不需要显式声明其类型
ASL赋值方法:
有且仅有一个,Store(a,b)如
Store(0,Local0)//Local0=0
Store(Local0,Local1)//Local0=Local1

ASL运算函数:
上面提到ASL没有运算符号,但是有运算函数
Add 整数相加
And 整数于
Decrement 整数自减1
Divide 整数除法
Increment 整数自增1
Mod 整数求余
Multiply 整数相乘
ShiftLeft 左移
ShiftRight 右移
Subtract 整数减法
Or 或
Not 取反
Nor 异或
等等,具体请查阅ACPI Specification
举例如下:
  1. Add(1, 2, Local0) //Local0 = 1 + 2
  2. And(0x11, 0x22, Local0) //Local0 = 0x11 & 0x22
  3. Divide(10, 9, Local1, Local0) //Local0 = 10 / 9, Local1 = 10 % 9
  4. Mod (10, 9, Local0) //Local0 = 10 % 9
  5. Multiply(1, 2, Local0) //Local0 = 1 * 2
  6. ShiftLeft(1, 20, Local0) // Local0 = 1 << 20
  7. ShiftRight(0x10000, 4, Local0) // Local0 = 0x10000 >> 4
  8. Subtract(2, 1, Local0) //Local0 = 2 - 1
  9. Or(0x01, 0x02, Local0) //Local0 = 0x01 | 0x02
  10. Not(0x00,Local0) //Local0 = ~(0x00)
  11. Nor(0x11, 0x22, Local0) //Local0 = ~(0x11) & ~(0x22)
复制代码

ASL逻辑运算:
LAnd 逻辑与
LEqual 逻辑相等
LGreater 逻辑大于
LGreaterEqual 逻辑大于等于
LLess 逻辑小于
LLessEqual 逻辑小于等于
LNot 逻辑反
LNotEqual 逻辑不等于
LOr 逻辑或
  1. Store (LAnd(1, 1), Local0) //Local0 = 1 & 1
  2. Store (LEqual(1, 1), Local0) //Local0 = (1 == 1)
  3. Store (LGreater(1, 2), Local0) //Local0 = (1 > 2)
  4. Store (LGreaterEqual(1, 2), Local0) //Local0 = (1 >= 2)
  5. Store (LLess(1, 2), Local0) //Local0 = (1 < 2)
  6. Store (LLessEqual(1, 2), Local0) //Local0 = (1 <= 2)
  7. Store (LNot(0), Local0) //Local0 = !0
  8. Store (LNotEqual(0, 1), Local0) //Local0 = (0 != 1)
  9. Store (LOR(0, 1), Local0) //Local0 = (0 | 1)
复制代码
不难发现逻辑运算只会有两种结果0或者1。

ASL函数的定义:
1、定义函数
  1. Method(TEST)
  2. {}
复制代码
2、定义有两个输入参数的函数,以及使用局部变量Local0~Local7
  1. Method(MADD,2)
  2. {
  3.     Store(Arg0, Local0)
  4.     Store(Arg1, Local1)
  5.     Add(Local0, Local1, Local0)
  6. }
复制代码
实现了两个参数的加法运算,因此传入的参数一定要隐式整形数。
3、定义带返回值的函数
  1. Method(MADD,2)
  2. {
  3.     Store(Arg0, Local0)
  4.     Store(Arg1, Local1)
  5.     Add(Local0, Local1, Local0)
  6.     Return (Local0)
  7. }
复制代码
例子为自定义加法的实现。函数实现如同系统函数Add一样的相加
Store(MADD(1,2), Local0) //Local0 = 1 + 2
4、定义可序列化的函数
  1. Method(MADD, 2, Serialized)
  2. {
  3. Store(Arg0, Local0)
  4. Store(Arg1, Local1)
  5. Add(Local0, Local1, Local0)
  6. Return (Local0)
  7. }
复制代码
这个有点类似于多线程同步的概念,也就是说,当函数声明为Serialized,内存中仅能存在一个实例。一般应用在函数中创建一个对象。应用举例说明:
  1. Method(TEST, Serialized)
  2. {
  3.     Name(MSTR,"I will sucess"
  4. }
复制代码
如果这样子声明TEST这个函数,那么在两个地方同时调用这个函数
  1. Device (Dev1)
  2. {
  3.      TEST()
  4. }
  5. Device (Dev2)
  6. {
  7.      TEST()
  8. }
复制代码

如果先执行Dev1的TEST,Dev2中的TEST将等待Dev1中的TEST函数执行完毕再执行。如果声明为
  1. Method(TEST, NotSerialized)
  2. {
  3. Name(MSTR,"I will sucess"
  4. }
复制代码
那么将在其中一个Devx调用TEST的时候,另外一个调用失败,当它试图创建相同的字符串MSTR的时候。

ASL流程控制:
和常见的高级语言一样,ASL也有与之对应的控制流程语句。
Break
BreakPoint
Case
Continue
Default
Else
ElseIf
If
Return
Stall
Switch
While
(一)分支控制If, ElseIf, Else, Switch, Case
1、If用法介绍
例如下面的语句判断一下当前系统的接口是不是Darwin,如果是把OSYS = 0x2710
  1. If (_OSI ("Darwin"))
  2. {
  3.     Store (0x2710, OSYS)
  4. }
复制代码
2、ElseIf、Else用法介绍,如果系统结构不是Darwin,另外如果系统不是Linux,那么OSYS = 0x07D0
  1. If (_OSI ("Darwin"))
  2. {
  3.     Store (0x2710, OSYS)
  4. }
  5. ElseIf (_OSI ("Linux"))
  6. {
  7.     Store (0x03E8, OSYS)
  8. }
  9. Else
  10. {
  11.     Store(0x07D0, OSYS)
  12. }
复制代码
3、Switch, Case, Defaule, BreakPoint示例
  1. Switch(Arg2)
  2. {
  3.     Case(1)
  4.     {
  5. If(LEqual(1, Arg1)
  6. {
  7.     Return (1)
  8. }
  9. BreakPoint
  10.     }
  11.     Case(2)
  12.     {
  13.         ....
  14.         Return (2)
  15.     }
  16.     Default
  17.     {
  18.         BreakPoint
  19.     }
  20. }
复制代码
Switch可以看做是一系列If....Else的集合。BreakPoint相当于断点,意味着退出当前Swtich
(二)循环控制While,Break,Continue以及暂停Stall示例
  1. Store(10, Local0)
  2. While (LAnd (0x00, Local0))
  3. {
  4.     Decrement (Local0)
  5.     Stall (32)
  6. }
复制代码
Local0等于10,如果Local0逻辑于0不为真,Local0自减1,暂停32us,所以这段代码延时10 * 32 = 320 us。

累了,今天就写到这里,有了这些基础,鄙人觉得现在大部分论坛坛友对着DSDT的时候就不会是发呆又发呆,至少可以明白些少语句了。

评分

17

查看全部评分

头像被屏蔽
lihaotv2004 发表于 2011-11-21 14:19 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

rouen 发表于 2011-11-21 15:36 | 显示全部楼层
mark,回去要研究下
回复

使用道具 举报

roomepc 发表于 2011-11-21 15:37 | 显示全部楼层
看着就是像看天书啊
回复

使用道具 举报

lc761226 发表于 2011-11-21 16:16 | 显示全部楼层
深入研究
回复

使用道具 举报

zhuzhihua422619 发表于 2011-11-21 16:31 | 显示全部楼层
恩 谢谢 有时间慢慢研究下  
回复

使用道具 举报

tannyliu 发表于 2011-11-21 16:32 | 显示全部楼层
mark mark。。
回复

使用道具 举报

harrysh 发表于 2011-11-21 16:33 | 显示全部楼层
比较难懂,只能膜拜。。。
回复

使用道具 举报

zhangwj1978 发表于 2011-11-21 16:35 | 显示全部楼层
太高深了~~对不懂编程的人而言 真的很难理解。。只是最多知道一个顺序。。起码在编辑DSDT的时候 不会乱找。
回复

使用道具 举报

robert1111446 发表于 2011-11-21 22:17 | 显示全部楼层
这个要顶,感谢楼主分享知识
回复

使用道具 举报

绝对斯文败类 发表于 2011-11-21 23:31 | 显示全部楼层
谢谢楼主为大家分享知识 希望楼主再接再厉 谢谢
回复

使用道具 举报

scdyjy 发表于 2011-11-21 23:48 | 显示全部楼层
好在学过C语言,语法还看得懂
回复

使用道具 举报

qiqiwsq 发表于 2011-11-21 23:53 | 显示全部楼层
这个要顶,感谢楼主分享知识
回复

使用道具 举报

pwxubo 发表于 2011-11-22 00:01 | 显示全部楼层
感谢楼主分享
回复

使用道具 举报

ttydy 发表于 2011-11-22 00:18 | 显示全部楼层
又出了一个高人呀!学习中!!!
回复

使用道具 举报

abigfrog 发表于 2011-11-22 00:23 | 显示全部楼层
谢谢,语法蛮简洁,不过如果采用C Style就更好了
回复

使用道具 举报

flyangs 发表于 2011-11-22 00:39 来自手机 | 显示全部楼层
好东西 可惜原来就没有学编程
回复

使用道具 举报

zshwq5 发表于 2011-11-22 01:42 | 显示全部楼层
技术帖一定要支持,先收藏慢慢学。
回复

使用道具 举报

szdjg 发表于 2011-11-22 06:15 | 显示全部楼层
好好学习一下,受益非浅啊
回复

使用道具 举报

jerryhz 发表于 2011-11-22 08:21 | 显示全部楼层
支持楼主!期待看到dsdt错误修改篇!呵呵。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋手机版联系我们

Copyright © 2005-2025 PCBeta. All rights reserved.

Powered by Discuz!  CDN加速及安全服务由「快御」提供

请勿发布违反中华人民共和国法律法规的言论,会员观点不代表远景论坛官方立场。

远景在线 ( 苏ICP备17027154号 )|远景论坛 |Win11论坛 |Win10论坛 |Win8论坛 |Win7论坛 |WP论坛 |Office论坛

GMT+8, 2025-2-9 07:17

快速回复 返回顶部 返回列表