ACPI调试

ACPI调试

2024-12-23
bios
  • 参考 ACPI AML Runtime Debugger in Ubuntu 18.04 (x64)
  • 之前一直以为ACPI是无法加打印的,但是在写ASL的过程中遇到了一些难于解决的问题,经过搜索后有了下面这篇文章。
  • 要启用AML的打印,需要在编译内核时指定CONFIG_ACPI_DEBUGGER=y这个参数,否则是无法打印的,不过ubuntu在Ubuntu 18.04 (x64)之后就默认设置了这个参数,所以可以我们可以使用ubuntu系统来做AML的调试。下面所有的代码调试都是在ubuntu server 22.04.5上实现。

环境配置 #

  • 要进行ACPI调试前需要安装acpidbg工具,该工具需要联网下载,但是我的调试服务器没办法联网,所以现在本地搭建了一个一样的虚拟机,通过虚拟机下载相应的deb包,随后拷到服务器上安装。
  • 安装虚拟机过程略过,下面说一下虚拟机的网络配置,virtualbox默认会启动NAT网络地址转换,NAT能让虚拟机连上外网,但是无法通过SSH连上虚拟机;我们需要启用一个仅主机网络(相当于在物理机上创建了一个virtualbox专用的虚拟网卡),通过此虚拟网卡连接到虚拟机中。此虚拟网卡可以在virtualbox中配置IP地址。
  • NAT
  • 仅主机
  • 随后进入到虚拟机的/etc/netplan中,创建文件99_config.yaml,填充如下内容(详细可参考 Configuring networks|Ubuntu
network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s8:
      #IP配置取决于当前virtualbox总配置的IP地址
      addresses:
        - "192.168.168.168/24"
    enp0s3:
      #virtualbox nat,下面这些信息直接填照抄即可。
      addresses:
        - "10.0.2.15/24"
      nameservers:
        addresses: [8.8.8.8]
      routes:
        - to: default
          via: 10.0.2.2
  • 随后执行netplan apply让网络配置生效,此时就可以通过ssh连接到虚拟机内部了。
  • 通过ssh连接后,通过如下命令下载相应的deb包,执行完后,deb包会被下载到/var/cache/apt/archives目录下,将该目录下的deb包打包传递到服务器上安装即可。
apt install linux-tools-`uname -r` linux-tools-generic --download-only

ACPI Debug #

  • 按照如下Printf的格式加入打印信息到ASL中,%o会被替换成后面相应的变量。
Method (_SUN, 0, NotSerialized)  // _SUN: Slot User Number
{
    Printf("VendorId = %o, DeviceId = %o, Slot = %o", VEND, DEVI, SLTN)
    Return (SLTN)
}
  • 随后编译烧入BIOS后,进入服务器的OS中,执行acpidbg,就可以进行调试了。acpidbg常用的命令如namespacepathsexecute
  • namespace会打印出ACPI的层级关系,如下图所示
root@server:~# acpidbg


- namespace
ACPI Namespace (from Namespace Root):
 0  _GPE Scope        0000000008fab98e 000 
 0  _PR_ Scope        000000005953797b 000 
 1    C000 Processor    00000000a1ac5d21 01A ID 00 Len 06 Addr 0000000000000810
 2      _PCT Package      00000000a7326f94 01B Elements 02
 2      _PSS Package      0000000046ef281e 01B Elements 03
 2      XPSS Package      000000005f13ae73 01B Elements 03
 2      _PSD Package      000000009366b23a 01B Elements 01
 2      PPCV Integer      000000009ee3a624 01B = 0000000000000000
 2      _PPC Method       000000007965a545 01B Args 0 Len 0005 Aml 00000000be65bdfb
 1    C001 Processor    000000005eb2da62 01A ID 01 Len 06 Addr 0000000000000810
 2      _PCT Package      00000000ee112324 01B Elements 02
 2      _PSS Package      0000000091ffd188 01B Elements 03
 2      XPSS Package      00000000fb1c13d0 01B Elements 03
 2      _PSD Package      0000000039eb741a 01B Elements 01
 2      PPCV Integer      00000000df6eb317 01B = 0000000000000000
 2      _PPC Method       000000000665d99d 01B Args 0 Len 0005 Aml 00000000fdc3368c
 1    C002 Processor    00000000bfa4f34a 01A ID 02 Len 06 Addr 0000000000000810
  • paths会打印出namespace objects的全路径名
#从左到右依次是层级、Object类型以及全路径名
 3   Device           _SB.S0D2.D2C0
 4    Integer         _SB.S0D2.D2C0._ADR
 4    Method          _SB.S0D2.D2C0._PRW
 4    Method          _SB.S0D2.D2C0._PRT
 4    Region          _SB.S0D2.D2C0.K1PC
 4    RegionField     _SB.S0D2.D2C0.K1SL
 4    Device          _SB.S0D2.D2C0.BRG1
 5     Integer        _SB.S0D2.D2C0.BRG1._ADR
 5     Device         _SB.S0D2.D2C0.BRG1.BRG2
 6      Integer       _SB.S0D2.D2C0.BRG1.BRG2._ADR
 6      Device        _SB.S0D2.D2C0.BRG1.BRG2.BRG3
 7       Integer      _SB.S0D2.D2C0.BRG1.BRG2.BRG3._ADR
 7       Region       _SB.S0D2.D2C0.BRG1.BRG2.BRG3.PP8C
 7       RegionField  _SB.S0D2.D2C0.BRG1.BRG2.BRG3.VEND
 7       RegionField  _SB.S0D2.D2C0.BRG1.BRG2.BRG3.DEVI
 7       Method       _SB.S0D2.D2C0.BRG1.BRG2.BRG3._SUN
 3   Device           _SB.S0D2.D2C1
 4    Integer         _SB.S0D2.D2C1._ADR
  • 如果我们需要查看一个Field、Integer或者Method的执行结果,可以使用execute命令。
#查看_ADR的值
- execute _SB.S0D2.D2C0._ADR
Evaluating \_SB.S0D2.D2C0._ADR
Evaluation of \_SB.S0D2.D2C0._ADR returned object 000000003e779e35, external buffer length 18
 [Integer] = 0000000000030001

#查看_SUN method的执行结果
- execute _SB.S0D2.D2C0.BRG1.BRG2.BRG3._SUN
Evaluating \_SB.S0D2.D2C0.BRG1.BRG2.BRG3._SUN
ACPI Debug:  "VendorId = 0000000000001D94, DeviceId = 0000000000006210, Slot = 0000000000000002"
Evaluation of \_SB.S0D2.D2C0.BRG1.BRG2.BRG3._SUN returned object 000000003e779e35, external buffer length 18
 [Integer] = 0000000000000002

#查看RegionField的值
- execute _SB.S0D2.D2C0.BRG1.BRG2.BRG3.VEND
Evaluating \_SB.S0D2.D2C0.BRG1.BRG2.BRG3.VEND
Evaluation of \_SB.S0D2.D2C0.BRG1.BRG2.BRG3.VEND returned object 0000000066540b46, external buffer length 18
 [Integer] = 0000000000001D94

其他 #

  • 如果需要在dmesg中查看ASL中增加的打印,可以修改/etc/default/grub文件,加入如下配置信息(具体含义可以参考 ACPI Debug Output),并执行update-grub让其生效,随后重启就能在dmesg中看到ASL中的打印信息了。
GRUB_CMDLINE_LINUX_DEFAULT="acpi.debug_layer=0xFFFFFFFF acpi.debug_level=0x2"