ASL REFERENCE

  • 基本准则
  • 数据运算
    • 算术运算
    • 逻辑运算
  • 函数,流程语句
  • OperationRegion 的使用,IO,Memory,PCI,EC读写

在项目中SIO芯片部分控制着各种设备串口的功能,而对于该部分需要ASL语言来表述。目前ACPI的最新版本是6.3版本,相关的SPEC可以在Specifications | Unified Extensible Firmware Interface Forum中下载到,本文主要内容来源为SPEC第19章ACPI SOURCE LANGUAGE (ASL) REFERENCE以及一个基础语法的文件,主要写了自己项目中遇到的相关用法,后续遇到会继续补充。

ASL是一种用于定义ACPI对象(包括编写ACPI控制方法)的源语言。原始设备制造商OEM和平台固件开发人员用ASL定义对象和编写控制方法,然后使用翻译工具(编译器)生成控制方法的ACPI机器语言(AML)版本。

AML和ASL是不同的语言,尽管它们是密切相关的。每个acpi兼容的操作系统都必须支持AML。给定的用户可以定义一些任意的源语言(替换ASL),并编写一个工具将其转换为AML。OEM或平台固件供应商需要编写ASL,并能够单步AML进行调试。(调试器和类似的工具应该是aml级别的工具,而不是源代码级别的工具。)一个ASL翻译实现者必须了解如何读取ASL和生成AML。AML解释器作者必须了解如何执行AML。

对于数学和逻辑操作,ASL支持类似于C语言的标准符号操作符和表达式。还支持复合赋值操作符。由符号操作符和表达式生成的AML代码与为等价的遗留ASL操作符生成的AML代码相同。

基本准则

  1. 变量命名不超过 4 个字符,且不能以数字开头。
  2. 变量或者函数命名,不分大小写(VB?= Very bad)
  3. Scope 形成作用域,概念类似于 C++中的 namespace,Java 中的 package。
  4. Device 定义也会形成自己的作用域,类似于 C++中 class 的概念
  5. Method 或者 Function 定义函数,函数可以定义在 Device 下或者 Scope 下,但是不能脱离 Scope 定义单独的函数,也就是说,函数必须依附于对象(Scope or device)
  6. 以"_"字符开头的函数,都是系统保留的,不得给自己的函数取这样的名字
  7. ASL 中没有运算符号(逻辑或者算术都是如此),但有与此等价的相应系统函数代替
  8. 符号“\”引用根作用域,“^”引用父级或称上级作用域
  9. 作用域,或者称路径,有相对和绝对之分。相对作用域从当前作用域开始,向上延伸。也就是说在当前作用域中使用函数和变量时,解析器会首先从当前作用域中寻找它的定义,如果找不到,则会从父级或称上级作用域中继续寻找,一直找到当前作用域的 root 为止。绝对径,则从定义此变量或者函数的root 作用域开始,一级级写下去,一直写到此变量的作用域,作用域的引用使用符号“”,例如\SB.PCI0.ABCD 。
  10. 函数最多可传递 8 个参数,在函数里用 Arg0~Arg7 引用,不可以自己定义名字
  11. 在函数中最多可以使用 8 个局部变量,用 Local0~Local7 表示,不用定义,但是在把局部变量的值赋给其他变量之前,局部变量必须是有效的值,也就是说,至少有一次把值赋给局部变量的操作
  12. 声明变量时不需要显式声明其类型,会Perl 或者 Python 这类 Script 语言的见怪不怪。

数据运算

  1. 数据类型 ASL 中支持的数据类型有,
    a) 整数- Integer,
    b) 字符串 - String,
    c) 事件 - Event,
    d) 数组 - Buffer,
    e) 对象集合 - Package
  2. 定义变量
    Name(MYTS, 0) // 定义一个整数
    Name(TSTR, “Hello ASL”) // 定义一个字符串
  3. 赋值
    最常用的赋值函数只有一个,即 Store(), 如
    Store(0x1234, Local0) // Local0 = 0x1234;
    Store(“Hello ASL”, Local0) // Local0 = “Hello ASL”
    下图总结了基本的符号运算:数学运算符、逻辑运算符、赋值和复合赋值操作

算术运算


当然嵌套也是可以的,例如: Store(Add(5, 4), Local0) // Local0 = 5 + 4

对于运算符的优先级 + - 最低 ,* / % 高一级 ,例如 Loca10 = (5+3) * 12 + 100/9 - 100%9

第一步,从最低优先级最后的 + - 开始,转换
Store(Subtract(Add((5+3) * 12 , 100/9), 100%9), Loca10)
第二步,“*”“/”“%”3 个运算处于同一优先级,可以同时转换
Store(Subtract(Add(Multiply((5+3) , 12) , Divide(100,9)), Mod(100,9)), Loca10)
最后,将括号内的加法转换
Store(Subtract(Add(Multiply(Add(5,3), 12) , Divide(100,9)), Mod(100,9)), Loca10)
这样就可以成功得到一个完全用 ASL 写成的算式。

逻辑运算


复合使用:Local0 = 30*( 5== 3) + (50/4 >= 30)
第一步,将最高优先级的“==”和“/”转换成 ASL 符号
Local0 = 30 * LEqual(5, 3) + (Divide(50, 4) >= 30)
第二步,将“*”和“>=”转换成 ASL
Local0 = Multiply(30 , LEqual(5, 3)) + (LGreaterEqual(Divide(50, 4) ,30))
第三步,将“+”和“=”转换成 ASL 符号
Store(Add (Multiply(30, LEqual(5, 3)), LGreaterEqual(Divide(50, 4) ,30)), Loca10)

函数,流程语句

1.定义函数Method(TMED){}
2. 定义有两个输入参数的函数

Method(TMED, 2)
{
// Arg0 - 第一个输入参数
// Arg1 - 第二个输入参数
}
  1. 在函数中使用局部变量
Method(TMED, 2)
{Store(Arg0, Local0)Store(Arg1, Local1)Add(Local0, Local1, Local0)
}

4 . 在函数中使用返回值

Method(TMED, 2)
{Store(Arg0, Local0)Store(Arg1, Local1)Add(Local0, Local1, Local0)Return(Local0)
}
  1. 调用函数
    TMED(3, 5)
  2. 保存函数的返回值
Store(TMED(4, 5), TMPD)

If的用法

Store (4, Local2)
If (And (Local0, Local2))
{XOr (Local0, Local2, Local0)
}

ElseIf 的用法

If (LEqual (local0, "Microsoft Windows NT"))
{Store (3, TOOS)
}
ElseIf (LEqual (Local0, "Microsoft Windows"))
{Store (1, TOOS)
}
ElseIf (LEqual (Local0, "Microsoft WindowsME:Millennium Edition"))
{Store (2, TOOS)
}

Else 的用法

If (LGreater (Local0, 5)
{Increment (CNT)
} Else If (Local0) {Add (CNT, 5, CNT)
} Else
{Decrement (CNT)
}

switch case default 的用法

switch(Arg2)
{case(0){switch(Arg1){case(0) {return (Buffer() {0x1F})}case(1) {return (Buffer() {0x3F})}}return (Buffer() {0x7F})}case(1){… function 1 code …Return(Zero)}case(2){… function 2 code …Return(Buffer(){0x00})}case(3) { … function 3 code …}case(4) { … function 4 code …}default {BreakPoint }
}

循环控制 While, Break, Continue
While的用法

While(LEqual(Local0, 45))
{
Noop
}

Break的用法

While(LEqual(Local0, 45))
{If(Mod (Local0, 4)){Break}Noop
}

Continue的用法

While(LEqual(Local0, 45))
{If(Mod (Local0, 4)){Continue}Noop
}

OperationRegion 的使用,IO,Memory,PCI,EC读写

Spec 有一些特殊的规定

  1. OS 必须保证 SystemIO OperationRegion 在任何情况下都可以使用
  2. OS 必须保证 PCI Root Bus 下的 PCI_Config OperationRegion 一定可用
  3. OS 必须保证,SystemMemory OperationRegion 在访问通过 Memory Map Report 的 Memory 时,一定可
    用。事实上,这一条就是说明,只要是在有效地址空间中的 Memory 访问,OS 必须保证 Memory
    OperationRegion 可用

IO OperationRegion
展示一个 IO OperationRegion 的使用,我们使用定义的 OperationRegion,将 debug code输出到 80 Port
//示例开始

OperationRegion (DBGP, SystemIO, 0x80, 4)
Field (DBGP, ByteAcc, Lock, Preserve)
{P80L, 8
}
Store(0xA3, P80L) // 输出 A3 到 80 port

Memory OperationRegion

对于 PCIe 设备来说,有两种访问方法,一种是通过传统的 PCI 兼容方式,另外一种是通过 MMIO,不但可以访问 PCI 的 256 byte
的 PCI Space,而且可以访问全部的 4K PCI space,有这样一组函数,他能够在 ASL 里面自由的访问 PCI Express 的 Configuration Space。
//示例开始

#define PCIE_BASE 0xE0000000
Method (RDPB, 1)
{Add (Arg0, PCIE_BASE, Local0) // Add PCI Express MMIO base addressOperationRegion (PECF, SystemMemory, Local0, 0x1)Field (PECF, ByteAcc, Nolock, Preserve){MCFG, 8 ,}Return (MCFG)
}
//上面展示的函数是直接通过 MMIO 访问 PCI Express 设备的 configuration space,但是上面函数只适合
//比较熟练的开发者使用,因为需要自己计算 PCIe 设备的地址,那么,我们把上面的函数稍微转换一下,
//变成下面的函数,这样就够直观了。
// Arg0 - bus no
// Arg1 - dev no
// Arg2 - func no
// Arg3 - register offset
Method (RDPB, 4)
{ShiftLeft(Arg0, 20, Local0) // 计算 bus number PCIe addressOr(ShiftLeft(Arg1, 15), Local0, Local0) // 计算 device number PCIe addressOr(ShiftLeft(Arg2, 12), Local0, Local0) // 计算 function number PCIe addressOr(Arg3, Local0, Local0) // 计算 register,形成最终 PCIe addressAdd (Arg0, PCIE_BASE, Local0) // Add PCI Express MMIO base addressOperationRegion (PECF, SystemMemory, Local0, 0x1)Field (PECF, ByteAcc, Nolock, Preserve){MCFG, 8 ,}Return (MCFG)
}

上面的函数,可以直接在 ASL 读某个 PCIe 设备的一个 byte,例如,读 PCI 设备,bus 0,dev 31, func 3, register 0x40,可以使用如下语句:
Store(RDPB(0, 31, 3, 0x40), Local0)
上面是读 PCIe Register 的函数,接下来,我们将上面的函数稍作修改,写一个写 byte 到 PCIe register的函数。

// Arg0 - bus no
// Arg1 - dev no
// Arg2 - func no
// Arg3 - register offset
// Arg4 - value
Method (WRPB, 4)
{ShiftLeft(Arg0, 20, Local0) // 计算 bus number PCIe addressOr(ShiftLeft(Arg1, 15), Local0, Local0) // 计算 device number PCIe addressOr(ShiftLeft(Arg2, 12), Local0, Local0) // 计算 function number PCIe addressOr(Arg3, Local0, Local0) // 计算 register,形成最终 PCIe addressAdd (Arg0, PCIE_BASE, Local0) // Add PCI Express MMIO base addressOperationRegion (PECF, SystemMemory, Local0, 0x1)Field (PECF, ByteAcc, Nolock, Preserve){MCFG, 8 ,}Store(Arg4, MCFG)
}

可以使用以下语句,将一个 byte 写入到 bus 0, dev 31, func 3, register 0x40
WRPB(0, 31, 3, 0x40, 5)

PCI_CONFIG OperationRegion

可以通过定义 PCI OperationRegion 来访问 PCI 和 PCI Express 设备的配置空间。不过,可以从 PCIOperationRegion 的定义看到,OperationRegion 本身只定义 Register 在 Configuration Space 的位置和长度,但不能确定 PCI 设备 bus number,device number,和 function number,所以也就不能确定设备的地址。 ACPI 引入了其他一些 Method 来确定 ACPI 中 PCI 设备的地址。 _SEG 函数定义 PCI 设备的Segment,在 x86 架构中来说,一般不使用_SEG,所有的 PCI 设备默认都在 Segment 0. _BBN 函数定义PCI Root Bridge 的 bus number,一般来说在 PCI Root Bridge 下定义_BBN(0),意指从 bus 0 开始。有了 segment 和 bus,最后我们在 PCI 设备下定义一个_ADR 属性,确定此 PCI 设备的 device number 和function number,_ADR 的返回值中,高 16 位表示 device number,低 16 位表示 function number,接下来将展示一段 sample code,读写 bus 0 ,device 29,function 1 USB controller 的 PCI Configuration Space
//示例开始

Name(_ADR, 0x001d0001) // Device (HI WORD)=29, Func (LO WORD)=1
OperationRegion(USBR, PCI_Config, 0xC4, 1)
Field(USBR, ANYACC, NOLOCK, PRESERVE)
{URES, 8
}Method(TEMD)
{Store(3, URES)
}

EC OperationRegion
EC OperationRegion 是定义 EC Space 操作的,可以在 ASL 里面定义 EC OperationRegion,直接读写 ECOperationRegion,OS 的 ACPI 或者 EC Driver 或将这些操作转换为对 EC Space 的读写。根据 ACPI spec,对于一个读操作,driver 会向 EC 发送 0x80 command 读其中的 value,对于写操作,driver 会向 EC 发0x81 command 将一个 value 写道 EC Space。接下来定义一个 EC OperationRegion,假设 EC Space offset 0x00 是 CPU 的温度。
//示例开始

OperationRegion (ECF2, EmbeddedControl, 0x00, 0xFF)
Field (ECF2, ByteAcc, Lock, Preserve)
{CTMP, 8, //CPU Temp
}
Store(CTMP, Local0) // Read CPU temperature from EC Space

与上面其他 OperationRegion 不同的是,EC OperationRegion 并不是任何时刻都可以使用,所以我们要
follow ACPI spec,在同一 scope 中定义一个_Reg 属性,来判断 EC OperationRegion 是否可用
//示例开始

Name(ECON, 0) // Variable to remember EC OperationRegion Status
Method(_REG, 0x2)
{if(LEqual(Arg0, 0x03)) // Is it EC OperationRegion? Yes EC =3{If(Arg1) // Is OperationRegion Connect?{Store(0x01, ECON) // Available} Else // OperationRegion Disconnect{Store(0x00, ECON) // unavailable}[其他博客](https://blog.csdn.net/tom__mao__/article/details/51724568)

BIOS知识枝桠——ASL语言相关推荐

  1. BIOS知识枝桠——ACPI

    ACPI在BIOS中的应用 ACPI Overview Power State ACPI Table XSDT FADT ASL Code 变量和运算 函数 ACPI Overview 完全解读:Ad ...

  2. BIOS知识枝桠——SCI SMI IRQ

    SCI SMI 中断 中断分析 SCI SMI SMM SCI和SMI的异同 特殊的GPE: Q event SMI的几种常见的注册 SWSMI的触发 常见SMI的应用 中断 中断: 指当出现需要时, ...

  3. BIOS知识枝桠——GPU

    GPU理论阐述 概念 功能 供应商 NVIDIA GPU 名称解读 显存 GPU/显卡信息查看.鉴别工具 显示接口 GPU通用计算编程 科普类文章,无实际技术相关,内容来源网络 概念 图形处理器(英语 ...

  4. BIOS知识枝桠——FV

    FV 基本概念 架构组成 File Type&Section Type FV的访问 FV拓展 EFI IMAGE (PE/COFF) FV拓展 EFI OPTIONROM 基本概念 FD:固件 ...

  5. BIOS知识枝桠——Event

    Event 传统的中断模式 硬件中断 软件中断 Event Overview Event Function Event Use TPL Timer UEFI不再为开发者提供中断支持,但在UEFI内部还 ...

  6. BIOS知识枝桠——文件系统

    硬盘与文件系统 硬盘物理结构 MBR分区 GPU分区 FAT ROM Layout 硬盘物理结构 以一个机械硬盘为例,内部包括磁片.主轴.速写磁头.传动手臂.传动轴.反力矩弹簧装置,SSD没有这样的结 ...

  7. BIOS知识枝桠 -- PCIE

    博客内容来源为网络下载ppt,侵删 PCI的发展 PCI Local Bus 示意图 NoteBook上常见的PCIE Device:SSD DGPU WLAN LAN CardReader. 通过总 ...

  8. BIOS知识枝桠——Device Path

    EFI Device Path 定义&原型 文本表示形式 EFI Device Path种类 Hardware Device Path ACPI Device Path Messaging D ...

  9. BIOS知识枝桠—— Library

    Library overview Lib Overview Lib的文件结构 库的实体: 库的头文件: 库的Dec文件: 库函数的调用: MdePkg 常用Lib PUBLIC DEFINITIONS ...

最新文章

  1. AtCoder AGC033F Adding Edges (图论)
  2. Nginx monitor
  3. java删除xml文件中尖括号之外的内容
  4. vscode浏览器扩展(图文教程) - 设置篇
  5. Laravel 超好用代码提示工具 Laravel IDE Helper
  6. 深入浅出MFC学习笔记:MFC六大关键技术仿真之RTTI运行时类型识别
  7. 微服务架构实战篇(三):Spring boot2.0 + Mybatis + PageHelper实现增删改查和分页查询功能
  8. 在大多数人转向.NET和JAVA阵营的时候,我正在悄悄地向古老的COBOL招手
  9. java中将汉字转拼音,解决pinyin4j多音节问题
  10. 2D前景触发与3D触发结合案例
  11. sql 纵向求和_SQL中求和函数SUM()的应用实例
  12. 前端三刺客---JS(WebAPI)
  13. 蓝奏云获取直API源码
  14. PHP登入网站抓取并且抓取数据
  15. 怎么把用vue写的前后台项目打包上传到服务器让其能访问
  16. GORM CRUD 10 分钟快速上手
  17. 为什么只看重结果_不要只看重结果 过程也是美丽的
  18. IRAP 的安装以及运行的实例 主要就是瞎调让程序能跑,,,
  19. Matlab图片重命名
  20. 【FICO】S4下的资产年结

热门文章

  1. IPC-4921A 中文 CN、IPC-4552B 中文、IPC-6013E 中文 CN、IPC-HDBK-9798,IPC-6018D,IPC-6018DS
  2. AutoCAD .Net二次开发之Editor选择集
  3. 《SGX ECALL》汇总
  4. win10 复制F12后的http请求入参的json
  5. 查看电脑的外网IP地址
  6. linux下intel安装教程,在 Ubuntu 15.10 上安装 Intel Graphics 安装器
  7. matlab画青藏高原地图,教程合集 | NCL与GrADS地图绘制合集
  8. 【Kuangbin数论】阿拉丁和飞毯
  9. 答疑解惑 2017中国软件生态大会兰州播撒云生态火种
  10. 查看tomcat进程号,并终止进程