ACPI 中文文档ACPI 中文文档
首页
第 1 章
第 2 章
第 3 章
第 4 章
第 5 章
第 6 章
第 7 章
第 8 章
第 9 章
第 10 章
第 11 章
第 12 章
第 13 章
第 14 章
第 15 章
第 16 章
第 17 章
第 18 章
第 19 章
第 20 章
第 21 章
附录 A
首页
第 1 章
第 2 章
第 3 章
第 4 章
第 5 章
第 6 章
第 7 章
第 8 章
第 9 章
第 10 章
第 11 章
第 12 章
第 13 章
第 14 章
第 15 章
第 16 章
第 17 章
第 18 章
第 19 章
第 20 章
第 21 章
附录 A
  • 第 21 章

    • 总览
    • 21.1. ACPI 数据表的类型
    • 21.2. ACPI 表定义语言规范

21.2. ACPI 表定义语言规范

以下各节定义了 ACPI 表定义语言(TDL)。语法记号遵循与 ASL 源语言相同的规则(见第 19.2.1 节)。各种数据类型的完整定义遵循 ASL 语法规范。

21.2.1. 表定义语言(TDL)概述

大多数 ACPI 表具有如下结构(FACS 除外):

  • 一个通用的 36 字节表头,包含表签名、长度、校验和、修订版本以及其他数据。

  • 一个表主体,包含特定于该表的数据。

表定义语言允许通过字段集合来定义 ACPI 表。TDL 源代码的每一行都是一个字段,并对应于表定义中的单个数据项。

例如,通用 ACPI 表头的 C 定义如下:

typedef struct acpi_table_header
{
    char Signature[4];
    UINT32 Length;
    UINT8 Revision;
    UINT8 Checksum;
    char OemId[6];
    char OemTableId[8];
    UINT32 OemRevision;
    char AslCompilerId[4];
    UINT32 AslCompilerRevision;
} ACPI_TABLE_HEADER;

在表定义语言中,ACPI 表头可以描述如下:

: "ECDT"
: 00000000
: 01
: 00
: "OEM "
: "MACHINE1"
: 00000001
: ""
: 00000000

此外,还可以选择性地使用伴随的字段名来描述:

            Signature : "ECDT" [Embedded Controller Boot Resources Table]
         Table Length : 00000000
             Revision : 01
             Checksum : 00
               Oem ID : "OEM "
         Oem Table ID : "MACHINE1"
         Oem Revision : 00000001
      Asl Compiler ID : ""
Asl Compiler Revision : 00000000

注

在 ACPI 表头中,TableLength、Checksum、AslCompilerId 和 AslCompilerRevision 字段都是输出字段,在表生成期间由编译器自动填充。此外,字段名由反汇编器输出,该反汇编器将现有表格式化为 TDL 代码。

21.2.2. TDL 语法规范

说明:本节给出 TDL 的形式语法。为便于与原始规范、编译器输入格式以及后续章节交叉对照,语法中的非终结符、关键字名和数据类型名保留英文原名;说明性文字与注释译为中文。

> // 根项

> DataTable := > > > FieldList > > // 字段项

> FieldList := > > > Field | <Field FieldList>

> Field := > > > <FieldDefinition OptionalFieldComment> | CommentField

> FieldDefinition := > >> // 预定义(已知)ACPI 表的字段 >> >> > >> >> <OptionalFieldName ‘:’ FieldValue> | >> >> > >> >> // 通用数据类型(用于自定义或未定义的 ACPI 表) >> >> > >> >> <’uint8’ ‘:’ integerexpression> // 8 位无符号整数 >> >> <’uint16’ ‘:’ integerexpression> // 16 位无符号整数 >> >> <’uint24’ ‘:’ integerexpression> // 24 位无符号整数 >> >> <’uint32’ ‘:’ integerexpression> // 32 位无符号整数 >> >> <’uint40’ ‘:’ integerexpression> // 40 位无符号整数 >> >> <’uint48’ ‘:’ integerexpression> // 48 位无符号整数 >> >> <’uint56’ ‘:’ integerexpression> // 56 位无符号整数 >> >> <’uint64’ ‘:’ integerexpression> // 64 位无符号整数 >> >> <’string’ ‘:’ String> // 带引号的 ASCII 字符串 >> >> <’unicode’ ‘:’ String> // 将带引号的 ASCII 字符串转换为 Unicode 字符串 >> >> <’buffer’ ‘:’ byteconstlist> // 由 8 位无符号整数组成的原始缓冲区 >> >> <’guid’ ‘:’ guid> // 采用 GUID 格式 >> >> <’label’ ‘:’ label> // ASCII 标签 - 不带引号的字符串

> OptionalFieldName := > > > Nothing | AsciiCharList // 可选字段名称/描述

> FieldValue := > > > IntegerExpression | String | Buffer | Flags | Label

> OptionalFieldComment := > > > Nothing | <’[‘ asciicharlist ‘]’>

> CommentField := > > > <’//’ asciicharlist newline> | <’/’ asciicharlist ‘/’> | <’[‘ asciicharlist ‘]’> > > // 数据表达式

> IntegerExpression := > > > Integer | <integerexpression integeroperator integerexpression> | <’(‘ integerexpression ‘)’> > > // 以下运算符按优先级顺序给出。优先级规则与 C 语言相同。括号优先于所有运算符。

> IntegerOperator := > > > ‘!’ | ‘~’ | ‘*’ | ‘/’ | ‘%’ | ‘+’ | ‘-‘ | ‘<<’ | ‘>>’ | ‘<’ | ‘>’ | ‘<=’ | ‘>=’ | ‘==’ | ‘!=’ | ‘&’ | ‘^’ | ‘|’ | ‘&&’ | ‘||’ > > // 数据类型

> String := > > > <’”’ asciicharlist ‘”’>

> Buffer := > > > ByteConstList

> Guid := > > > <dwordconst ‘-‘ wordconst ‘-‘ wordconst ‘-‘ wordconst ‘-‘ const48>

> Label := > > > AsciiCharList > > // 数据项

> Integer := // 重复定义 - 见前一章 > > > ByteConst | WordConst | Const24 | DWordConst | Const40 | Const48 | Const56 | QWordConst | LabelReference

> LabelReference := > > > <’$’ label>

> Flags := > > > OneBit | TwoBits

> ByteConstList := > > > ByteConst | <byteconst ‘ ‘ byteconstlist>

> AsciiCharList := > > > Nothing | PrintableAsciiChar | <printableasciichar asciicharlist> > > // 终结符

> ByteConst := > > > 0x00-0xFF

> WordConst := > > > 0x0000 - 0xFFFF

> Const24 := > > > 0x000000 - 0xFFFFFF

> DWordConst := > > > 0x00000000 - 0xFFFFFFFF

> Const40 := > > > 0x0000000000 - 0xFFFFFFFFFF

> Const48 := > > > 0x000000000000 - 0xFFFFFFFFFFFF

> Const56 := > > > 0x00000000000000 - 0xFFFFFFFFFFFFFF

> QWordConst := > > > 0x0000000000000000 - 0xFFFFFFFFFFFFFFFF

> OneBit := > > > 0 - 1

> TwoBits := > > > 0 - 3

> PrintableAsciiChar := > > > 0x20 - 0x7E

> NewLine := > > > ‘\n’

21.2.3. 数据类型

21.2.3.1. 整数

ACPI 中的所有整数都是无符号的。编译器支持四种主要的无符号整数类型:Byte、Word、DWord 和 QWord。此外,对于特殊情况,还存在一些非标准大小的整数,例如 24 位和 56 位。整数实际所需的宽度由 ACPI 表定义。如果在输入源中指定的整数在数值上大于目标字段的宽度,编译器将发出错误。数据表编译器要求整数以十六进制形式输入,且不带“hex”前缀。

示例:

[001]     Revision : 04 // Byte (8-bit)
[002]   C2 Latency : 0000 // Word (16-bit)
[004] DSDT Address : 00000001 // DWord (32-bit)
[008]      Address : 0000000000000001 // QWord (64-bit)

非 2 的幂长度示例:

[003]     Reserved : 000000 // 24 bits
[007] Capabilities : 00000000000000 // 56 bits

21.2.3.2. 整数表达式

所有需要整数值的字段都支持表达式。

支持的运算符(标准 C 语义,按优先级顺序):

() Parentheses
! Logical NOT
~ Bitwise ones compliment (NOT)
* Multiply
/ Divide
% Modulo
+ Add
- Subtract
<< Shift left
>> Shift right
< Less than
> Greater than
<= Less than or equal
>= Greater than or equal
== Equal
!= Not Equal
& Bitwise AND
^ bitwise Exclusive OR
| Bitwise OR
&& Logical AND
|| Logical OR

示例:

[001]   Revision : 04 \* (4 + 7) // Byte (8-bit)
[002] C2 Latency : 0032 + 8 // Word (16-bit)

21.2.3.3. 标志

许多 ACPI 表包含标志字段。对于这些字段,只需要向编译器指定各个独立的标志位。编译器会将这些单独的位聚合为一个适当大小的整数。

示例:

[002] Flags (decoded below) : 0005
                   Polarity : 1
               Trigger Mode : 1

在此示例中,只需要向编译器指定 Polarity 和 Trigger Mode 字段(取值为零或一)。然后编译器会为 ACPI 表创建最终的 16 位 Flags 字段。

21.2.3.4. 字符串

字符串必须始终用引号括起来。编译器实际生成的字符串可能带有或不带有空终止符,这取决于 ACPI 规范中的表定义。例如,通用 ACPI 表头中的 OEM ID 和 OEM Table ID(如上所示)分别固定为六个和八个字符。它们不一定以空字符终止。然而,大多数字符串是变长的,并由编译器自动添加空终止符。如果为固定长度字符串字段指定的字符串过长,则会发出错误。字符串长度在每个相关 ACPI 表的定义中指定。

不允许在带引号的字符串中使用转义序列。反斜杠字符 ‘' 表示 ACPI 命名空间的根。

示例:

[008]         Oem Table ID : "TEMPLATE"   // Fixed length
[006] Processor UID String : "\CPU0 "     // Variable length

21.2.3.5. 缓冲区

当所需二进制数据大于一个 QWord,或者该数据不能恰好适配某种标准整数宽度时,通常会使用缓冲区。例如 UUID,以及由 SLIT 表定义的字节数据。

示例:

> // SLIT 项 > > [032] Locality 00A 10 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23
> > > 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 > > // DMAR 项 > > [002] PCI Path : 1F 07

每个十六进制字节都应单独输入,并以空格分隔。可以使用续行字符(反斜杠)将缓冲区数据延续到多行。

21.2.4. 由编译器自动设置的字段

有几类 ACPI 表字段由编译器自动设置。这通过免除程序员执行这些任务来简化 ACPI 表开发过程。

校验和:

所有 ACPI 表校验和都会被自动计算并插入。这包括出现在标准 ACPI 表头中的主校验和,以及任何附加的校验和字段,例如出现在 ACPI 2.0 RSDP 中的扩展校验和。

表和子表长度:

所有 ACPI 表长度都会被自动计算并插入。这包括出现在通用 ACPI 表头中的主表长度,以及任何适用的内部子表长度。

示例:

[004]  Table Length : 000000F4
[001] Subtable Type : 08 <platform interrupt sources>
[001]        Length : 10
[001] Subtable Type : 01 <memory affinity>
[001]        Length : 28

标志:

如上一节所述,各个标志会由编译器自动聚合,并作为大小和数值都正确的整数插入到 ACPI 表中。

编译器 ID:

数据表编译器会在编译期间,针对每个表,自动将 iASL 的 ID 和当前修订版本插入到通用 ACPI 表头中。

21.2.5. 特殊字段

保留字段:

所有在 ACPI(或其他)规范中由表定义声明为保留的字段都应设置为零。

表修订版本:

通用 ACPI 表头中的这个字段通常非常重要,并定义了表其余部分的结构。开发者应注意确保该值正确且为当前值。该字段不会由编译器自动设置。相反,它被用来指示正在编译的是哪个版本的表。

表签名:

ACPI 中有若干表签名要么不同于表名,要么长度不寻常:

FADT - 签名是 “FACP”。

MADT - 签名是 “APIC”。

RSDP - 签名是 “RSD PTR ”(带尾随空格)

21.2.6. TDL 通用数据类型

以下数据类型用于构造 TDL 编译器未预定义(已知)的 ACPI 表:

> UINT8 生成一个 8 位无符号整数 UINT16 生成一个 16 位无符号整数 UINT24 生成一个 24 位无符号整数 UINT32 生成一个 32 位无符号整数 UINT40 生成一个 40 位无符号整数 UINT48 生成一个 48 位无符号整数 UINT56 生成一个 56 位无符号整数 UINT64 生成一个 64 位无符号整数 String 生成一个以空字符结尾的 ASCII 字符串(ASCIIZ) Unicode 生成一个以空字符结尾的 Unicode(UTF-16)字符串 Buffer 生成一个由 8 位无符号整数组成的缓冲区 GUID 在一个 16 字节缓冲区中生成一个编码后的 GUID Label 在表中的当前位置(偏移量)生成一个标签。这个标签可以通过在标签前加上 ‘$’ 符号,在整数表达式中被引用。

21.2.7. 在 TDL 中定义已知的 ACPI 表

预计通过 TDL 编译器创建的大多数 ACPI 表,都是编译器已知的 ACPI 表。这意味着编译器包含该表所需的结构和定义,依据的是 ACPI 规范或该表的其他相关规范。

对于这些已知的 ACPI 表,指定表数据只需为表中的每个字段定义其值即可。编译器会自动确定数据类型,执行范围检查以及任何数值检查,并生成适当的输出。

任何已知 ACPI 表的起点,都是规定该表格式的文档(通常是 ACPI 规范),或者由 ASL 编译器生成的表模板文件,甚至可以是 AML 反汇编器的输出。编写 TDL 代码时,需要对表定义本身中指定的每个数据项实现一行代码。

例如,ACPI 表的表头可以简单地定义为一串字符串和整数。TDL 编译器会将这些数据项格式化为一个 36 字节的 ACPI 表头:

: "ECDT"
: 00000000
: 01
: 00
: "OEM "
: "MACHINE1"
: 00000001
: ""
: 00000000

21.2.8. 在 TDL 中定义未知或新的 ACPI 表

对于那些是新的或其格式对编译器而言未知的 ACPI 表,引入了“通用”数据类型,以允许使用显式数据类型来定义这些表。

通用数据类型示例:

     Label : StartRecord
     UINT8 : 11
    UINT16 : $EndRecord - $StartRecord // Record length
    UINT24 : 112233
    UINT32 : 11223344
    UINT56 : 11223344556677
    UINT64 : 1122334455667788

    String : "This is a string"
DevicePath : "\PciRoot(0)\Pci(0x1f,1)\Usb(0,0)"
   Unicode : "This string will be encoded to Unicode"

    Buffer : AA 01 32 4C 77
      GUID : 11223344-5566-7788-99aa-bbccddeeff00
     Label : EndRecord

21.2.9. 表定义语言示例

21.2.9.1. ECDT 反汇编器输出

iASL 反汇编器的输出可直接作为 TDL 编译器的输入使用:

[000h 0000 4]                 Signature : "ECDT" [Embedded Controller Data Table]
[004h 0004 4]              Table Length : 0000004E
[008h 0008 1]                  Revision : 01
[009h 0009 1]                  Checksum : F4
[00Ah 0010 6]                    Oem ID : "INTEL "
[010h 0016 8]              Oem Table ID : "TEMPLATE"
[018h 0024 4]              Oem Revision : 00000001
[01Ch 0028 4]           Asl Compiler ID : "INTL"
[020h 0032 4]     Asl Compiler Revision : 20110316

[024h 0036 12]  Command/Status Register :      [Generic Address Structure]
[024h 0036 1]                  Space ID : 01   [SystemIO]
[025h 0037 1]                 Bit Width : 08
[026h 0038 1]                Bit Offset : 00
[027h 0039 1]      Encoded Access Width : 00   [Undefined/Legacy]
[028h 0040 8]                   Address : 0000000000000066

[030h 0048 12]            Data Register :      [Generic Address Structure]
[030h 0048 1]                  Space ID : 01   [SystemIO]
[031h 0049 1]                 Bit Width : 08
[032h 0050 1]                Bit Offset : 00
[033h 0051 1]      Encoded Access Width : 00   [Undefined/Legacy]
[034h 0052 8]                   Address : 0000000000000062

[03Ch 0060 4]                       UID : 00000000
[040h 0064 1]                GPE Number : 09
[041h 0065 13]                 Namepath : "\_SB.PCI0.EC"

Raw Table Data: Length 78 (0x4E)

  0000: 45 43 44 54 4E 00 00 00 01 F4 49 4E 54 45 4C 20  ECDTN.....INTEL
  0010: 54 45 4D 50 4C 41 54 45 01 00 00 00 49 4E 54 4C  TEMPLATE....INTL
  0020: 16 03 11 20 01 08 00 00 66 00 00 00 00 00 00 00  ... ....f.......
  0030: 01 08 00 00 62 00 00 00 00 00 00 00 00 00 00 00  ....b...........
  0040: 09 5C 5F 53 42 2E 50 43 49 30 2E 45 43 00        .\_SB.PCI0.EC.

21.2.9.2. 带字段注释的 ECDT 定义

与反汇编器输出类似,但更简单:

Signature               : "ECDT" [Embedded Controller Data Table]
Table Length            : 0000004E
Revision                : 01
Checksum                : F4
Oem ID                  : "INTEL "
Oem Table ID            : "TEMPLATE"
Oem Revision            : 00000001
Asl Compiler ID         : "INTL"
Asl Compiler Revision   : 20110316

Command/Status Register : [Generic Address Structure]
Space ID                : 01 [SystemIO]
Bit Width               : 08
Bit Offset              : 00
Encoded Access Width    : 00 [Undefined/遗留]
Address                 : 0000000000000066

Data Register           : [Generic Address Structure]
Space ID                : 01 [SystemIO]
Bit Width               : 08
Bit Offset              : 00
Encoded Access Width    : 00 [Undefined/遗留]
Address                 : 0000000000000062

UID                     : 00000000
GPE Number              : 09
Namepath                : "\_SB.PCI0.EC"

21.2.10. 最小 ECDT 定义

一个不含字段名的最小 ECDT 定义示例:

: "ECDT" [Embedded Controller Boot Resources Table]
: 0000004E
: 01
: F4
: "INTEL "
: "TEMPLATE"
: 00000001
: "INTL"
: 20110316

: [Generic Address Structure]
: 01 [SystemIO]
: 08
: 00
: 00 [Undefined/Legacy]
: 0000000000000066

: [Generic Address Structure]
: 01 [SystemIO]
: 08
: 00
: 00 [Undefined/Legacy]
: 0000000000000062

: 00000000
: 09
: "\_SB.PCI0.EC"

21.2.10.1. 通用 ACPI 表定义

TDL 编译器未知的表可以通过使用通用数据类型来定义。不过,所有 ACPI 表都假定具有通用 ACPI 表头:

Signature             : "OEMZ"
Table Length          : 00000052
Revision              : 01
Checksum              : 6C
Oem ID                : "TEST"
Oem Table ID          : "CUSTOM "
Oem Revision          : 00000001
Asl Compiler ID       : "INTL
Asl Compiler Revision : 00000001

                UINT8 : 01
                UINT8 : 08
                UINT8 : 00
                UINT8 : 00
               UINT64 : 0000000000000066
               UINT32 : 00000000
                UINT8 : 12
               String : "Hello World!"
Prev
21.1. ACPI 数据表的类型