ACPI ドライバーインターフェース

こんにちは、K里です。

今回は ACPI ドライバーインターフェースについてお話したいと思います。ACPI (Advanced Configuration and Power Interface) は、OS 主導の電源管理制御を実現するために既定された OS - BIOS 間のインターフェース仕様になります。ACPI の電源制御は、OS がいつ何をやるかを決めるのに対し、ACPI BIOS は各種 ACPI テーブル (RSDP に始まり FACP、DSDT など)、AML などをサポートし、具体的な制御方法を提供します。

カーネルドライバーから ACPI BIOS に関する情報の取得あるいは制御を行う手法として、ACPI Control Method を定義しており、AML (ACPI Machine Language) で記述されます。カーネルドライバーは、ACPI Control Method が読み込まれるデバイスオブジェクト (PDO) の名前空間内で以下の IOCTL を使用してこれらの Method を実行することが可能です。これには、Child Object で定義される Control Method も含まれます。

l IOCTL_ACPI_EVAL_METHOD
l IOCTL_ACPI_ASYNC_EVAL_METHOD
l IOCTL_ACPI_EVAL_METHOD_EX
l IOCTL_ACPI_ASYNC_EVAL_METHOD_EX

例えば、アプリケーションから BIOS で定義される情報 (ソフトウェアのバージョンやバッテリーなど各種ハードウェア情報) を参照したい場合には WMI などを使用して情報を取得できる可能性がありますが、BIOS 固有の情報を定義し、その情報を参照もしくは制御したい場合には、標準 API では実現が困難なため上記 IOCTL を使用して ACPI Control Method の実行することで原理的に制御可能です。主な処理概要は以下のようになります。

1. IOCTL を実行するドライバー (以下ドライバーと略記) をインストールするためのデバイスを実装します
2. 1 のデバイス内でドライバーから制御が必要な Control Method を実装します
3. 1 のデバイスに対してドライバーをインストールします
4. アプリケーションから DeviceIoControl を使用してドライバーに Control Method の実行を通知します
5. ドライバーで、IOCTL を使用し、2 の Control Method を実行します
6. 5 の Control Method の実行結果をアプリケーションに通知します

また、以下はデバッグ向けの情報となりますが、ACPI.sys を Checked Build 版モジュールに置き換え、!amli set コマンドより AMLTrace と AMLDebugSpew を ON にすることで Control Method の実行結果をデバッガ上に出力することが可能です。

1: kd> !amli set traceon

1: kd> !amli set spewon

 

1: kd> !amli set

AMLTrace =on

AMLDebugSpew =on

LoadDDBBreak =off

ErrorBreak =off

VerboseMode =off

LogEvent =on

LogSize =204

 

1: kd> g

 

AMLI: 878D3840: \_SB.CP00._STA()

 

AMLI: 878D3840: \_SB.CP01._STA()

 

AMLI: 878D3840: \_SB.PCI0.ISA.SIO.LPTB._STA()

 

AMLI: 8798FD48: \_SB.PCI0.ISA.SIO.FDC._STA()

 

ffffffff8606f1c5: {

ffffffff8606f1c5: | Return(CSTA(0x0)

ffffffff8606f259: | {

ffffffff8606f259: | | If(LEqual(0x0,Arg0=0x0)=0xffffffff)

ffffffff8606f25f: | | {

ffffffff8606f25f: | | | Return(0xf)

ffffffff8606f262: | | }

ffffffff8606f262: | })

ffffffff8606f1cc: }

ffffffff861c417d: {

ffffffff861c417d: | Return(CSTA(CPID=0x1)

ffffffff8606f259: | {

ffffffff8606f259: | | If(LEqual(0x0,Arg0=0x1)=0x0)

ffffffff8606f262: | | Add(Add(ShiftLeft(ShiftRight(Arg0=0x1,0x5,)=0x0,0x2,)=0x0,0x40,)=0x40,ECFG=0xdbc00000,Local1)=0xdbc00040

ffffffff8606f275: | | And(Arg0=0x1,0x1f,Local3)=0x1

ffffffff8606f27a: | | OperationRegion(CREG,0x0,Local1=0xdbc00040,0x10)

ffffffff8606f284: | | Field(CREG,0x3)

ffffffff8606f28c: | | {

ffffffff8606f291: | | | Z000,32

ffffffff8606f291: | | }

ffffffff8606f291: | | Store(Z000=0x3,Local0)=0x3

ffffffff8606f297: | | If(And(ShiftLeft(0x1,Local3=0x1,)=0x2,Local0=0x3,)=0x2)

ffffffff8606f2a1: | | {

ffffffff8606f2a1: | | | Return(0xf)

ffffffff8606f2a4: | | }

ffffffff8606f2a4: | })

ffffffff861c4186: }

  :

  (snip)

  :

 

今回の場合、カーネルドライバーの作成の他 BIOS 側の変更も必要になりますが、ACPI IOCTL を使用することで OS に依存せずにアプリケーション – BIOS 間の制御が可能と思われますので参考になりましたら幸いです。

 

ではまた。

 

Appendix

Advanced Configuration & Power Interface

https://www.acpi.info/

Evaluating ACPI Control Methods

https://msdn.microsoft.com/en-us/library/ff536139(VS.85).aspx

ACPI Debugging

https://msdn.microsoft.com/en-us/library/ff537808(VS.85).aspx