获取ACPI TABLE的方法
1. 首先要安装acpidump和iasl命令。
$ sudo apt-get install acpidump
$ sudo apt-get install iasl
$ sudo apt-get install pmtools
有的机器上需要安装pmtools才可以。
2. 导出ACPI的数据。
$ sudo cat /proc/acpi/dsdt > dstd.dat
或者
$ sudo cat /sys/firmware/acpi/tables/DSDT > /tmp/dsdt.dat
如果找不到该文件可以使用下面的命令:
$ sudo acpidump > acpi.dat
3. 分离各表格数据,会生成多个数据文件。
$ acpixtract -a acpi.dat
Acpi table [DSDT] - 41555 bytes written to DSDT.dat
Acpi table [FACS] - 64 bytes written to FACS.dat
Acpi table [FACP] - 116 bytes written to FACP.dat
Acpi table [APIC] - 132 bytes written to APIC.dat
Acpi table [ASF!] - 99 bytes written to ASF!.dat
Acpi table [MCFG] - 60 bytes written to MCFG.dat
Acpi table [TCPA] - 50 bytes written to TCPA.dat
Acpi table [SLIC] - 374 bytes written to SLIC.dat
Acpi table [HPET] - 56 bytes written to HPET.dat
Acpi table [DMAR] - 456 bytes written to DMAR.dat
Acpi table [RSDT] - 68 bytes written to RSDT.dat
Acpi table [RSDP] - 20 bytes written to RSDP.dat
4. 反汇编DSDT.dat,
$ iasl -d DSDT.dat
Intel ACPI Component Architecture
AML Disassembler version 20100528 [Oct 15 2010]
Copyright (c) 2000 - 2010 Intel Corporation
Supports ACPI Specification Revision 4.0a
Loading Acpi table from file DSDT.dat
Acpi table [DSDT] successfully installed and loaded
Pass 1 parse of [DSDT]
Pass 2 parse of [DSDT]
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)
...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Parsing completed
Disassembly completed, written to "DSDT.dsl"
5. 根据需要修改DSDT.dsl文件,然后重新编译该文件,会生成DSDT.aml和DSDT.hex两个文件。
$ iasl -tc dsdt.dsl
Intel ACPI Component Architecture
ASL Optimizing Compiler version 20100528 [Oct 15 2010]
Copyright (c) 2000 - 2010 Intel Corporation
Supports ACPI Specification Revision 4.0a
......................................................
ASL Input: DSDT.dsl - 8762 lines, 320704 bytes, 3778 keywords
AML Output: DSDT.aml - 39328 bytes, 780 named objects, 2998 executable opcodes
Compilation complete. 0 Errors, 41 Warnings, 0 Remarks, 988 Optimizations
6. 更新DSDT的方法。
其一(没有测试过,不知道能否成功):
使用新的dsdt.aml代替BIOS中的版本:
cp /boot/initrd.img-2.6.20-16-generic /boot/initrd.img-2.6.20-16-generic-bak
sudo cp dsdt.aml /etc/initramfs-tools/DSDT.aml
sudo update-initramfs -u -k all
其二(需要安装acpiexec,为找到):
iasl -sa DSDT.dsl # e.g. recompile a modified, disassembled DSDT for
initramfs inclusion (see later)
acpiexec DSDT.dat # parse, interpret and load a DSDT in userspace
其三:
这个方法需要重新编译内核。
首先将DSDT.hex文件复制到内核源码的include目录下。
$ cp DSDT.hex $SRC/include/
然后修改内核配置文件.config
CONFIG_STANDALONE=n
CONFIG_ACPI_CUSTOM_DSDT=y
CONFIG_ACPI_CUSTOM_DSDT_FILE="DSDT.hex"
重新编译,更新内核,然后启动,可以在dmesg中看到
[ 0.000000] ACPI: Override [DSDT- CDV-TPT], this is unsafe: tainting kernel
[ 0.000000] Disabling lock debugging due to kernel taint
[ 0.000000] ACPI: DSDT @ 0x7f378010 Table override, replaced with:
[ 0.000000] ACPI: DSDT c0f0f140 0703F (v02 Intel CDV-TPT 00000000 INTL 20091214)
就说明DSDT已经被替换成修改过的了。
7. 在DSDT中添加LOG。
首先应该打开CONFIG_ACPI_DEBUG=y。
acpi.debug_level= ACPI_LV_DEBUG_OBJECT,
acpi.debug_layer= ACPI_TABLES | ACPI_NAMESPACE,
使用将想要的变量或者字符串赋值给Debug即可。
(Store (AAAA, Debug)
下面附上原文:
Dumping ACPI tables using acpidump and acpixtract
Most of the time when I'm looking at BIOS issues I just look at the disassembled ACPI DSDT using the following runes:
$ sudo cat /proc/acpi/dsdt > dstd.dat
$ iasl -d dstd.dat
..and look at the disassembly in dstd.dsl
Some BIOS bugs need a little more examination, and that's where I use acpidump + acpixtract. The simplest way to dump all the ACPI tables is as follows:
$ sudo acpidump > acpi.dat
$ acpixtract -a acpi.dat
Acpi table [DSDT] - 24564 bytes written to DSDT.dat
Acpi table [FACS] - 64 bytes written to FACS.dat
Acpi table [FACP] - 244 bytes written to FACP1.dat
Acpi table [APIC] - 104 bytes written to APIC1.dat
Acpi table [HPET] - 56 bytes written to HPET.dat
Acpi table [MCFG] - 60 bytes written to MCFG.dat
Acpi table [TCPA] - 50 bytes written to TCPA.dat
Acpi table [TMOR] - 38 bytes written to TMOR.dat
Acpi table [SLIC] - 374 bytes written to SLIC.dat
Acpi table [APIC] - 104 bytes written to APIC2.dat
Acpi table [BOOT] - 40 bytes written to BOOT.dat
Acpi table [SSDT] - 685 bytes written to SSDT1.dat
Acpi table [SSDT] - 163 bytes written to SSDT2.dat
Acpi table [SSDT] - 607 bytes written to SSDT3.dat
Acpi table [SSDT] - 166 bytes written to SSDT4.dat
Acpi table [SSDT] - 1254 bytes written to SSDT5.dat
Acpi table [XSDT] - 148 bytes written to XSDT.dat
Acpi table [FACP] - 116 bytes written to FACP2.dat
Acpi table [RSDT] - 88 bytes written to RSDT.dat
Acpi table [RSDP] - 36 bytes written to RSDP.dat
..this dumps out all the tables into files.
One can the disassemble the required file using iasl, e.g.:
$ iasl -d APIC1.dat
or decode the table using madt:
$ madt < ACPI1.dsl
ACPI: APIC (v001 INTEL CRESTLNE 0x06040000 LOHR 0x0000005a) @ 0x(nil)
ACPI: LAPIC (acpi_id[0x00] lapic_id[0x00] enabled)
ACPI: LAPIC (acpi_id[0x01] lapic_id[0x01] enabled)
ACPI: IOAPIC (id[0x01] address[0xfec00000] global_irq_base[0x0])
ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
ACPI: LAPIC_NMI (acpi_id[0x00] high edge lint[0x1])
ACPI: LAPIC_NMI (acpi_id[0x01] high edge lint[0x1])
Length 104 OK
Checksum OK
Or to just get one particular table, I use:
$ sudo acpidump -t SSDT > SSDT.dat
$ acpixtract -a SSDT.dat
$ iasl -d SSDT.dat
Intel ACPI Component Architecture
AML Disassembler version 20090521 [Jun 30 2009]
Copyright (C) 2000 - 2009 Intel Corporation
Supports ACPI Specification Revision 3.0a
Loading Acpi table from file SSDT.dat
Acpi table [SSDT] successfully installed and loaded
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)
.........
Parsing completed
Disassembly completed, written to "SSDT.dsl"
Armed with a copy of the ACPI spec, one can then start digging into why there are weird Linux/BIOS interactions occurring.
How to Build a custom DSDT into the kernel
Get original DSDT:
# cp /proc/acpi/dsdt DSDT
or
# acpidump > acpidump.out
$ acpixtract DSDT acpidump > DSDT.dat
Disassemble it
$ iasl -d DSDT.dat
Make your changes:
$ vi DSDT.dsl
Build it:
$ iasl -tc DSDT.dsl
Put it where the kernel build can include it:
$ cp DSDT.hex $SRC/include/
Add this to the kernel .config:
CONFIG_STANDALONE=n
CONFIG_ACPI_CUSTOM_DSDT=y
CONFIG_ACPI_CUSTOM_DSDT_FILE="DSDT.hex"
Make the kernel and off you go!
You should see in dmesg:
Table [DSDT] replaced by host OS
Linux ACPI Custom Control Method How To
Written by Zhang Rui <
[email protected]>
Linux supports customizing ACPI control methods at runtime.
Users can use this to
1. override an existing method which may not work correctly, or just for debugging purposes.
2. insert a completely new method in order to create a missing method such as _OFF, _ON, _STA, _INI, etc. For these cases, it is far simpler to dynamically install a single control method rather than override the entire DSDT, because kernel rebuild/reboot is not needed and test result can be got in minutes.
Note: Only ACPI METHOD can be overridden, any other object types like "Device", "OperationRegion", are not recognized. Note: The same ACPI control method can be overridden for many times, and it's always the latest one that used by Linux/kernel. Note: To get the ACPI debug object output (Store (AAAA, Debug)), please run "echo 1 > /sys/module/acpi/parameters/aml_debug_output".
1. override an existing method a) get the ACPI table via ACPI sysfs I/F. e.g. to get the DSDT, just run "cat /sys/firmware/acpi/tables/DSDT > /tmp/dsdt.dat" b) disassemble the table by running "iasl -d dsdt.dat".
c) rewrite the ASL code of the method and save it in a new file,
d) package the new file (psr.asl) to an ACPI table format. Here is an example of a customized \_SB._AC._PSR method,
DefinitionBlock ("", "SSDT", 1, "", "", 0x20080715)
{ External (ACON)
Method (\_SB_.AC._PSR, 0, NotSerialized)
{ Store ("In AC _PSR", Debug)
Return (ACON) } }
Note that the full pathname of the method in ACPI namespace
should be used.
And remember to use "External" to declare external objects. e) assemble the file to generate the AML code of the method. e.g. "iasl psr.asl" (psr.aml is generated as a result) f) mount debugfs by "mount -t debugfs none /sys/kernel/debug"
g) override the old method via the debugfs by running "cat /tmp/psr.aml > /sys/kernel/debug/acpi/custom_method"
2. insert a new method This is easier than overriding an existing method.
We just need to create the ASL code of the method we want to
insert and then follow the step c) ~ g) in section 1.
3. undo your changes The "undo" operation is not supported for a new inserted method
right now, i.e. we can not remove a method currently.
For an overrided method, in order to undo your changes, please
save a copy of the method original ASL code in step c) section 1,
and redo step c) ~ g) to override the method with the original one.
Note: We can use a kernel with multiple custom ACPI method running, But each individual write to debugfs can implement a SINGLE
method override. i.e. if we want to insert/override multiple
ACPI methods, we need to redo step c) ~ g) for multiple times.
Note: Be aware that root can mis-use this driver to modify arbitrary memory and gain additional rights, if root's privileges got
restricted (for example if root is not allowed to load additional modules after boot).
/sys/module/acpi/parameters/:
trace_method_name The AML method name that the user wants to trace
trace_debug_layer The temporary debug_layer used when tracing the method.
Using 0xffffffff by default if it is 0.
trace_debug_level The temporary debug_level used when tracing the method.
Using 0x00ffffff by default if it is 0.
trace_state The status of the tracing feature.
"enabled" means this feature is enabled
and the AML method is traced every time it's executed.
"1" means this feature is enabled and the AML method
will only be traced during the next execution.
"disabled" means this feature is disabled.
Users can enable/disable this debug tracing feature by
"echo string > /sys/module/acpi/parameters/trace_state".
"string" should be one of "enable", "disable" and "1".
ACPI Debug Output
The ACPI CA, the Linux ACPI core, and some ACPI drivers can generate debug output. This document describes how to use this facility.
Compile-time configuration
--------------------------
ACPI debug output is globally enabled by CONFIG_ACPI_DEBUG. If this config option is turned off, the debug messages are not even built into the kernel.
Boot- and run-time configuration
--------------------------------
When CONFIG_ACPI_DEBUG=y, you can select the component and level of messages you're interested in. At boot-time, use the acpi.debug_layer and acpi.debug_level kernel command line options. After boot, you can use the debug_layer and debug_level files in /sys/module/acpi/parameters/ to control the debug messages.
debug_layer (component)
-----------------------
The "debug_layer" is a mask that selects components of interest, e.g., a specific driver or part of the ACPI interpreter. To build the debug_layer bitmask, look for the "#define _COMPONENT" in an ACPI source file.
You can set the debug_layer mask at boot-time using the acpi.debug_layer command line argument, and you can change it after boot by writing values to /sys/module/acpi/parameters/debug_layer.
The possible components are defined in include/acpi/acoutput.h and include/acpi/acpi_drivers.h. Reading /sys/module/acpi/parameters/debug_layer shows the supported mask values, currently these:
ACPI_UTILITIES 0x00000001
ACPI_HARDWARE 0x00000002
ACPI_EVENTS 0x00000004
ACPI_TABLES 0x00000008
ACPI_NAMESPACE 0x00000010
ACPI_PARSER 0x00000020
ACPI_DISPATCHER 0x00000040
ACPI_EXECUTER 0x00000080
ACPI_RESOURCES 0x00000100
ACPI_CA_DEBUGGER 0x00000200
ACPI_OS_SERVICES 0x00000400
ACPI_CA_DISASSEMBLER 0x00000800
ACPI_COMPILER 0x00001000
ACPI_TOOLS 0x00002000
ACPI_BUS_COMPONENT 0x00010000
ACPI_AC_COMPONENT 0x00020000
ACPI_BATTERY_COMPONENT 0x00040000
ACPI_BUTTON_COMPONENT 0x00080000
ACPI_SBS_COMPONENT 0x00100000
ACPI_FAN_COMPONENT 0x00200000
ACPI_PCI_COMPONENT 0x00400000
ACPI_POWER_COMPONENT 0x00800000
ACPI_CONTAINER_COMPONENT 0x01000000
ACPI_SYSTEM_COMPONENT 0x02000000
ACPI_THERMAL_COMPONENT 0x04000000 ACPI_MEMORY_DEVICE_COMPONENT 0x08000000
ACPI_VIDEO_COMPONENT 0x10000000
ACPI_PROCESSOR_COMPONENT 0x20000000
debug_level
-----------
The "debug_level" is a mask that selects different types of messages, e.g., those related to initialization, method execution, informational messages, etc. To build debug_level, look at the level specified in an ACPI_DEBUG_PRINT() statement.
The ACPI interpreter uses several different levels, but the Linux ACPI core and ACPI drivers generally only use ACPI_LV_INFO.
You can set the debug_level mask at boot-time using the acpi.debug_level command line argument, and you can change it after boot by writing values to /sys/module/acpi/parameters/debug_level.
The possible levels are defined in include/acpi/acoutput.h. Reading /sys/module/acpi/parameters/debug_level shows the supported mask values, currently these:
ACPI_LV_INIT 0x00000001
ACPI_LV_DEBUG_OBJECT 0x00000002
ACPI_LV_INFO 0x00000004
ACPI_LV_INIT_NAMES 0x00000020
ACPI_LV_PARSE 0x00000040
ACPI_LV_LOAD 0x00000080
ACPI_LV_DISPATCH 0x00000100
ACPI_LV_EXEC 0x00000200
ACPI_LV_NAMES 0x00000400
ACPI_LV_OPREGION 0x00000800
ACPI_LV_BFIELD 0x00001000
ACPI_LV_TABLES 0x00002000
ACPI_LV_VALUES 0x00004000
ACPI_LV_OBJECTS 0x00008000
ACPI_LV_RESOURCES 0x00010000
ACPI_LV_USER_REQUESTS 0x00020000
ACPI_LV_PACKAGE 0x00040000
ACPI_LV_ALLOCATIONS 0x00100000
ACPI_LV_FUNCTIONS 0x00200000
ACPI_LV_OPTIMIZATIONS 0x00400000
ACPI_LV_MUTEX 0x01000000
ACPI_LV_THREADS 0x02000000
ACPI_LV_IO 0x04000000
ACPI_LV_INTERRUPTS 0x08000000
ACPI_LV_AML_DISASSEMBLE 0x10000000
ACPI_LV_VERBOSE_INFO 0x20000000
ACPI_LV_FULL_TABLES 0x40000000
ACPI_LV_EVENTS 0x80000000
Examples
--------
For example, drivers/acpi/bus.c contains this:
#define _COMPONENT ACPI_BUS_COMPONENT
...
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
To turn on this message, set the ACPI_BUS_COMPONENT bit in acpi.debug_layer and the ACPI_LV_INFO bit in acpi.debug_level. (The ACPI_DEBUG_PRINT statement uses ACPI_DB_INFO, which is macro based on the ACPI_LV_INFO definition.)
Enable all AML "Debug" output (stores to the Debug object while interpreting AML) during boot:
acpi.debug_layer=0xffffffff acpi.debug_level=0x2
Enable PCI and PCI interrupt routing debug messages:
acpi.debug_layer=0x400000 acpi.debug_level=0x4
Enable all ACPI hardware-related messages:
acpi.debug_layer=0x2 acpi.debug_level=0xffffffff
Enable all ACPI_DB_INFO messages after boot:
# echo 0x4 > /sys/module/acpi/parameters/debug_level
Show all valid component values:
# cat /sys/module/acpi/parameters/debug_layer