Linuxを載せたノートPCの電池残量が表示されない
はじめに
表題の通り。
貰いものの古いノートPCが、Windows 11に対応していないことが判明し、中身を消去してLinuxを入れ直すことにした。ところが、いざ起動してみると、電池残量が表示されない。
さすがに不便なので、頑張って調査&修理する。
環境
PC:NEC VersaPro UltraLite タイプVG
型番:PC-VK19SGZDF
OS:EndeavourOS
ビルドID:2025.03.19
2012年10月ごろに発売された、ビジネス向けPCとのこと。
ビジネス向けPCを個人が持っていて大丈夫なのかと思ったが、個人でも購入できるらしい。
現状の確認
KInfoCenter
KInfoCenterでバッテリーの情報を確認するも、そもそも表示されない。

UPower
バッテリーを表示するコマンドラインツールupowerはどうだろうか。
$ upower
$
・・・?
$ upower --dump
Device: /org/freedesktop/UPower/devices/line_power_ADP1
native-path: ADP1
power supply: yes
updated: xxxx年xx月xx日 xx時xx分xx秒 (xx seconds ago)
has history: no
has statistics: no
line-power
warning-level: none
online: no
icon-name: 'ac-adapter-symbolic'
Device: /org/freedesktop/UPower/devices/DisplayDevice
power supply: no
updated: xxxx年xx月xx日 xx時xx分xx秒 (xx seconds ago)
has history: no
has statistics: no
unknown
warning-level: none
percentage: 0%
icon-name: 'battery-missing-symbolic'
ADP1はACアダプターのことだそうだ。Display Deviceは分からないが、バッテリーっぽくはない。
acpiコマンド
acpiというコマンドでバッテリー情報を読み出せるらしい。
参考:Linux ノートPCのバッテリー状態を確認するコマンド acpi
$ acpi -V
Adapter 0: off-line
なんとなく、ダメそう。
ところで、acpiとはなんだろう?
ACPI(読:エーシーピーアイ)とは
パソコンさんの電源管理に関する規格のひとつ
であり
電源に関するあれやこれやを主にOSで制御するやつ
です。
OSから電源を管理するためのインターフェースを定めた規格、といったところか。
そもそもACPIは、Intel,Microsoft,東芝,ヒューレットパッカード,フェニックステクノロジーズによって共同で開発された、オープンな規格だそうだ。初版は1996年と、そんなに古いわけではないらしい。
もっとも、2013年からはUEFI Forumが管理を引き継いだようで、最新版の6.6が2025年5月に公開されている。
ACPI Specification Version 6.6
原因の解明
とにかく、バッテリー残量を表示できない、ということは分かった。では、それは何故か?
・・・そもそも、バッテリー残量を取得する仕組みすら知らないことに気付いた。OSあたりがよしなにやってくれている、くらいにしか考えたことがなかったが、今回は「よしなに」の部分を掘り下げなければならないのだ。
こういうときは、ArchWikiを見に行く。
バッテリー状態を取得する方法は複数あります。
古典的な方法は ACPI インターフェイスを使ってバッテリーレベルを定期的に取得するデーモンを使う方法です。
システムによっては、バッテリーを 1% 放電するたびに udev にイベントが送られます。udev ルールを使ってこのイベントを他のアクションに繋げることができます。
DSDTをどうにかする
というわけで、原因はDSDTの設定だと考えられるので、これをどうにかしたい。ArchWikiを見てみると、いくつか選択肢があるようだ。
方法1:カーネルパラメータにWindowsのバージョンを渡す
DSDTには簡単なプログラムを書くことができるのだが、使用するOSによってパラメータを変更している場合、Windows用の分岐しかなく、必要なパラメータを取得できないことがあるらしい。
そこで、使用しているOSをWindowsだと虚偽申告することで、Windows用のパラメータを使用できるようにするそうだ。
カーネルパラメータの設定は、ブートローダーのブート選択メニューでブートエントリーを編集することで行った。
ただ、この方法では上手くいかなかった。後で判明するが、分岐の問題ではなかったようだ。
方法2:先人が修正したDSDTを使う
頑張って調べたが見つからなかった。
方法3:自力でDSDTを修正する
DSDTを抽出&修正&適用する。
DSDTを抽出
ArchWikiに従って作業するだけなので省略。
抽出したDSDTを修正
同上。
詰まった点としては、dslテーブルから16進AMLテーブルを生成するときに発生するエラーの解消が、かなり大変だった。以下、発生したエラーとその修正方法をメモしておく。
その1
dsdt.dsl 3256: IO (Decode16,
Error 6090 - ^ Min/Max/Length/Gran are all zero, but no resource tag
dsdt.dsl 3268: IO (Decode16,
Error 6090 - ^ Min/Max/Length/Gran are all zero, but no resource tag
Length = Range Maximum - Range minimum + 1という公式があるらしい。Range maximumもRange minimumも共に0x00なので、Lengthを0x00から0x01にする。
参考:Native DSDT gives many "Address Min is greater than Address Max" errors
その2
dsdt.dsl 4992: PLD_Revision = 0x1,
Error 6105 - Invalid object type for reserved name ^ (_PLD: found Buffer, Package required)
このPLD_RevisionはToPLDというメソッド?の引数なのだが、これはPackage(){}という構文の中に入れないといけないらしい。というわけで、Package(){ ToPLD ( PLD_Revision = 0x1 , ... ) }とする。
参考:Issue with modifying DSDT on ASUS Rampage X79 Black Edition
その3
dsdt.dsl 10886: Name (_HID, "pnp0c14") // _HID: Hardware ID
Error 6136 - Non-hex letters must be upper case ^ (pnp0c14)
大文字にしろや、ということのようだ。pnp0c14をPNP0C14に変更する。
これで完成。OEMバージョンの変更を忘れずに(1敗)