ACPI AML debug and override ACPI tables using initrd

本文介绍ACPICA debugger tools,acpidbg和acpidump、acpiexec等;并演示如何使用这些工具,配合initrd,在不重新加载firmware的情况下,修改ACPI table。

一、ACPICA debugger acpidbg

acpidbg是一个runtime调试AML code的工具,不过Linux kernel 4.13中才引入。

1.1 how to enable?

参考Documentations/acpi/aml-debugger.txt文档。
使用acpidbg工具需要kernel和userspace都支持
kernel
编译kernel时,需要设置
CONFIG_ACPI_DEBUGGER=y;
CONFIG_ACPI_DEBUGGER_USER=m
之后,编译kernel,得到acpi_dbg.ko;
userspace tools:acpidbg
$ cd tools
$ make acpi
生成的可执行程序在tools/acpi/power/acpi/acpidbg/acpidbg
$make install
将acpidbg安装到系统的执行路径中;

1.2 how to start userspace debugger

重启系统,使用acpidbg built-in的kernel启动

$ mount  -t debugfs none /sys/kernel/debug
$ modprobe acpi_dbg			
$ tools/acpi/power/acpi/acpidbg/acpidbg

之后,就可以进入到可交互的AML debugger环境中了,可以输入debugger command执行。

1.3 command supported

acpidbg 启动之后,可以输入help命令,查看acpidbg支持的command如下:

$ acpidbg
- help
Summary of AML Debugger Commands
Namespace Access:			//访问namespace的命令
  	Businfo                             			//Display system bus info
  	Disassemble <Method>                		//Disassemble a control method
  	Find <AcpiName> (? is wildcard)     	//Find ACPI name(s) with wildcards
  	Integrity                           				//Validate namespace integrity
  	Methods                             			//Display list of loaded control methods
  	Namespace [Object] [Depth]          		//Display loaded namespace tree/subtree
  	Notify <Object> <Value>             		//Send a notification on Object
Objects [ObjectType]                		//Display summary of all objects or just given type
Owner <OwnerId> [Depth]             		//Display loaded namespace by object owner
 	Paths                               Display full pathnames of namespace objects
  	Predefined                          Check all predefined names
  	Prefix [<Namepath>]                 Set or Get current execution prefix
  	References <Addr>                   Find all references to object at addr
  	Resources [DeviceName]              Display Device resources (no arg = all devices)
  	Set N <NamedObject> <Value>         Set value for named integer
  	Template <Object>                   Format/dump a Buffer/ResourceTemplate
  	Type <Object>                       Display object type

Control Method Execution:
  1) Evaluate <Namepath> [Arguments]     			//Evaluate object or control method
  2) Execute <Namepath> [Arguments]      			//Synonym for Evaluate
  3) Debug <Namepath> [Arguments]        			//Single-Step a control method

Miscellaneous:
  Allocations                         			//Display list of current memory allocations
  Dump <Address>|<Namepath> [Byte|Word|Dword|Qword]        
  Handlers 						//Info about global handlers
  Help [Command]                      		//This help screen or individual command
  History                             			//Display command history buffer
  Level <DebugLevel>] [console]       	//Get/Set debug level for file or console
  Locks                               			//Current status of internal mutexes
  Osi [Install|Remove <name>]         	//Display or modify global _OSI list
  Quit or Exit                        			//Exit this command
  Stats <SubCommand>                  	//Display namespace and memory statistics
     Allocations                      Display list of current memory allocations
     Memory                           Dump internal memory lists
     Misc                             Namespace search and mutex stats
     Objects                          Summary of namespace objects
     Sizes                            Sizes for each of the internal objects
     Stack                            Display CPU stack usage
     Tables                           Info about current ACPI table(s)
  Tables                              Display info about loaded ACPI tables
  ! <CommandNumber>                   Execute command from history buffer
  !!                                  Execute last command again

Method and Namespace Debugging:
  Trace <State> [<Namepath>] [Once]   Trace control method execution
     Enable                           Enable all messages
     Disable                          Disable tracing
     Method                           Enable method execution messages
     Opcode                           Enable opcode execution messages
  Test <TestName>                     Invoke a debug test
     Objects                          Read/write/compare all namespace data objects
     Predefined                       Validate all ACPI predefined names (_STA, etc.)
  Execute predefined                  Execute all predefined (public) methods

Control Method Single-Step Execution:
  Arguments (or Args)                 Display method arguments
  Breakpoint <AmlOffset>              Set an AML execution breakpoint
  Call                                Run to next control method invocation
  Go                                  Allow method to run to completion
  Information                         Display info about the current method
  Into                                Step into (not over) a method call
  List [# of Aml Opcodes]             Display method ASL statements
  Locals                              Display method local variables
  Results                             Display method result stack
  Set <A|L> <#> <Value>               Set method data (Arguments/Locals)
  Stop                                Terminate control method
  Tree                                Display control method calling tree
  <Enter>                             Single step next AML opcode (over calls)

在我的DELL机器上运行acpidbg的实例如下:

- namespace \_SB.PWRB
	ACPI Namespace (from PWRB (00000000570a7360) subtree):
	 0  _HID Integer      0000000086484fc8 01 = 000000000C0CD041
	 0  _UID Integer      000000008432cef4 01 = 00000000000000AA
 	 0  _STA Integer      00000000699fce6e 01 = 000000000000000B
	 0  _PRW Method       00000000467154ae 01 Args 0 Len 0009 Aml 00000000f0406bd4
	Namespace node count: 4
- execute \_SB.PWRB._STA		//execute _STA  method
	Evaluating \_SB.PWRB._STA
	Evaluation of \_SB.PWRB._STA returned object 000000005d4a43c1, external buffer length 18
	 [Integer] = 000000000000000B
- handlers:		//list handlers info
   Operation Region Handlers at the namespace root:
   		SystemMemory (00) : Default   (000000008e3627f4)
   		SystemIO (01) : Default   (00000000c26e80d4)
   		PCI_Config (02) : Default   (00000000df357aeb)
   		EmbeddedControl (03) : None
   		SMBus (04) : None
   		SystemCMOS (05) : None
   		PCIBARTarget (06) : None
   		IPMI (07) : None
   		GeneralPurposeIo (08) : None
   		GenericSerialBus (09) : None
   		DataTable (7E) : Default   (00000000b76a34e6)
   		FunctionalFixedHW (7F) : None
   Fixed Event Handlers:
   		PM_Timer (00) : None
   		GlobalLock (01) : User      (00000000c25964bf)
   		PowerButton (02) : User      (00000000d0879d19)
   		SleepButton (03) : None
   		RealTimeClock (04) : User      (00000000dbb9df24)
   Miscellaneous Global Handlers:
   		System Notifications : User      (0000000030e91327)
   		Device Notifications : User      (0000000061dc2179)
   		ACPI Table Events : User      (000000005fb8bcf3)
   		Control Method Exceptions : User      (0000000075b0eefe)
   		OSI Invocations : User      (0000000096a26980)
   Operation Region Handlers for specific devices:
   		PCI_Config (02) : Default (00000000df357aeb) Device Name: \_SB.PCI0 (0000000099b391d1)
   		SystemCMOS (05) : User (00000000787d56eb) Device Name: \_SB.PCI0.LPCB.RTC (00000000bece04ca)
   		GenericSerialBus (09) : User (00000000289e2622) Device Name: \_SB.PCI0.SBUS (0000000061eb7af3)
   		SystemIO (01) : User (0000000097b46fee) Device Name: \_SB.PCI0.SBUS (0000000061eb7af3)
   		GenericSerialBus (09) : User (00000000289e2622) Device Name: \_SB.PCI0.GFX0 (0000000099865817)

1.4 退出userspace debugger

ctrl+C、“quit”、“exit”都可以退出acpidbg;
之后$ rmmod acpi_dbg卸载模块即可。

二、ACPICA tools

acpidbg很好用,但是直到kernel 4.13 中才引入,那老版本的kernel怎么办呢?
别担心,在4.13 之前,虽然没有acpidbg,但是kernel提供了很多ACPICA tools,包括acpidump、acpiexec、acpixtract等工具,也能帮助我们对AML code进行调试。
下面我依然以执行PWRB device的_STA control method为例,介绍这些ACPICA tools的常用方法。

2.1 获取所有的ACPI tables

$ sudo acpidump > acpi.log

2.2 提取DSDT和SSDT信息

$acpixtract acpi.log

该命令会从acpi.log中摘取DSDT和所有的SSDT信息,生成dsdt.dat和ssdtN.dat文件。
DSDT 和SSDT是device configuration table,构成了整个ACPI namespace,包括所有的device node 信息。

2.3 反编译dsdt 和ssdt 文件

$ iasl -d *.dat

得到DSDT和SSDT相应的ASL 文件。

2.4 查看PWRB device在哪个table里

从ACPI spec中可以查到PWRB device的HID为“PNP0C0C”

	$grep "PNP0C0C" *.dsl 
		dsdt.dsl:            Name (_HID, EisaId ("PNP0C0C") /* Power Button Device */)  

之后,我们就可以使用vim/vi 打开dsdt.dsl文件,查看PWRB device的详细信息如下:

scope(\_SB) {
	Device (PWRB)  {
		Name (_HID, EisaId ("PNP0C0C") /* Power Button Device */)  
		Name (_UID, 0xAA)  
		Name (_STA, 0x0B)
		Method (_PRW, 0, NotSerialized)  {
			Return (GPRW (0x1B, 0x03))
		}
	}
}

2.5 通过acpiexec执行PWRB device的_STA method

acpiexec的使用和acpidbg类似,不过它需要先加载ACPI table,然后在仿真环境中执行AML code,即acpiexec的执行不会真正地操作hardware register或memory。

$acpiexec dsdt.dat 
	- execute \_SB.PWRB._STA
		Evaluating \_SB.PWRB._STA
		Evaluation of \_SB.PWRB._STA returned object 0x55bcd14acc90, external buffer length 18
		 [Integer] = 000000000000000B

	- execute \_SB.PWRB._PRW
		Evaluating \_SB.PWRB._PRW
		Evaluation of \_SB.PWRB._PRW returned object 0x55bcd14acc90, external buffer length 48
		[Package] Contains 2 Elements:
			[Integer] = 000000000000001B
			[Integer] = 0000000000000003

三、利用initrd修改ACPI table

前面两节介绍了如何使用acpidbg和ACPICA tools工具对AML code进行debug,我们接下来介绍如何使用这些工具配合initrd修改ACPI table。
参考文档Documentations/acpi/initrd_table_override.txt
如果kernel设置了CONFIG_ACPI_TABLE_UPGRADE=y,那就可以通过initrd修改或新增ACPI table。 除了RSDP、FACS table之外的其他ACPI table都可以用这种方式来修改。
接下来,我会通过一个实例,向DSDT table中新增一个IPMI device,来演示如何通过initrd来修改ACPI table。

3.1 获取当前的DSDT table

 $ mkdir /tmp 
 $ cd tmp 
 $ acpidump > acpidump
 $ acpixtract -a acpidump 	
 $  iasl -d dsdt.dat					//解析得到dsdt.dsl 文件

3.2 修改dsdt.dsl文件

在PCI0 scope中添加IPMI device

scope (_PCI0) {
	Device (MI00)	{
		Name(_HID,"IPI0001")
		Name(_IFT,0x01)
		Method (_STA, 0, NotSerialized) {
 			Return (0x0F)
 		}
 	}
}

3.3 增加DSDT table中的OEM version

before:
	DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000000)
after:
	DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000001)

我们加入新的DSDT table时,如果platform中已经有了一个DSDT table,会去比较二者的OEM version。若new table的OEM version比较大,则会替换原来的table,否则依然使用原来的table。因此,我们要把new DSDT table的OEM revision加大,这样才能用新的DSDT替换原来的table。

3.4 编译修改的dsdt.dsl

$ iasl -sa dsdt.dsl	

得到dsdt.aml 文件

3.5 将编译后的dsdt.aml文件加入到initrd中

将编译后的dsdt.dml加入到一个new uncompressed cpio archive中;
dsdt.aml 需要放到kernel/firmware/acpi/目录下
$ mkdir -p kernel/firmware/acpi
$ cp dsdt.aml kernel/firmware/acpi/
创建acpi_test_initrd 文件,放到/boot/目录下:
$ find kernel | cpio -H newc --create > /boot/acpi_test_initrd
新创建的acpi_test_initrd需要放在最前面,之前的压缩的cpio文件initrd.img-4.20.17放 在其后面
$ cat /boot/initrd.img-4.20.17 >> /boot/acpi_test_initrd

3.6 之后重启系统,使用新的initrd文件

重启时需要在grub中修改boot initrd:

before:
	initrd /boot/initrd.img-4.20.17
after:
	initrd /boot/acpi_test_initrd 

3.7 系统启动之后,查看是否IPMI device MI00是否已经加进去了。

启动acpidbg查看

$ modprobe acpi_dbg
$ acpidbg
- find MI00		
                  \_SB.PCI0.MI00 Device       000000001350acba 01
- execute _SB.PCI0.MI00._STA	
	Evaluating \_SB.PCI0.MI00._STA
	Evaluation of \_SB.PCI0.MI00._STA returned object 000000000c9bc94a, external buffer length 18
 		[Integer] = 000000000000000F

启动acpidbg之后,通过find命令在ACPI namespace查找MI00 device,能看到IPMI device已经成功地加入到ACPI table中了,而且我们还能够执行MI00 device的control method,如果有问题,可以使用acpidbg提供的命令进行调试并修改了。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值