ASUS のノートに Linux を入れようとして苦労した話

ファミレスとかで作業をするため、安くて、持ち運びしやすいノートパソコンを買いました。

2022年発売モデルの11.6型の ASUS E210KA です。

CPU は Celeron N4500 、メモリ 4GB でストレージは eMMC 128GB 。希望小売価格5万で現時点の実売価格4万くらいの製品です。

https://jp.store.asus.com/store/asusjp/ja_JP/pd/productID.5609653800

https://www.amazon.co.jp/dp/B09TPHCQ8R

当然、快適な Windows ライフを楽しめるとは思っていませんので、すぐに Linux を入れることにします。

## 試行錯誤
### とりあえずインストール

比較的軽量なディストリビューションであればなんでもよかったのですが、 18.04 の頃に一度使ってみて結構好みだった Voyager をダウンロードしました。

Rufus で Live USB を作成し、 Secure Boot と Fast Boot を無効にしたノートパソコンにインストールを試みます。インストーラの案内に従って進み、パーティションの構成は手動で設定。

![Screenshot from 2023-07-08 15-47-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215290/ff35940c-ad49-2329-50be-6fc6c051e52e.png)

さあ、インストール。

と思いきや、 ext4 のフォーマットで失敗。

![Screenshot from 2023-07-08 15-47-40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215290/1493c532-ea5d-f270-800f-ad20ee39d9cb.png)

ここでのエラーはあまりないことだと思うので頭をひねりますが、ファイルシステムを XFS にしてやりなおしてみると問題なくフォーマットは完了しました。よくわからないながらインストールを進めますが、途中でエラーが発生。

![Screenshot from 2023-07-08 22-53-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215290/46ca6d84-96aa-65f0-3df4-c1cba426a210.png)

インストールメディア、ドライブあるいはハードディスクの不良（と思われる） I/O エラーというメッセージ。

### USB のイメージを疑う

Live USB を作成するときに Rufus を使いましたが、ソフト内で推奨とされている iso モードではなく dd モードでないとうまくいかないという記述をみつけたため、設定を変えて作成しなおしたりしてみましたが、相変わらず失敗します。

USB メモリも新しく購入した2つの製品で試してみたけどかわらず。

他のディストリビューションを試してみるも、やはり途中で失敗。オンラインでパッケージをダウンロードする方法、オフラインでイメージからファイルを展開する方法など試してみても失敗。

### 不良セクタを疑う

ext4 のフォーマットをコマンドで実行した際、 `dmesg` には、このようなログが出力されていました。

```shell-session
$ sudo mkfs.ext4 /dev/mmcblk0p3
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done                            
Creating filesystem with 28310267 4k blocks and 7077888 inodes
Filesystem UUID: 56264c09-de04-4108-8579-f20a94120561
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
	4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (131072 blocks): done
Writing superblocks and filesystem accounting information: mkfs.ext4: Input/output error while writing out and closing file system

$ sudo dmesg | less
# 一部抜粋
[  189.438279] mmc0: running CQE recovery
[  189.439200] blk_print_req_error: 2 callbacks suppressed
[  189.439203] I/O error, dev mmcblk0, sector 17807232 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[  189.439212] buffer_io_error: 2 callbacks suppressed
[  189.439214] Buffer I/O error on dev mmcblk0p3, logical block 3968, lost async page write
[  189.439221] Buffer I/O error on dev mmcblk0p3, logical block 3969, lost async page write
[  189.439224] Buffer I/O error on dev mmcblk0p3, logical block 3970, lost async page write
[  189.439226] Buffer I/O error on dev mmcblk0p3, logical block 3971, lost async page write
[  189.439229] Buffer I/O error on dev mmcblk0p3, logical block 3972, lost async page write
[  189.439231] Buffer I/O error on dev mmcblk0p3, logical block 3973, lost async page write
[  189.439233] Buffer I/O error on dev mmcblk0p3, logical block 3974, lost async page write
[  189.439235] Buffer I/O error on dev mmcblk0p3, logical block 3975, lost async page write
[  189.439242] Buffer I/O error on dev mmcblk0p3, logical block 3976, lost async page write
[  189.439245] Buffer I/O error on dev mmcblk0p3, logical block 3977, lost async page write
[  189.439483] mmc0: running CQE recovery
[  189.440998] mmc0: running CQE recovery
[  189.442480] mmc0: running CQE recovery
[  189.443717] I/O error, dev mmcblk0, sector 17804672 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[  189.443966] mmc0: running CQE recovery
[  189.445121] mmc0: running CQE recovery
[  189.446200] mmc0: running CQE recovery
[  189.447339] mmc0: running CQE recovery
[  189.448480] mmc0: running CQE recovery
[  189.449580] mmc0: running CQE recovery
[  189.450737] mmc0: running CQE recovery
[  189.451908] mmc0: running CQE recovery
[  189.453120] mmc0: running CQE recovery
[  189.454307] mmc0: running CQE recovery
[  189.455672] mmc0: running CQE recovery
[  189.456834] mmc0: running CQE recovery
[  189.457942] mmc0: running CQE recovery
[  189.458864] I/O error, dev mmcblk0, sector 17804032 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[  189.459151] mmc0: running CQE recovery
[  189.460293] mmc0: running CQE recovery
[  189.461475] mmc0: running CQE recovery
[  189.462421] I/O error, dev mmcblk0, sector 17803776 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[  189.462777] mmc0: running CQE recovery
[  189.464327] mmc0: running CQE recovery
[  189.465647] mmc0: running CQE recovery
[  189.466663] mmc0: running CQE recovery
[  189.467868] mmc0: running CQE recovery
[  189.468989] mmc0: running CQE recovery
[  189.470313] I/O error, dev mmcblk0, sector 17805952 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[  189.470556] mmc0: running CQE recovery
[  189.472022] mmc0: running CQE recovery
[  189.473273] I/O error, dev mmcblk0, sector 17803520 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[  189.473540] mmc0: running CQE recovery
[  189.474644] mmc0: running CQE recovery
[  189.475573] I/O error, dev mmcblk0, sector 17806592 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[  189.475788] mmc0: running CQE recovery
[  189.476691] I/O error, dev mmcblk0, sector 17806848 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[  189.476924] mmc0: running CQE recovery
[  189.478066] mmc0: running CQE recovery
[  189.479010] I/O error, dev mmcblk0, sector 17804416 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[  189.479270] mmc0: running CQE recovery
[  189.480142] I/O error, dev mmcblk0, sector 17806976 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[  189.480389] mmc0: running CQE recovery
```

XFS でフォーマットしたあと、インストールが途中まで進みますがそのあと失敗するため、どこかに不良セクタがあるようにも見えます。

`mkfs.ext4` には不良セクタにマークを付け、それを避けて使用することができるオプションがあるため、 `badblocks` をかけてチェックしてみましたが不良セクタは検知できず。読み書きモードでも同様に検知できませんでした。

八方塞がりで、これはまな板にしかならないかな、と思い始めました。[^MyASUS]

[^MyASUS]: ところで MyASUS で製品登録をすると「ASUS のあんしん保証」として自損を問わずどんな壊れ方でも“絶対サポート”らしいですが、これも適用範囲内なのでしょうかね？

### ASUS の eMMC CQE が原因

```
[  189.438279] mmc0: running CQE recovery
```

ログのこっちのほうがキーだったみたいです。

詳しいことはわからないため完全に憶測となりますが、 eMMC のコントローラの Command Queue Engine が正常な動作をしないこと（？）、あるいは Linux の処理を異常と判断し修復しようとすること（？）のような感じで、 CQE を無効にするフラグをセットすることで問題は解消しました。

https://superuser.com/questions/1688659/128gb-emmc-drive-on-asus-laptop-unable-to-format-to-ext4

## 改めてインストール
### ディストリビューションのインストール

まず、インストールしたい Live USB を挿し、起動します。

起動時に Try と Install を選択する必要がある場合は、 Try を選択しインストールが始まらないようにしておきます。

起動したら、下記コマンドを実行し CQE を無効にします。

```shell-session
$ sudo modprobe -r sdhci_pci
$ sudo modprobe -r sdhci
$ sudo modprobe sdhci debug_quriks=0x20000
$ sudo modprobe sdhci_pci
```

このあとインストーラを立ち上げてインストールを進めます。後述の作業のため、オンラインでアップデートが可能であっても利用しないほうがよいと思います。

インストールが完了しても再起動はしないでください。

![Screenshot from 2023-07-08 23-21-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215290/f938e6a9-1fc0-d8d4-5c2d-19779b49c236.png)

### 永続化の設定

今は USB から起動していたため、 `sdhci` モジュールの再読込で対応が可能でした。しかし eMMC 上の OS を起動しようとすると、 CQE 無効化前に eMMC にアクセスする必要があるためカーネルパニックを起こして起動しなかったり、起動してもすぐに使用できなくなります。

起動時のカーネルパラメータで CQE 無効フラグを追加することで一時的に起動することができるため、そのときに永続化の設定を行うこともできますが、せっかくなので USB からブートしている現環境で永続化を試みます。

パーティション構成は下記のとおりとします。

- `/dev/mmcblk0p1` : `/boot/efi`
- `/dev/mmcblk0p2` : swap
- `/dev/mmcblk0p3` : `/`

`chroot` を使用して、 eMMC 上にインストールした環境の initrd を更新し、起動時に CQE 無効の設定が生きるようにします。

```shell-session
$ sudo mount /dev/mmcblk0p3 /mnt
$ sudo mount /dev/mmcblk0p1 /mnt/boot/efi
$ sudo mount --rbind /dev /mnt/dev
$ sudo mount -t proc none /mnt/proc
$ sudo mount --rbind /sys /mnt/sys
$ sudo chroot /mnt

# echo "options sdhci debug_quirks=0x20000" >/etc/modprobe.d/sdhci-disable-cqe.conf
# update-initramfs -u -k all
update-initramfs: Generating /boot/initrd.img-6.2.0-20-generic

# lsinitramfs /boot/initrd.img-6.2.0-20-generic | grep cqe
etc/modprobe.d/sdhci-disable-cqe.conf
# exit
exit

$ sudo umount -l /mnt/sys
$ sudo umount /mnt/proc
$ sudo umount -l /mnt/dev
$ sudo umount /mnt/boot/efi 
$ sudo umount /mnt
```

ブートパーティションのマウント先は、インストールしたディストリビューション、使用ブートローダなどによって異なる場合があります。

ディストリビューションによって `update-initramfs` ではなく `mkinitcpio` や `dracut` を使うこともあります。 `dracut` の場合は

```shell-session
$ sudo dracut -f --hostonly --no-hostonly-cmdline /boot/initramfs-linux.img 
```

インストール時に、オンラインからパッケージのアップデートを有効にすると、 Live USB 上のカーネルバージョンと、 eMMC 上にインストールされたカーネルのバージョンが異なることでエラーが発生することがあります。その場合には `/boot` に含まれている initrd の名前や `/lib/modules` を参考に、オプションでカーネルバージョンの指定などが必要です。

### 様子見

ブートまわりの知識が乏しく、ちゃんとあっているかわからないため、再起動やカーネルの更新などを行いながら、問題なく動作するか様子を見ます。カーネル更新時には initrd の更新処理が行われるかも確認しておきます。

とりあえず、よくわからないながら動いています。

ちなみに、当初 Voyager Linux をインストールしてみましたが、どうも動作がもっさりとしているため EndeavourOS にしてみました。 Arch Linux 系はじめてだったので、ちょっと興味あったこともあり。

## カーネル開発陣の動き

この件を検索すると Linux カーネルのパッチについてのメーリングリストがみつかりましたが、それが提案なのか、採択されたものかまでは追えていません。少なくとも Linux Kernel 6.3 のインストールイメージでも、この問題は発生しました。

該当する Bugzilla としてはこちらあたり。

https://bugzilla.kernel.org/show_bug.cgi?id=212065