您的位置:首页 > 其它

我所认识的ACPI

2015-07-15 13:56 489 查看
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:                   
cabd
 
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的用法:


[plain]
view plaincopy

If (predicate1)  
{  
    …statements1…  
}  
ElseIf (predicate2)  
{  
    …statements2…  
}  
Else  
{  
    …statements3…  
}  

For Example:

[plain]
view plaincopy

If (predicate1)  
{  
    …statements1…  
}  
ElseIf (predicate2)  
{  
    …statements2…  
}  
Else  
{  
    …statements3…  
}  

Switch语句:

[plain]
view plaincopy

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语句的用法:

[plain]
view plaincopy

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)

\_GPE, 主要负责ACPI的事件处理
\_PR, 处理器相关
\_SB, 所有的设备和总线
\_SI, 系统指示灯
\_TZ, Thermal相关,用于读取某些温度值

2. \_GPE

用RW在windows下面可以查看本机的ACPI Table。我们来看一下真实的\_GPE是什么样子的。



GPE下面的东西,别的不多讲,主要讲一下Lxx Method.
GPE域内的Lxx方法都是和GP0_STS寄存器中的bit对应起来的。举个例子,_L01对应的就是GP0_STATUS中的第一位。
注意,Lxx中的xx是16进制而不是十进制,所以如果你看到_L24,千万不要以为是bit24, 而应该是bit36。

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中实际元素的个数,那么多出来的这些元素是未定义的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: