自己动手写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

相关文章

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

Java Scanner类解析与实战教程

《JavaScanner类解析与实战教程》JavaScanner类(java.util包)是文本输入解析工具,支持基本类型和字符串读取,基于Readable接口与正则分隔符实现,适用于控制台、文件输... 目录一、核心设计与工作原理1.底层依赖2.解析机制A.核心逻辑基于分隔符(delimiter)和模式匹

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

spring AMQP代码生成rabbitmq的exchange and queue教程

《springAMQP代码生成rabbitmq的exchangeandqueue教程》使用SpringAMQP代码直接创建RabbitMQexchange和queue,并确保绑定关系自动成立,简... 目录spring AMQP代码生成rabbitmq的exchange and 编程queue执行结果总结s

从基础到高阶详解Python多态实战应用指南

《从基础到高阶详解Python多态实战应用指南》这篇文章主要从基础到高阶为大家详细介绍Python中多态的相关应用与技巧,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、多态的本质:python的“鸭子类型”哲学二、多态的三大实战场景场景1:数据处理管道——统一处理不同数据格式

MySQL数据类型与表操作全指南( 从基础到高级实践)

《MySQL数据类型与表操作全指南(从基础到高级实践)》本文详解MySQL数据类型分类(数值、日期/时间、字符串)及表操作(创建、修改、维护),涵盖优化技巧如数据类型选择、备份、分区,强调规范设计与... 目录mysql数据类型详解数值类型日期时间类型字符串类型表操作全解析创建表修改表结构添加列修改列删除列

Python 函数详解:从基础语法到高级使用技巧

《Python函数详解:从基础语法到高级使用技巧》本文基于实例代码,全面讲解Python函数的定义、参数传递、变量作用域及类型标注等知识点,帮助初学者快速掌握函数的使用技巧,感兴趣的朋友跟随小编一起... 目录一、函数的基本概念与作用二、函数的定义与调用1. 无参函数2. 带参函数3. 带返回值的函数4.