from http://blog.csdn.net/huangkangying/article/details/7853343
什么是ACPI?
ACPI的全称是Advanced Configuration and PowerInterface。它是由早期的APM发展和改进起来的,其主要作用是为操作系统提供一套标准的电源管理接口。
ACPI关键概念:
经常听起别人谈到什么Gx State, Cx State, Sx State的, 听得我不知所云,后来看了ACPI的spec后,才有所了解, 先把图搞下来:
- Power Management State(电源管理状态)
为了方便电源管理,ACPI Specification 中定义了四种关键的电源管理状态:
- Global State (Gx State) 全局态,这个属于是top-level 的状态
- G0 --Working State 工作态(S0)
- G1 --Sleeping State 睡眠态(S1-S4)
- G2 --Soft-off State (S5)
- G3 --Mechanical -off State
- System Sleeping State(Sx) 系统睡眠态, S1-S4主要是由恢复到运行态的时间来区分的
- S0 --对应G0,运行态
- S1 --系统时钟停止,处理器停止
- S2 --系统 Cache清除,处理器停止
- S3 --Suspend to RAM
- S4 --Suspend to Disk
- S5 --Soft-off
- CPU Power State(Cx)
- C0 -- 工作态,全速运行
- C1 -- CPU停止工作
- C2 -- 低功耗,高延时
- C3 -- 更低功耗,更高延时
- Device State(Dx)
- D0 -- Full Power 全速
- D1 -- 中间态
- D2 -- 比D1能耗低,延时高
- D3 -- Off
- ASL & AML Language
ASL是一种解释性的语言,由它可以编译成支持ACPI的OS认识的AML语言。
- ACPI Control Method (ACPI控制方法)
类似于C语言中的函数,AML的函数叫做Method. 跟据ACPI的规范,BIOS提供了一些标准的Method给OS调用。例如_PTS, _WAK等等。
ACPI常用的寄存器,及寄存器位的含义
ACPI_ENABLE, | 当向SMI_CMD写入这个值的时候,系统将触发事件进入ACPI模式 |
GPE0_BLK, GPE1_BLK | General Purpose Event 0 and General Purpose Event 1 Block |
P_BLK | Processor Controlling features. 处理器功能相关 |
SCI_EN | 如果置1,将使用SCI中断, 如果清零,将使用SMI中断 |
SLP_EN | 用于切换Sleeping State,一般和SLP_TYPE一起使用 |
SLP_TYPE | 当SLP_EN置1的时候,系统将进入到SLP_TYPE所定义的状态 |
SMI_CMD | SMI Command Port |
WAK_STS | 当系统由睡眠态被唤醒时,此位被置位 |
X_GPE0_BLK, X_GPE1_BLK | Extended General Purpose E vent |
X_Firmware_Waking_Vector | 64 bits firmware waking vector |
SCI 和 SMI的区别?
SCI是针对ACPI的叫法,SMI是针对APM的叫法。
SCI is a system interrupt used by hardware to notify the OS of ACPI events.
SMI is OS-transparent interrupt generated by interrupt event on legacy systems
常用的ACPI Table名称及含义
ACPI BIOS主要使用ACPI Table来描述主板上的所有资源,OS以此来对系统进行电源管理。
ACPI的主要结构如下所示:
常见的ACPI Table如下:
FACS:Firmware ACPI Control Structure
FACS是BIOS用来完成firmware与OS之间交互的这样一种内存结构, 它主要包含了以下三个部分:
- Hardware Signature: 当系统从S4被唤醒的时候,OS会去读取Hardwaresignature 来验证系统 的硬件是否有被改动过,如果被改动,刚系统不能直接load以前保存的image信息,而是应该执行一次coldreboot。
- Firmware Waking Vector : 在Waking Vector中主要保存了唤配系统后应该执行的程序的物理地址。
- Global Lock:主要用于OS和firmware在访问硬件资源的时候同步。
FADT: Fixed ACPI Description Table: 包含了FACS和DSDT的物理地址
RSDT: Root System Description Table
MADT: Multiple ACPI Description Table
DSDT: Differentiated System Description Table
SSDT: Secondary System Description Table
PSDT: Persistent System Description Table
DSDT首先被OS加载,然后是SSDT。
在此总结一下BIOS初始化的流程和OS初始化的流程(Figure 16-71):
先说BIOS初始化的流程吧,BIOS由Boot Vector启动后,首先要判断一下Sleep Type,
Sleep Type == S2: 如是要是从S2状态被唤醒的,则只用初始化CPU, Enable内存和配置一下cache就可以直接时Waking Vector了;
Sleep Type != S2: 初始化CPU, 初始化内存控制器,使能内存,配置Cache,使能Cache,初始化Chipset
再判断Sleep Type是否等于S3:
Sleep Type == S3: 直接跳到Waking Vector
Sleep Type != S3: 判断Sleep Type 是否等于S4:
Sleep Type == S4BIOS: 重新装载memory image, 然后转入Waking Vector
Sleep Type != S4BIOS: 说明从S4 Boot, 需要重新post然后时OSBootloader
图figure 16-74中显示了OS初始化的流程:
这里可以看到,有两条路径可以进入到OS:
一条是通过OS boot loader, 这条路径是S4进入时走的
另一条是通过Waking Vector,这条路径是由S2, S3状态被唤醒时走的
1. ASL基本准则
a) 变量名必须由4个字符组成,第1个字符不能是数字
b) 变量名和函数名不区分大小写
c) Scope和Device都会形成自己的作用域,类似于C++中的namespace和class
d) 所有以”_”开头的函数都是Reserved的,给系统使用,不能给自己的函数起这样的名字
e) ASL中的路径有相对路径和绝对路径之分。其结构有点像文件目录。
f) 对于函数,最多只能传递8个参数(Arg0~Arg7),只能用这8个名字,不能自己起名字
g) 对于局部变量,最多能使用8个变量(Local0~Local7),和函数参数一样,不能自己起名字,而且在使用之前必须手动赋初值。
h) 声明变量时不需要显示声明其类型,这一点不同于C和C++。
2. 数据类型
ASL 常用的几种数据类型
a) Integer – 整数 b) String – 字符串 c) Event -- 事件
d) Buffer -- 数组 e) Package – 对象结合
问:如何获取一个变量的类型?
答:使用函数ObjectType(Obj)可以得到变量类型
返回值:
0: Uninitialized 1: Integer 2: String 3: Buffer
4: Package 7: Event
3. 定义变量
正如前面提到的,声明变量时不需要显式地声明其类型。
Name(MYIN,1) //定义了一个整数
Name(MSTR, “Hello,world”) //定义了一个字符串
4. 赋值
ASL中使用函数Store()来进行赋值操作
Store(0x1234, Local0)
Store(“Hello”, Local0)
5. 算术运算
ASL中不使用+-*/等符号进行运算,全部使用函数
常用的有:
Add: Add(0x1, 0x2, Local0) // Local0 = 0x1+ 0x2
And: And(0x1, 0x2, Local0) // Local0 = 0x1& 0x2
Divide: Divide(0x2, 0x1, Local0) // Local0 = 0x2/ 0x1
Mod: Mod(0x2, 0x1, Local0) //Local0 = 0x2% 0x1
Multiply: Multiply(0x2, 0x1, Local0) //Local0 = 0x1* 0x2
Nor: Nor(0x1, 0x2, Local0) //Local0 = (~0x1)& (~0x2)
Not: Not(0x1, Local0) // Local0 =~0x1
Or: Or(0x1, 0x2, Local0) // Local0 = 0x1 |0x2
ShiftLeft: ShiftLeft(0x1, 0x8, Local0) // Local0 = (0x1)<<0x8
ShiftRight: ShiftRight(0x8, 0x2, Local0) //Local0 = (0x8)>>0x2
Subtract: Subtract(0x2, 0x1, Local0) //Local0 = 0x2– 0x1
Xor: Xor(0x1, 0x2, Local0) //Local0 = 0x1 ^ 0x2
6. 逻辑运算
和算术运算一样,ASL中同样使用函数来进行逻辑运算
常用的有:
LAnd: LAnd(0x1, 0x2) //0x1 && 0x2
LEqual: LEqual(0x1, 0x2) // 0x1== 0x2
LGreater: LGreater(0x1, 0x2) //0x1 > 0x2
LGreaterEqual: LGreaterEqual(0x1,0x1) // 0x1 >= 0x2
LLess: LLess(0x1, 0x2) // 0x1 < 0x2
LLessEqual: LLessEqual(0x1,0x2) // 0x1 <= 0x2
LNot: LNot(0x1) //!(0x1)
LNotEqual: LNotEuqal(0x1,0x2) //0x1 != 0x2
LOr: LOr(0x1,0x2) // 0x1 || 0x2
7. 函数定义
Method(ADBG, 2) //表示有两个输入参数{
// Arg0, First parameter
// Arg1, Second parameter
Store(Arg0, Local0) //局部变量0
Store(Arg1, Local1) //局部变量1
Add(Local0, Local1, Local1)
Return(Local1) //返回Local1
}
调用函数
ADBG(3, 5)
8. 流程控制
在ASL中,常见的流程控制列表如下:Break, BreakPoint, Case, Continue, Default, Else, ElseIf, Fatal, If, NoOp, Return, Sleep, Stall, Switch, While
If的用法:
- If (predicate1)
- {
- …statements1…
- }
- ElseIf (predicate2)
- {
- …statements2…
- }
- Else
- {
- …statements3…
- }
For Example:
- If (predicate1)
- {
- …statements1…
- }
- ElseIf (predicate2)
- {
- …statements2…
- }
- Else
- {
- …statements3…
- }
- Switch (expression)
- {
- Case (value) {
- Statements executed if Lequal (expression, value)
- }
- Case (Package () {value, value, value}) {
- Statements executed if Lequal (expression, any value in package)
- }
- Default {
- Statements executed if expression does not equal
- any case constant-expression
- }
- }
- While (LGreater(Local0, 0))
- {
- Subtract(Local0, 1, Local0);
- }
我所知道的ACPI(4) -- ASL深入了解
前面的章节已经对ACPI Table和ASL语言的基本语法有过初步的介绍。这里在复习一下。ASL是ACPI Source Language的简称,它经过编译器编译过后变成AML,然后交给操作系统来执行。1. 根作用域下面的5个域(\_GPE, \_PR, \_SB, \_SI, \_TZ)
2. \_GPE
3. \_PR Processor相关
- Scope (_PR)
- {
- Processor (CPU0, 0x00, 0x00000410, 0x06)
- {
- ....
- }
- ....
- }
4. \_SB 所有的设备和总线
我所知道的ASL(5)
ASL常用的数据类型有:
Integer(整数), String(字符串), Event(事件), Buffer(数组), Package(对象集合)
定义一个Integer:
Name(TEST, 0)
定义一个String:
Name(TEST, "ABCD")
定义一个Buffer:
Buffer (BufferSize) {String or ByteList}
Buffer() {0xa, 0xb, 0xc, 0xd}
Buffer(2) {0xa, 0xb}
定义一个Package:
Package (NumElements) {PackageList}
Package中的成员可以是Integer, String, Buffer, 当然也可以是Package
例如:
Package () {
3,
9,
“ACPI 1.0 COMPLIANT”,
Package () {
“CheckSum=>”,
Package () {7, 9}
},
0
}
如果Package中NumElements缺省,那么有它被设置成Package中实际包含的元素个数。
如果NumElements大于Package中实际元素的个数,那么多出来的这些元素是未定义的。