DSDT
関連記事
DSDT (Differentiated System Description Table) は ACPI 規格の一部です。特定のシステムに対応して電源イベントに関する情報を提供します。ACPI テーブルはメーカーによってファームウェア上に用意されています。Linux で ACPI の機能が使えないというのはよくある問題です。例えば: ファンが稼働しない、フタを閉じたときに画面がオフにならない、など。これらの問題は DSDT が Windows しか考えずに作成されているのが原因で、インストール後にパッチをあてることができます。この記事では問題のある DSDT を解析・再構築して、デフォルトの DSDT をカーネルから置き換える方法を説明します。
基本的に DSDT テーブルは ACPI (電源管理) のイベントがあると実行されるコードです。
目次
はじめに
- ACPI 関連の問題はハードウェアメーカーによってリリースされたファームウェアのアップデートで修正される場合があります。無駄な努力をしなくてもいいように、まずはアップデートされたファームウェアをインストールすることが推奨されます。
- あなたの環境の基幹的なコードを操作することになります。変更を加えるときは万全を期すべきです。また、あらかじめディスクを複製したほうが良いでしょう。
- DSDT に修正をかける前に、以下のショートカットを試すことができます:
カーネルから Windows のバージョンを報告する
カーネルパラメータの acpi_os_name 変数を使ってください。例:
acpi_os_name="Microsoft Windows NT"
もしくは:
acpi_osi="!Windows2012"
上記の設定を GRUB の kernel 行に追加してください。
他にテストできる文字列:
- "Microsoft Windows XP"
- "Microsoft Windows 2000"
- "Microsoft Windows 2000.1"
- "Microsoft Windows ME: Millennium Edition"
- "Windows 2001"
- "Windows 2006"
- "Windows 2009"
- "Windows 2012"
- 上記の全てで駄目なら、"Linux" も試してください。
下の手順で DSDT を展開して .dsl ファイルを検索して、"Windows" を grep して何が表示されるか確認することもできます。
修正済みの DSDT を検索する
DSDT ファイルは本来 ACPI Source Language で書かれています (.asl/.dsl ファイル)。コンパイラを使うことで 'ACPI Machine Language' ファイル (.aml) やヘックステーブル (.hex) が生成できます。ファイルを Arch に組み入れるには、コンパイル済みの .aml ファイルを手に入れる必要があります。自分でコンパイルするか、あるいはインターネット上の誰かを自己責任で信頼するかです。インターネットからファイルをダウンロードした場合、大抵は圧縮済みの .asl ファイルになっています。ファイルを unzip してコンパイルしてください。インターネットからダウンロードすることの利点はコードの修正について自分で調べなくてもよいということです。
Arch ユーザーで同じノートパソコンを使っているというのは少数派のうちの少数派になります。同じ機種について情報がないか他のディストリや Linux のフォーラムも検索してみてください。技術に精通した人が大勢居るところなら同じ問題が見つかって、誰かが作った DSDT が発見できる、あるいはコンパイル済みのバージョンがあるかもしれません (自己責任で使ってください)。検索エンジンが最良のツールです。検索キーワードは短くしましょう: '機種名' + 'dsdt' で結果が得られるはずです。
自分で再コンパイルする
この取り組みにおける最良のリソースは、ACPI Spec ホームページ および Linux ACPI プロジェクト になります。これは、acpi.sourceforge.net で発生したアクティビティに優先します。 簡単に言うと、Intel の ASL コンパイラーを使用して、システムの DSDT テーブルをソースコードに変換し、エラーを特定して修正し、再コンパイルすることです。
コードを変更するには、acpica をインストールする必要があります。
システムの DSDT が Intel と Microsoft のコンパイラどちらを使ってコンパイルされたのか確認してください:
# dmesg | grep DSDT
ACPI: DSDT 00000000bf7e5000 0A35F (v02 Intel CALPELLA 06040000 INTL 20060912) ACPI: EC: Look up EC in DSDT
Microsoft のコンパイラが使われている場合、INTL という省略形が MSFT になります。DSDT を逆コンパイル・再コンパイルするときにエラーが発生したら、Google で検索したり ACPI の仕様にあたって修正してください。使用しているコンパイラのバージョンが違うためにエラーが起こる場合、起動時に ACPICA が対処することがあります。カーネルの ACPICA コンポーネントは DSDT をコンパイルするときに発生する些細なエラーに大抵は対処してくれます。システムがちゃんと動作しているのであれば、コンパイルエラーにあまり悩む必要はありません。
バイナリ ACPI テーブルを抽出します:
# cat /sys/firmware/acpi/tables/DSDT > dsdt.dat
ACPI テーブルを .dsl ファイルに逆アセンブルします:
$ iasl -d dsdt.dat
.dsl ファイルから 16 進 AML テーブル (C 言語) を作成してみます:
$ iasl -tc dsdt.dsl
16 進 AML テーブルの作成時に出力されたエラーを調べて修正します。例えば:
dsdt.dsl 6727: Name (_PLD, Buffer (0x10) Error 4105 - Invalid object type for reserved name ^ (found BUFFER, requires Package)
エラーが発生したファイルの行 6727 を修正します:
(_PLD, Package(1) {Buffer (0x10) { ... }})
OEM バージョンを上げます。そうしないと、カーネルは変更された ACPI テーブルを適用しません。たとえば、OEM バージョンを増やす前に、次のようにします:
DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000000)
OEM バージョンを上げた後:
DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000001)
すべてのエラーを修正し、OEM バージョンを上げた後、16 進 AML テーブルを再度作成します:
$ iasl -tc dsdt.dsl
C インクルードファイルをカーネルソースに挿入するためのオプション -ic
を試してみるとよいでしょう。エラーや警告が発生しなければ、問題なく実行できます。
修正済みのコードを使う
カスタム DSDT を使う方法は3つあります:
- ブートローダーによってロードされる CPIO アーカイブを作成する
- カーネルに組み入れてコンパイルする
- 起動時にロードする (サポートされていません)
CPIO アーカイブを使う
この方法ではカーネルを再コンパイルする必要がなく、カーネルをアップデートしても再度修正を行う必要がありません。
以下のカーネルコンフィグを有効にしてください (標準の linux パッケージではデフォルトで有効です):
ACPI_TABLE_UPGRADE=y
(Linux カーネル 4.6 以上)CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
(Linux カーネル 4.5 以下)
詳しくは [1] を見てください。
まず、以下のフォルダを作成:
$ mkdir -p kernel/firmware/acpi
修正した ACPI テーブルを作成した kernel/firmware/acpi
フォルダにコピー。例:
$ cp dsdt.aml ssdt1.aml kernel/firmware/acpi
新しく作成した kernel/
フォルダの中で、以下のコマンドを実行:
$ find kernel | cpio -H newc --create > acpi_override
上記のコマンドで修正済みの ACPI テーブルを含む CPIO アーカイブが作成されます。アーカイブを boot
ディレクトリにコピーしてください:
# cp acpi_override /boot
最後に、ブートローダーを設定して CPIO アーカイブをロードします。例えば Systemd-boot を使用している場合、/boot/loader/entries/arch.conf
は以下のようになります:
title Arch Linux linux /vmlinuz-linux initrd /acpi_override initrd /initramfs-linux.img options root=PARTUUID=ec9d5998-a9db-4bd8-8ea0-35a45df04701 resume=PARTUUID=58d0aa86-d39b-4fe1-81cf-45e7add275a0 ...
設定後は再起動を行ってから結果を確認してください。
カーネルにコンパイル
カスタムカーネルをコンパイルする方法をよく読んでください。一番簡単なのは"伝統的な"方法です。DSDT をコンパイルした後、iasl は2つのファイルを生成します: dsdt.hex
と dsdt.aml
。
menuconfig
を使う:
- "Device Drivers -> Generic Driver Options" の "Select only drivers that don't need compile-time external firmware" を無効化してください。
- "Power management and ACPI options -> ACPI (Advanced Configuration and Power Interface) Support" にある "Include Custom DSDT" を有効化して、修正済みの DSDT ファイル (
dsdt.aml
ではなくdsdt.hex
) の絶対パスを指定してください。
起動時にロード
Arch の標準カーネルはカスタム DSDT の使用をサポートしているため、まずは iasl でコンパイルした .aml ファイルを /boot/dsdt.aml
にコピーしてください。
ブートローダーで DSDT を置き換えるため、カスタム DSDT テーブルをブートローダーのイメージに組み込む必要があります。以下を /etc/grub.d/01_acpi
にコピー (GRUB_CUSTOM_ACPI
は使用する .aml ファイルのパスに置き換えてください):
#!/bin/sh set -e # Uncomment to load custom ACPI table GRUB_CUSTOM_ACPI="/boot/dsdt.aml" # DON'T MODIFY ANYTHING BELOW THIS LINE! prefix=/usr exec_prefix=${prefix} libdir=${exec_prefix}/lib . /usr/share/grub/grub-mkconfig_lib #. ${libdir}/grub/grub-mkconfig_lib # Load custom ACPI table if [ x${GRUB_CUSTOM_ACPI} != x ] && [ -f ${GRUB_CUSTOM_ACPI} ] \ && is_path_readable_by_grub ${GRUB_CUSTOM_ACPI}; then echo "Found custom ACPI table: ${GRUB_CUSTOM_ACPI}" >&2 prepare_grub_to_access_device `${grub_probe} --target=device ${GRUB_CUSTOM_ACPI}` | sed -e "s/^/ /" cat << EOF acpi (\$root)`make_system_path_relative_to_its_root ${GRUB_CUSTOM_ACPI}` EOF fi
ファイルに実行可能権限を付与してください、そうしないと grub-mkconfig によって無視されます:
# chmod +x /etc/grub.d/01_acpi
これで GRUB は DSDT を core.img に組み込みます。
次に新しいブートイメージが必要です。GRUB を使っている場合、以下を実行:
# grub-mkconfig -o /boot/grub/grub.cfg
最後に、initrd を再作成してください:
# mkinitcpio -p linux
再起動すれば変更が適用されます。
新しい DSDT が使われているかどうか確認するには # cat /sys/firmware/acpi/tables/DSDT > dsdt.dat
でテーブルを読み込んで iasl -d dsdt.dat
で逆コンパイルしてください。
上書きされたことを確認
dmesg | grep DSDT
を実行。- 上書きされたことを示す文字列を探して下さい。例:
[ 0.000000] ACPI: Override [DSDT- A M I], this is unsafe: tainting kernel [ 0.000000] ACPI: DSDT 00000000be9b1190 Logical table override, new table: ffffffff81865af0 [ 0.000000] ACPI: DSDT ffffffff81865af0 0BBA3 (v02 ALASKA A M I 000000F3 INTL 20130517)