Open4

Linuxを載せたノートPCの電池残量が表示されない

AsethAseth

はじめに

表題の通り。
貰いものの古いノートPCが、Windows 11に対応していないことが判明し、中身を消去してLinuxを入れ直すことにした。ところが、いざ起動してみると、電池残量が表示されない。
さすがに不便なので、頑張って調査&修理する。

環境

PC:NEC VersaPro UltraLite タイプVG
型番:PC-VK19SGZDF
OS:EndeavourOS
ビルドID:2025.03.19

2012年10月ごろに発売された、ビジネス向けPCとのこと。
ビジネス向けPCを個人が持っていて大丈夫なのかと思ったが、個人でも購入できるらしい。

AsethAseth

現状の確認

KInfoCenter

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で制御するやつ
です。

引用:ACPIとは | わわわIT用語辞典

OSから電源を管理するためのインターフェースを定めた規格、といったところか。

そもそもACPIは、Intel,Microsoft,東芝,ヒューレットパッカード,フェニックステクノロジーズによって共同で開発された、オープンな規格だそうだ。初版は1996年と、そんなに古いわけではないらしい。
もっとも、2013年からはUEFI Forumが管理を引き継いだようで、最新版の6.6が2025年5月に公開されている。
ACPI Specification Version 6.6

AsethAseth

原因の解明

とにかく、バッテリー残量を表示できない、ということは分かった。では、それは何故か?

・・・そもそも、バッテリー残量を取得する仕組みすら知らないことに気付いた。OSあたりがよしなにやってくれている、くらいにしか考えたことがなかったが、今回は「よしなに」の部分を掘り下げなければならないのだ。
こういうときは、ArchWikiを見に行く。

バッテリー状態を取得する方法は複数あります。
古典的な方法は ACPI インターフェイスを使ってバッテリーレベルを定期的に取得するデーモンを使う方法です。
システムによっては、バッテリーを 1% 放電するたびに udev にイベントが送られます。udev ルールを使ってこのイベントを他のアクションに繋げることができます。

引用:ノートパソコン - ArchWiki

AsethAseth

DSDTをどうにかする

というわけで、原因はDSDTの設定だと考えられるので、これをどうにかしたい。ArchWikiを見てみると、いくつか選択肢があるようだ。

参考:DSDT - ArchWiki

方法1:カーネルパラメータにWindowsのバージョンを渡す

DSDTには簡単なプログラムを書くことができるのだが、使用するOSによってパラメータを変更している場合、Windows用の分岐しかなく、必要なパラメータを取得できないことがあるらしい。
そこで、使用しているOSをWindowsだと虚偽申告することで、Windows用のパラメータを使用できるようにするそうだ。

カーネルパラメータの設定は、ブートローダーのブート選択メニューでブートエントリーを編集することで行った。

参考:カーネルパラメータ - ArchWiki

ただ、この方法では上手くいかなかった。後で判明するが、分岐の問題ではなかったようだ。

方法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 maximumRange minimumも共に0x00なので、Length0x00から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_RevisionToPLDというメソッド?の引数なのだが、これは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)

大文字にしろや、ということのようだ。pnp0c14PNP0C14に変更する。

これで完成。OEMバージョンの変更を忘れずに(1敗)

修正したDSDTを適用する