自己动手写DSDT系列教程1-ASL(ACPI Source Language)基础篇

2024-04-16 21:08

本文主要是介绍自己动手写DSDT系列教程1-ASL(ACPI Source Language)基础篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写在前面的话,鄙人不是一个主板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都以


DefinitionBlock ("xxxx", "DSDT", 0x02, "xxxx", "xxxx", xxxx)
{


开始,同时以


}


结束。这个就是根作用域。xxxx参数依次表示输出文件名、OEMID、表ID、OEM版本。第三个参数根据第二个参数指定,如上面所示。如果是"DSDT"就一定是0x02,其他参数都可以自由修改。
3、以“_”字符开头的函数和变量都是系统保留的,这就是为什么反编译某些AML以后得到的ASL出现_T_X,重新编译的时候会出现警告。
4、Method定义函数,函数可以定义在Device下或者Scope下,但是不能脱离Scope定义单独的函数,所以不会有这种情况出现。


Method (xxxx, 0, NotSerialized)
{
......
}
DefinitionBlock ("xxxx", "DSDT", 0x02, "xxxx", "xxxx", xxxx)
{
......
}


5、根作用域下有\_GPE,\_PR,\_SB,\_SI,\_TZ五个作用域。\_GPE就是ACPI的事件处理,\_PR处理器,\_SB所有的设备和总线。\_SI系统指示灯。_TZ热区,用于读取某些温度。不同属性的东西放在对应的作用域下。例如:
设备Device (PCI0)放在Scope (\_SB)里面


Scope (\_SB)
{
    Device (PCI0)
    {
        ....
    }
    ....
}


CPU相关的信息放在Scope (_PR)


Scope (_PR)
{
    Processor (CPU0, 0x00, 0x00000410, 0x06)
    {
        ....
    }
    ....
}


Scope (_GPE)放着相关的事件处理


Scope (_GPE)
{
    Method (_L0D, 0, NotSerialized)
    {
        ....
    }
    ....
}


乍一看不是函数吗?当然函数也可以放在这里。但是请注意函数名“_”开头,是系统保留的函数。
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")//定义一个字符串


Name (_PRW, Package (0x02)
                {
                    0x0D,
                    0x03
                })


//定义一个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
举例如下:


Add(1, 2, Local0) //Local0 = 1 + 2
And(0x11, 0x22, Local0) //Local0 = 0x11 & 0x22
Divide(10, 9, Local1, Local0) //Local0 = 10 / 9, Local1 = 10 % 9
Mod (10, 9, Local0) //Local0 = 10 % 9
Multiply(1, 2, Local0) //Local0 = 1 * 2
ShiftLeft(1, 20, Local0) // Local0 = 1 << 20
ShiftRight(0x10000, 4, Local0) // Local0 = 0x10000 >> 4
Subtract(2, 1, Local0) //Local0 = 2 - 1
Or(0x01, 0x02, Local0) //Local0 = 0x01 | 0x02
Not(0x00,Local0) //Local0 = ~(0x00)
Nor(0x11, 0x22, Local0) //Local0 = ~(0x11) & ~(0x22)


ASL逻辑运算:
LAnd 逻辑与
LEqual 逻辑相等
LGreater 逻辑大于
LGreaterEqual 逻辑大于等于
LLess 逻辑小于
LLessEqual 逻辑小于等于
LNot 逻辑反
LNotEqual 逻辑不等于
LOr 逻辑或


Store (LAnd(1, 1), Local0) //Local0 = 1 & 1
Store (LEqual(1, 1), Local0) //Local0 = (1 == 1)
Store (LGreater(1, 2), Local0) //Local0 = (1 > 2)
Store (LGreaterEqual(1, 2), Local0) //Local0 = (1 >= 2)
Store (LLess(1, 2), Local0) //Local0 = (1 < 2)
Store (LLessEqual(1, 2), Local0) //Local0 = (1 <= 2)
Store (LNot(0), Local0) //Local0 = !0
Store (LNotEqual(0, 1), Local0) //Local0 = (0 != 1)
Store (LOR(0, 1), Local0) //Local0 = (0 | 1)


不难发现逻辑运算只会有两种结果0或者1。

ASL函数的定义:
1、定义函数


Method(TEST)
{}


2、定义有两个输入参数的函数,以及使用局部变量Local0~Local7


Method(MADD,2)
{
    Store(Arg0, Local0)
    Store(Arg1, Local1)
    Add(Local0, Local1, Local0)
}


实现了两个参数的加法运算,因此传入的参数一定要隐式整形数。
3、定义带返回值的函数


Method(MADD,2)
{
    Store(Arg0, Local0)
    Store(Arg1, Local1)
    Add(Local0, Local1, Local0)
    Return (Local0)
}


例子为自定义加法的实现。函数实现如同系统函数Add一样的相加
Store(MADD(1,2), Local0) //Local0 = 1 + 2
4、定义可序列化的函数


Method(MADD, 2, Serialized)
{
Store(Arg0, Local0)
Store(Arg1, Local1)
Add(Local0, Local1, Local0)
Return (Local0)
}


这个有点类似于多线程同步的概念,也就是说,当函数声明为Serialized,内存中仅能存在一个实例。一般应用在函数中创建一个对象。应用举例说明:


Method(TEST, Serialized)
{
    Name(MSTR,"I will sucess"
}


如果这样子声明TEST这个函数,那么在两个地方同时调用这个函数


Device (Dev1)
{
     TEST()
}
Device (Dev2)
{
     TEST()
}


如果先执行Dev1的TEST,Dev2中的TEST将等待Dev1中的TEST函数执行完毕再执行。如果声明为


Method(TEST, NotSerialized)
{
Name(MSTR,"I will sucess"
}


那么将在其中一个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


If (_OSI ("Darwin"))
{
    Store (0x2710, OSYS)
}


2、ElseIf、Else用法介绍,如果系统结构不是Darwin,另外如果系统不是Linux,那么OSYS = 0x07D0


If (_OSI ("Darwin"))
{
    Store (0x2710, OSYS)
}
ElseIf (_OSI ("Linux"))
{
    Store (0x03E8, OSYS)
}
Else
{
    Store(0x07D0, OSYS)
}


3、Switch, Case, Defaule, BreakPoint示例


Switch(Arg2)
{
    Case(1)
    {
If(LEqual(1, Arg1)
{
    Return (1)
}
BreakPoint
    }
    Case(2)
    {
        ....
        Return (2)
    }
    Default
    {
        BreakPoint
    }
}


Switch可以看做是一系列If....Else的集合。BreakPoint相当于断点,意味着退出当前Swtich
(二)循环控制While,Break,Continue以及暂停Stall示例


Store(10, Local0)
While (LAnd (0x00, Local0))
{
    Decrement (Local0)
    Stall (32)
}


Local0等于10,如果Local0逻辑于0不为真,Local0自减1,暂停32us,所以这段代码延时10 * 32 = 320 us。

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


原文出自:http://bbs.pcbeta.com/viewthread-944566-1-1.html


这篇关于自己动手写DSDT系列教程1-ASL(ACPI Source Language)基础篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/909895

相关文章

Window Server创建2台服务器的故障转移群集的图文教程

《WindowServer创建2台服务器的故障转移群集的图文教程》本文主要介绍了在WindowsServer系统上创建一个包含两台成员服务器的故障转移群集,文中通过图文示例介绍的非常详细,对大家的... 目录一、 准备条件二、在ServerB安装故障转移群集三、在ServerC安装故障转移群集,操作与Ser

windos server2022的配置故障转移服务的图文教程

《windosserver2022的配置故障转移服务的图文教程》本文主要介绍了windosserver2022的配置故障转移服务的图文教程,以确保服务和应用程序的连续性和可用性,文中通过图文介绍的非... 目录准备环境:步骤故障转移群集是 Windows Server 2022 中提供的一种功能,用于在多个

龙蜥操作系统Anolis OS-23.x安装配置图解教程(保姆级)

《龙蜥操作系统AnolisOS-23.x安装配置图解教程(保姆级)》:本文主要介绍了安装和配置AnolisOS23.2系统,包括分区、软件选择、设置root密码、网络配置、主机名设置和禁用SELinux的步骤,详细内容请阅读本文,希望能对你有所帮助... ‌AnolisOS‌是由阿里云推出的开源操作系统,旨

PyTorch使用教程之Tensor包详解

《PyTorch使用教程之Tensor包详解》这篇文章介绍了PyTorch中的张量(Tensor)数据结构,包括张量的数据类型、初始化、常用操作、属性等,张量是PyTorch框架中的核心数据结构,支持... 目录1、张量Tensor2、数据类型3、初始化(构造张量)4、常用操作5、常用属性5.1 存储(st

Java操作PDF文件实现签订电子合同详细教程

《Java操作PDF文件实现签订电子合同详细教程》:本文主要介绍如何在PDF中加入电子签章与电子签名的过程,包括编写Word文件、生成PDF、为PDF格式做表单、为表单赋值、生成文档以及上传到OB... 目录前言:先看效果:1.编写word文件1.2然后生成PDF格式进行保存1.3我这里是将文件保存到本地后

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

python库fire使用教程

《python库fire使用教程》本文主要介绍了python库fire使用教程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1.简介2. fire安装3. fire使用示例1.简介目前python命令行解析库用过的有:ar

LinuxMint怎么安装? Linux Mint22下载安装图文教程

《LinuxMint怎么安装?LinuxMint22下载安装图文教程》LinuxMint22发布以后,有很多新功能,很多朋友想要下载并安装,该怎么操作呢?下面我们就来看看详细安装指南... linux Mint 是一款基于 Ubuntu 的流行发行版,凭借其现代、精致、易于使用的特性,深受小伙伴们所喜爱。对

MySQL中my.ini文件的基础配置和优化配置方式

《MySQL中my.ini文件的基础配置和优化配置方式》文章讨论了数据库异步同步的优化思路,包括三个主要方面:幂等性、时序和延迟,作者还分享了MySQL配置文件的优化经验,并鼓励读者提供支持... 目录mysql my.ini文件的配置和优化配置优化思路MySQL配置文件优化总结MySQL my.ini文件

使用Nginx来共享文件的详细教程

《使用Nginx来共享文件的详细教程》有时我们想共享电脑上的某些文件,一个比较方便的做法是,开一个HTTP服务,指向文件所在的目录,这次我们用nginx来实现这个需求,本文将通过代码示例一步步教你使用... 在本教程中,我们将向您展示如何使用开源 Web 服务器 Nginx 设置文件共享服务器步骤 0 —