ACPI设备树- ACPI命名空间的表示
摘要
Linux ACPI子系统将ACPI命名空间对象转换为/sys/devices/LNXSYSTM:00目录下的Linux设备树,并在接收到ACPI热插拔通知事件时进行更新。对于这个层次结构中的每个设备对象,在/sys/bus/acpi/devices中都有一个相应的符号链接。本文说明了ACPI设备树的结构。
ACPI Definition Blocks
ACPI固件在系统内存地址空间中建立RSDP(Root System Description Pointer 根系统描述指针),指向XSDT(Extended System Description Table 扩展系统描述表)。XSDT总是使用它的第一个条目指向FADT(Fixed ACPI Description Table 固定ACPI描述表),FADT中的数据包括描述硬件的固定ACPI特性的各种固定长度的条目。FADT包含一个指向DSDT(Differentiated System Description Table 微分系统描述表)的指针。XSDT还包含指向可能多个SSDTs(Secondary System Description Table 二级系统描述表)的条目。
DSDT和SSDT数据被组织在称为定义块的数据结构中,定义块包含各种对象的定义,包括用AML (ACPI机器语言)编码的ACPI控制方法。DSDT的数据块以及SSDTs的内容表示称为ACPI命名空间的分层数据结构,其拓扑结构反映底层硬件平台的结构。
上述ACPI系统定义表之间的关系如下图所示:
+---------+ +-------+ +--------+ +------------------------+ | RSDP | +->| XSDT | +->| FADT | | +-------------------+ | +---------+ | +-------+ | +--------+ +-|->| DSDT | | | Pointer | | | Entry |-+ | ...... | | | +-------------------+ | +---------+ | +-------+ | X_DSDT |--+ | | Definition Blocks | | | Pointer |-+ | ..... | | ...... | | +-------------------+ | +---------+ +-------+ +--------+ | +-------------------+ | | Entry |------------------|->| SSDT | | +- - - -+ | +-------------------| | | Entry | - - - - - - - -+ | | Definition Blocks | | +- - - -+ | | +-------------------+ | | | +- - - - - - - - - -+ | +-|->| SSDT | | | +-------------------+ | | | Definition Blocks | | | +- - - - - - - - - -+ | +------------------------+ | OSPM Loading | \|/ +----------------+ | ACPI Namespace | +----------------+ Figure 1. ACPI Definition Blocks
注意:RSDP也可以包含指向RSDT(Root System Description Table 根系统描述表)的指针。平台提供RSDT以实现与ACPI 1.0操作系统的兼容性。如果XSDT存在的话,操作系统将期望使用XSDT。
ACPI命名空间例子
所有定义块都加载到单个命名空间中。命名空间是由名称和路径标识的对象的层次结构。以下命名约定适用于ACPI命名空间中的对象名称:
- 所有名称都是32位长。
- 名称的第一个字节必须是 ' A ' - ' Z ' 或者 ‘ _ ’ 中的一个。
- 名称的每个剩余字节必须是' A' - ' Z ', ' 0 ' - ' 9 ' 或者 ‘ _ ’中的一个。
- 以 “_” 开头的名称由ACPI规范保留。
- 符号“\”表示命名空间的根(即前缀为“\”的名称相对于命名空间的根)。
- ‘ ^ ’符号表示当前命名空间节点的父节点(即以‘ ^ ’结尾的名称相对于当前命名空间节点的父节点)。
+------+ | \ | Root +------+ | | +------+ +-| _PR | Scope(_PR): the processor namespace | +------+ | | | | +------+ | +-| CPU0 | Processor(CPU0): the first processor | +------+ | | +------+ +-| _SB | Scope(_SB): the system bus namespace | +------+ | | | | +------+ | +-| LID0 | Device(LID0); the lid device | | +------+ | | | | | | +------+ | | +-| _HID | Name(_HID, "PNP0C0D"): the hardware ID | | | +------+ | | | | | | +------+ | | +-| _STA | Method(_STA): the status control method | | +------+ | | | | +------+ | +-| PCI0 | Device(PCI0); the PCI root bridge | +------+ | | | | +------+ | +-| _HID | Name(_HID, "PNP0A08"): the hardware ID | | +------+ | | | | +------+ | +-| _CID | Name(_CID, "PNP0A03"): the compatible ID | | +------+ | | | | +------+ | +-| RP03 | Scope(RP03): the PCI0 power scope | | +------+ | | | | | | +------+ | | +-| PXP3 | PowerResource(PXP3): the PCI0 power resource | | +------+ | | | | +------+ | +-| GFX0 | Device(GFX0): the graphics adapter | +------+ | | | | +------+ | +-| _ADR | Name(_ADR, 0x00020000): the PCI bus address | | +------+ | | | | +------+ | +-| DD01 | Device(DD01): the LCD output device | +------+ | | | | +------+ | +-| _BCL | Method(_BCL): the backlight control method | +------+ | | +------+ +-| _TZ | Scope(_TZ): the thermal zone namespace | +------+ | | | | +------+ | +-| FN00 | PowerResource(FN00): the FAN0 power resource | | +------+ | | | | +------+ | +-| FAN0 | Device(FAN0): the FAN0 cooling device | | +------+ | | | | | | +------+ | | +-| _HID | Name(_HID, "PNP0A0B"): the hardware ID | | +------+ | | | | +------+ | +-| TZ00 | ThermalZone(TZ00); the FAN thermal zone | +------+ | | +------+ +-| _GPE | Scope(_GPE): the GPE namespace +------+ Figure 2. Example ACPI Namespace
Linux ACPI Device Objects
Linux内核的核心ACPI子系统为ACPI命名空间对象创建 struct acpi_device 对象,这些对象表示设备、电源资源处理器、thermal zones。这些对象通过sysfs作为/sys/devices/LNXSYSTM:00下的子树目录导出到用户空间。它们的名称格式为<bus_id:instance>,其中‘ bus_id ’指给定对象的ACPI命名空间表示,‘ instance ’用于区分相同‘ bus_id ’的不同对象(它是无符号整数的两位数十进制表示)。
‘ bus_id ’的值取决于其所属对象的类型,如下表所示:
+---+-----------------+-------+----------+ | | Object/Feature | Table | bus_id | +---+-----------------+-------+----------+ | N | Root | xSDT | LNXSYSTM | +---+-----------------+-------+----------+ | N | Device | xSDT | _HID | +---+-----------------+-------+----------+ | N | Processor | xSDT | LNXCPU | +---+-----------------+-------+----------+ | N | ThermalZone | xSDT | LNXTHERM | +---+-----------------+-------+----------+ | N | PowerResource | xSDT | LNXPOWER | +---+-----------------+-------+----------+ | N | Other Devices | xSDT | device | +---+-----------------+-------+----------+ | F | PWR_BUTTON | FADT | LNXPWRBN | +---+-----------------+-------+----------+ | F | SLP_BUTTON | FADT | LNXSLPBN | +---+-----------------+-------+----------+ | M | Video Extension | xSDT | LNXVIDEO | +---+-----------------+-------+----------+ | M | ATA Controller | xSDT | LNXIOBAY | +---+-----------------+-------+----------+ | M | Docking Station | xSDT | LNXDOCK | +---+-----------------+-------+----------+ Table 1. ACPI Namespace Objects Mapping
当根据ACPI System Description Tables(上表第一列的字母和第二列的符号表示)的内容创建struct acpi_device对象时,以下规则适用:
N:
对象的源是一个ACPI命名空间节点(如第二列中命名对象的类型所示)。在这种情况下,对象在sysfs中的目录将包含‘ path ’属性,其值是从命名空间root到节点的完整路径。
F:
struct acpi_device对象是为固定的硬件特性创建的(如第二列中固定特性标志的名称所示),因此它的sysfs目录将不包含‘ path ’属性。
M:
acpi_device对象是为具有特定控制方法的ACPI命名空间节点创建的(如第二列中ACPI定义的设备类型所示)。包含其命名空间路径的‘ path ’属性将出现在其sysfs目录中。例如,如果ACPI命名空间节点存在_BCL方法,则将为其创建一个带有LNXVIDEO ‘ bus_id ’的struct acpi_device对象。
上表的第三列表明ACPI系统描述表包含用于创建由给定行表示的struct acpi_device对象的信息(xSDT表示DSDT或SSDT)。
上表第四列为struct acpi_device对象的“bus_id”生成规则:
_HID:
表最后一列中的_HID表示对象的bus_id是从对应的ACPI命名空间节点下的_HID/_CID标识对象派生出来的。然后,对象的sysfs目录将包含可用于检索该对象的_HID和_CID的‘ hid ’和‘ modalias ’属性。
LNXxxxxx:
‘ modalias ’属性也存在于具有“LNXxxxxx”形式(伪设备)的bus_id的struct acpi_device对象中,在这种情况下,它包含bus_id字符串本身。
device:
表中最后一列的device表示对象的bus_id不能从对应ACPI命名空间节点的_HID/_CID中确定,尽管该对象代表一个设备(例如,它可能是一个PCI设备,定义了_ADR,没有_HID或_CID)。在这种情况下,字符串‘ device ’将被用作对象的bus_id。
Linux ACPI Physical Device Glue
ACPI设备(即struct acpi_device)对象可以链接到Linux设备层次结构中表示“物理”设备的其他对象(例如,PCI总线上的设备)。如果发生这种情况,则意味着ACPI设备对象是以不同方式表示的设备的“伴侣”,并且用于(1)提供该设备上无法通过其他方式获得的配置信息;(2)借助其ACPI控制方法对设备执行特定操作。一个ACPI设备对象可以通过这种方式链接到多个“物理”设备。
如果一个ACPI设备对象被链接到一个“物理”设备,它的sysfs目录包含到目标设备对象的sysfs目录的“physical_node”符号链接。然后,目标设备的sysfs目录将包含到配套ACPI设备对象的sysfs目录的“firmware_node”符号链接。链接机制依赖于ACPI命名空间提供的设备标识。例如,如果有一个代表PCI设备的ACPI命名空间对象(即代表PCI桥的ACPI命名空间对象下的设备对象),其_ADR返回0x00020000,父PCI桥的总线号为0,sysfs目录表示为ACPI命名空间对象创建的struct acpi_device对象,将包含链接到相应PCI设备的/sys/devices/pci0000:00/0000:00:02:0/ sysfs目录的“physical_node”符号链接。
链接机制通常是特定于总线的。其实现的核心位于drivers/acpi/glue.c文件中,但是根据所讨论的总线类型,还有一些补充部分位于其他地方。例如,它的pci特定部分位于drivers/pci/pci-acpi.c中。
Example Linux ACPI Device Tree
struct acpi_device对象的sysfs层次结构对应于图2中所示的示例ACPI命名空间,并添加了固定的PWR_BUTTON/SLP_BUTTON设备,如下所示:
+--------------+---+-----------------+ | LNXSYSTM:00 | \ | acpi:LNXSYSTM: | +--------------+---+-----------------+ | | +-------------+-----+----------------+ +-| LNXPWRBN:00 | N/A | acpi:LNXPWRBN: | | +-------------+-----+----------------+ | | +-------------+-----+----------------+ +-| LNXSLPBN:00 | N/A | acpi:LNXSLPBN: | | +-------------+-----+----------------+ | | +-----------+------------+--------------+ +-| LNXCPU:00 | \_PR_.CPU0 | acpi:LNXCPU: | | +-----------+------------+--------------+ | | +-------------+-------+----------------+ +-| LNXSYBUS:00 | \_SB_ | acpi:LNXSYBUS: | | +-------------+-------+----------------+ | | | | +- - - - - - - +- - - - - - +- - - - - - - -+ | +-| PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: | | | +- - - - - - - +- - - - - - +- - - - - - - -+ | | | | +------------+------------+-----------------------+ | +-| PNP0A08:00 | \_SB_.PCI0 | acpi:PNP0A08:PNP0A03: | | +------------+------------+-----------------------+ | | | | +-----------+-----------------+-----+ | +-| device:00 | \_SB_.PCI0.RP03 | N/A | | | +-----------+-----------------+-----+ | | | | | | +-------------+----------------------+----------------+ | | +-| LNXPOWER:00 | \_SB_.PCI0.RP03.PXP3 | acpi:LNXPOWER: | | | +-------------+----------------------+----------------+ | | | | +-------------+-----------------+----------------+ | +-| LNXVIDEO:00 | \_SB_.PCI0.GFX0 | acpi:LNXVIDEO: | | +-------------+-----------------+----------------+ | | | | +-----------+-----------------+-----+ | +-| device:01 | \_SB_.PCI0.DD01 | N/A | | +-----------+-----------------+-----+ | | +-------------+-------+----------------+ +-| LNXSYBUS:01 | \_TZ_ | acpi:LNXSYBUS: | +-------------+-------+----------------+ | | +-------------+------------+----------------+ +-| LNXPOWER:0a | \_TZ_.FN00 | acpi:LNXPOWER: | | +-------------+------------+----------------+ | | +------------+------------+---------------+ +-| PNP0C0B:00 | \_TZ_.FAN0 | acpi:PNP0C0B: | | +------------+------------+---------------+ | | +-------------+------------+----------------+ +-| LNXTHERM:00 | \_TZ_.TZ00 | acpi:LNXTHERM: | +-------------+------------+----------------+ Figure 3. Example Linux ACPI Device Tree
注意:
每个节点用“object/path/modalias”表示,其中:
1. ‘ object ’是对象在sysfs中的目录名。
2. ‘ path ’是对应的ACPI命名空间对象的ACPI命名空间路径,由对象的‘ path ’ sysfs属性返回。
3. ‘ modalias ’是对象的‘ modalias ’ sysfs属性的值(如本文档前面所述)。
本文来自博客园,作者:闹闹爸爸,转载请注明原文链接:https://www.cnblogs.com/wanglouxiaozi/p/18720529
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)