5.4. 定义块编码
本节指定定义块中用于定义名称(仅加载时间)、对象和包的编码。
5.4.1. AML 编码
定义块从头到尾被编码为流。流中的前导字节来自 ACPI 源语言 (ASL) 参考 中显示的 AML 编码表,表示如何解释一定数量的后续字节,其中每个后续字节又可以表示如何解释一定数量的后续字节。有关 AML 编码的完整规范,请参阅 ACPI 源语言 (ASL) 参考
在流中定义了两个级别的数据。一个是打包和对象声明(加载时),另一个是对象引用(包内容/运行时)。
所有编码都是这样的,编码的前导字节表示所进行的声明或引用的类型。该类型在流中具有隐式或显式长度。所有显式长度声明均采用如下所示的形式,其中 PkgLength 是操作数据的包含长度的长度。

图 5.17AML 编码
隐式长度对象的编码要么具有固定长度编码,要么允许嵌套编码,在某些时候,这会导致显式或隐式固定长度。
PkgLength 在流中被编码为一系列 1 到 4 个字节,最高有效两位为字节零,指示 PkgLength 编码中有多少个后续字节。接下来的两位仅用于一字节编码,这允许长度最大为 0x3F 的一字节编码。不使用这两个位的较长编码的最大长度如下:两字节编码 0x0FFF、三字节编码 0x0FFFFF 和四字节长度编码 0x0FFFFFFFF。
包长度不落在逻辑边界上是致命的。例如,如果一个包包含在另一个包中,则根据定义,其长度必须包含在外包内,对于隐式长度的数据也是如此。
5.4.2. 定义块加载
在某个时刻,系统软件决定“加载”定义块。当系统传递数据并填充ACPI命名空间并相应地初始化对象时,加载就完成了。发生填充的命名空间要么来自当前命名空间位置(由所有嵌套包定义),要么来自根(如果名称前面带有“”)。
定义块中出现的第一个对象必须是命名的控制方法。这是定义块的初始化控制。
包是包含对一个或多个对象的有序引用的对象。包也可以被视为数组的顶点,包中包含的任何对象都可以是另一个包。这允许固定或动态深度和顶点的多维数组。
未命名对象用于填充命名对象的内容。无法在“根”中创建未命名的对象。未命名的对象可以用作控制方法中的参数。
创建对象时控制方法执行可能会产生错误。如果创建命名对象的方法阻塞并在阻塞时重新进入,则可能会发生这种情况。发生这种情况是因为所有命名对象都有绝对路径。即使指定的对象名称是相对的,也是如此。例如,以下ASL代码段在功能上是相同的。
Method (DEAD)
{
Scope (\_SB_.FOO)
{
Name (BAR,0x1234) // Run time definition
}
}
Scope (\_SB_)
{
Name (\_SB_. FOO.BAR,) // Load time definition
}
请注意,在上面的示例中,DEAD 方法的执行始终会失败,因为对象 \SB.FOO.BAR 是在加载时创建的。
术语“定义块级”用于指不包含在任何控制方法中的AML字节流。此类AML字节流可以出现在“根”范围中或由“Device、PowerResource、Processor、Scope 和 ThermalZone”操作符创建/打开的范围中。详细说明请参见“ASL操作员参考、ASL操作员参考”。
定义块级别不仅允许命名对象,还允许所有术语对象(数学、逻辑和条件表达式等,请参阅“术语对象编码,术语对象编码”)。在定义块级别允许此类可执行AML操作码允许BIOS编写者根据系统设置定义动态对象列表。例如:
DefinitionBlock ("DSDT.aml", "DSDT", 2, "OEM", "FOOBOOK", 0x1000)
{
...
If (CFG1 () == 1))
{
...
Scope (_SB.PCI0.XHC.RHUB)
{
...
If (CFG2 () == 1)
{
...
Device (HS11)
{
...
If (CFG3 () == 1)
{
...
Device (CAM0)
{
...
}
...
}
...
}
...
}
...
}
...
}
...
}
定义块加载期间对定义块的解释与控制方法执行期间对控制方法的解释类似。