シリーズ目次(Qua Station を mainline Linux で動かす連載・全 7 本)
- (1) 6.18クロスビルド・Ubuntu 26.04起動・シリアルレス診断手法
- (2) SATA・PCIe・Wi-Fi・LEDのハードウェア復活
- (3) rootfsをSSDへ移行
- (4) ext4破損インシデントとUSB2.0/PCIe診断ログ洪水の解決
- (5) 番外編: 作ったのに使えなかったBluetooth SPP非常口コンソールの話
- (6) 配布イメージを作って GitHub で公開する ← 本記事
- (7) Linux 7.2→7.3 移植編 — Wi-Fi の無言死は上流の 1 行、翌日出た 7.3 は 2 行で一発起動
概要
シリーズ(1)〜(5)で mainline Linux 6.18 + Ubuntu 26.04 に載せ替えた au Qua Station (RTD1295) を、他の人も同じ構成で動かせる配布セットとして GitHub に公開しました。この記事は導入手順がメインです。何を用意して、どこに何を置いて、どう起動して、どう入るかを順に書き、作り方は最後に短くまとめます。
- リポジトリ(手順・スクリプト・README 日英): https://github.com/okura1234/quastation-linux
- イメージ本体(Release v0.1.0, pre-release): https://github.com/okura1234/quastation-linux/releases/tag/v0.1.0
- カーネルソース: https://github.com/okura1234/monarch-6.18 の
qua-distブランチ
先に正直に書いておきます。この配布イメージそのものでの実機起動テストはまだやっていません。本番で動いている機体(ADS-B 受信機として常時稼働中)を止めたくなかったためです。稼働中の機体と同じカーネル設定・同じ DTB・同じ手順で組んだ rootfs から再構成したものですが、「配布物を落として焼いたら動く」までは未確認の v0.1 です。試した方の報告は Issue で歓迎します。
用意するもの
| もの | 条件・備考 |
|---|---|
| Qua Station 本体 | U-Boot が USB 起動できる状態になっていること(下記) |
| 2.5 インチ SATA SSD / HDD | 内蔵ベイに入れる。中身は全部消えます。容量は 16 GB 以上あれば十分 |
| USB メモリ | 1 GB 以上。起動用(FAT32)。これも全部消えます |
| USB-LAN アダプタ | Realtek RTL8152/8153 系を推奨(ドライバ組込済み)。初回ログインの経路 |
| 作業用 Linux PC |
parted / mkfs.ext4 / mkfs.vfat / tar が使えればよい。USB-SATA 変換があると SSD を PC で作れて楽 |
前提: U-Boot の USB 起動対応
この機種は出荷状態では USB から起動できません。シリーズ(1)にも書きましたが、一度だけシリアルコンソール(内部 UART, 115200bps)で U-Boot に入り、bootcmd を USB 起動対応に書き換える必要があります。手順はコミュニティの tsukumijima/QuaStation-Ubuntu に詳しく、そこでベンダー 4.9 カーネルの Ubuntu を一度動かしたことがある機体なら、そのまま本配布セットに差し替えられます。
U-Boot(ベンダー製 2015.07)が読むのは 最初の USB ディスクの第 1 FAT パーティションにある uImage と QuaStation.dtb の 2 ファイルだけです。SSD の中身は U-Boot からは一切見えず、カーネルが起動してから initramfs が SSD を探します。
配置の全体像
USB メモリ(FAT32, ラベル BOOT) ← U-Boot が読む
├── uImage カーネル 6.18.52-qua1(initramfs 内蔵)
├── QuaStation.dtb Device Tree
└── wpa_supplicant.conf (任意) 置いておくと初回起動で Wi-Fi 設定に取り込まれる
SATA SSD(MBR, パーティション 1 つだけ) ← カーネルが LABEL で探す
└── /dev/sdX1 ext4, ラベル qua-root Ubuntu 26.04 rootfs 一式
├── /usr/lib/modules/6.18.52-qua1+/ カーネルモジュール
├── /usr/lib/firmware/{rtlwifi,rtl_bt,rtlbt}/
├── /etc/systemd/network/*.network 有線 DHCP・mDNS・Wi-Fi の優先順位
└── /swapfile 初回起動で 2 GB 作成
ポイントは 3 つです。
- 起動 USB は 2 ファイルだけ。rootfs は SSD にあるので、USB は小さくてよい(旧構成では rootfs も USB に置いていましたが、配布版では分けました)
-
SSD は 1 パーティション。カーネル内蔵の initramfs が
LABEL=qua-rootを探して root にします。パーティション番号や PARTUUID に依存しないので、PC でも Qua 上でも、どの SSD でも同じ手順で作れます - Wi-Fi の設定は USB 側に置く。rootfs に PSK を書き込む必要がなく、PC からテキストファイルを 1 つ置くだけで済みます
導入手順
1. Release からファイルを落とす
mkdir qua && cd qua
R=https://github.com/okura1234/quastation-linux/releases/download/v0.1.0
curl -LO $R/uImage; curl -LO $R/QuaStation.dtb
curl -LO $R/quastation-ubuntu2604-rootfs.tar.gz; curl -LO $R/SHA256SUMS
sha256sum -c SHA256SUMS
git clone https://github.com/okura1234/quastation-linux # tools/ のスクリプトを使う
2. SSD を作る(PC に USB-SATA で繋いで)
lsblk # SSD のデバイス名を確認(例 /dev/sdb)。間違えると PC 側を消します
sudo quastation-linux/tools/flash-ssd.sh /dev/sdb quastation-ubuntu2604-rootfs.tar.gz
スクリプトの中身は次の 4 行相当です。手でやる場合は --keep-directory-symlink を落とさないでください((1) で踏んだ、/lib の symlink を tar が実ディレクトリに化けさせて起動不能になる罠の対策です)。
parted -s /dev/sdb mklabel msdos mkpart primary ext4 1MiB 100%
mkfs.ext4 -L qua-root /dev/sdb1
mount /dev/sdb1 /mnt
tar --keep-directory-symlink --numeric-owner --xattrs -xzpf quastation-ubuntu2604-rootfs.tar.gz -C /mnt
3. 起動 USB を作る
sudo quastation-linux/tools/make-boot-usb.sh /dev/sdc uImage QuaStation.dtb # sdc = USB メモリ
中身は「MBR に FAT32 を 1 つ(ラベル BOOT)→ 2 ファイルをコピー」だけです。既に 4.9 系の Ubuntu で使っていた起動 USB があるなら、その FAT パーティションの uImage と QuaStation.dtb を差し替えるだけでも動きます(旧ファイルは uImage.49 のように改名して残しておくと戻せます)。
最初から Wi-Fi を使うなら、同じ USB に wpa_supplicant.conf を置きます。
ctrl_interface=/run/wpa_supplicant
update_config=1
country=JP
network={
ssid="YOUR-SSID"
psk="YOUR-PASSPHRASE"
}
4. 組み立てて電源 ON
- SSD を内蔵ベイへ
- USB メモリと USB-LAN アダプタを背面 USB へ。USB-LAN はルーターに結線しておく
- 電源 ON
LED で進み具合が分かります。
| 状態 | 意味 |
|---|---|
| 前面左 LED が点灯 | カーネルが起動し initramfs に入った |
| 前面左 LED が点滅しっぱなし | initramfs が qua-root ラベルの SSD を見つけられなかった(SSD 未認識・ラベル違い・ケーブル) |
| HDD LED が赤 → 緑(40〜60 秒後) | systemd まで起動完了。SSH 可能 |
5. ログインする
ssh qua@quastation.local
| 項目 | 値 |
|---|---|
| ユーザー / 初期パスワード |
qua / qua
|
| 初回ログイン | パスワード変更を強制されます |
| sudo | 可(パスワードあり)。root はロック |
| ホスト名 |
quastation(mDNS で quastation.local) |
.local で引けない環境では、ルーターの DHCP クライアント一覧で quastation を探してください。ルーターが無くて PC と直結する場合は、PC 側を 192.168.1.x/24 にして ssh qua@192.168.1.44 で入れます(有線に DHCP と並行してこの固定アドレスも付けてあります)。
6. 初回起動で自動的に行われること
qua-firstboot.service が毎回走り、未処理のものだけ実行します。
- SSH ホスト鍵の生成(イメージには入っていません)
-
/swapfile2 GB の作成(zram 768 MB と併用) - 起動 USB に
wpa_supplicant.confがあれば/etc/wpa_supplicant/wpa_supplicant-wlan0.confと-wlan1.confに複製し、wpa_supplicant@wlan0/@wlan1を有効化。USB 側のファイルは.importedに改名
wlan0 と wlan1 の両方に同じ設定を入れるのは、5 GHz (RTL8812AE) と 2.4 GHz (RTL8192EE) のどちらが wlan0 になるかが起動ごとに入れ替わるためです。経路の優先度は systemd-networkd の RouteMetric で「有線 → 5 GHz → 2.4 GHz」に固定してあります。
7. 後から Wi-Fi を設定する場合
sudo cp /etc/wpa_supplicant/wpa_supplicant.conf.example /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
sudo vi /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
sudo cp /etc/wpa_supplicant/wpa_supplicant-wlan0.conf /etc/wpa_supplicant/wpa_supplicant-wlan1.conf
sudo systemctl enable --now wpa_supplicant@wlan0 wpa_supplicant@wlan1
動くもの・動かないもの
| ハード | 状態 | 備考 |
|---|---|---|
| CPU 4 コア / RAM 2 GB | ✅ | zram + swapfile |
| SATA | ✅ | root。LABEL=qua-root
|
| USB 3.0 ×2 / 本体 USB 2.0 | ✅ | (4) で復活させた USB2.0 も有効 |
| Wi-Fi 5 GHz (RTL8812AE) | ✅ | mainline rtl8821ae
|
| Wi-Fi 2.4 GHz (RTL8192EE) | ✅ | 受信が 1 Mbps に張り付く持病あり。SSH は通る |
| Bluetooth (RTL8761ATV) | ✅ | 起動時に pinmux と rtk_hciattach を自動実行。bluetoothctl で使える |
| LED 11 個・COPY ボタン | ✅ | /sys/class/leds/ |
| LTE モデム (ASKEY) | 🟡 | 検出はする。SIM での通信は未検証 |
| eMMC | ❌ | 6.18 では mmcblk が見えない(4.9 では読めた)。起動にも使わない |
| 内蔵 GMAC | — | 筐体に RJ45 が無い個体がほとんど |
| GPU (Mali) | — | ヘッドレス前提 |
よくある質問になりそうなこと
-
タイムゾーンが UTC:
sudo timedatectl set-timezone Asia/Tokyo -
rtl_nic/rtl8153a-2.fwの読み込み失敗が dmesg に出る: 無くても動きます。気になるならsudo apt install linux-firmware -
たまに SATA が無言で止まる(ping は通るのに何も実行できない。(4) で遭遇):
qua-iowd.serviceが検知してsysrqで自動再起動します。不要ならsudo systemctl disable qua-iowd -
dmesgに PCIe の割り込みメッセージが大量に出る: 5 GHz カード側。無害ですがログは読みにくい -
元の 4.9 環境に戻したい: 起動 USB の
uImage/QuaStation.dtbを元に戻すだけ。SSD は触らなくてよい(別ラベルなので 6.18 側からも見えるだけで壊しません)
作り方(短く)
ここから先は「どう作ったか」です。再現したい人向けに要点だけ書きます。
設計で決めたこと
| 項目 | 決定 | 理由 |
|---|---|---|
| 入れるもの | デバイス対応は全部(SATA/PCIe Wi-Fi 5G・2.4G/BT/USB2.0/LED/zram/watchdog) | 「載っているハードは Linux から全部使える」がシリーズの到達点 |
| 入れないもの | ADS-B のコンテナ群、Tailscale | 自分のローカル仕様。配布物に混ぜると「動くけど何か足りない」の原因になる |
| SSD の区画 |
1 パーティションのみ、LABEL=qua-root
|
自分の機体は 20.04/24.04/26.04 の 3 世代が同居していたが、配布物では単純な方が良い |
| 初期ユーザー |
qua / qua、初回ログインで変更強制 (chage -d 0) |
配布用初期値はシンプルに。root はロック |
| 初回到達経路 | USB-LAN で DHCP + mDNS quastation.local + 予備の固定 192.168.1.44
|
下記 |
| Wi-Fi | 初期状態では未設定。起動 USB に wpa_supplicant.conf を置けば初回起動で取り込む |
Raspberry Pi 流。PSK を配布物に入れない |
| タイムゾーン | UTC | 配布物に自分の地域を入れない |
初回到達経路を 3 段構えにした理由
「固定 IP を 192.168.1.44 にしておけば楽では」と一度考えましたが、相手の LAN が 192.168.0.x や 10.x だと届かず、同じ LAN に 2 台挿すと衝突します。逆に DHCP だけだと IP が分からず、ルーターの管理画面を探すことになります。
結局、systemd-networkd で有線を DHCP にしつつ Address=192.168.1.44/24 を追加アドレスとして併記し、systemd-resolved の mDNS を有効にして quastation.local で引けるようにしました。README の案内は「.local → ルーターの DHCP 一覧 → PC 直結なら .44」の順です。
[Match]
Driver=r8152
[Link]
RequiredForOnline=no
[Network]
DHCP=yes
MulticastDNS=yes
Address=192.168.1.44/24
[DHCPv4]
RouteMetric=20
NIC は Name= ではなく Driver= で判定しています。(4) で踏んだ「wlan0/wlan1 の割り当てが起動ごとに入れ替わる」問題への対策で、配布物でも同じ罠を回避する必要があります。RequiredForOnline=no が無いと、ケーブル未接続のときに systemd-networkd-wait-online が 2 分待ってしまいます。配布イメージではさらに systemd-networkd-wait-online.service 自体も disable しています(どの NIC が挿さるか分からないので「オンライン待ち」に意味がない)。
「固定 PARTUUID」をどう外したか
自分の機体では、カーネル組込みのコマンドラインに root=PARTUUID=20a83e9c-04 と自分の SSD の値を直書きしていました((3) の経緯)。配布物では当然使えません。
内蔵 initramfs の init(busybox ベースのシェルスクリプト)を書き換え、root= を LABEL= / PARTUUID= / /dev/... のどれでも受け付けるようにし、既定を LABEL=qua-root にしました。探索は busybox の findfs に任せています。
ROOTSPEC=$(sed 's/^/ /' /proc/cmdline | sed -n 's/.* root=\([^ ]*\).*/\1/p')
[ -n "$ROOTSPEC" ] || ROOTSPEC=LABEL=qua-root
find_root() {
case "$ROOTSPEC" in
LABEL=*|UUID=*|PARTUUID=*) findfs "$ROOTSPEC" 2>/dev/null ;;
/dev/*) [ -b "$ROOTSPEC" ] && echo "$ROOTSPEC" ;;
esac
}
RTD1295 の SATA は initramfs 実行中に probe が deferred のまま進まない((3) 参照)ので、PHY と AHCI を drivers_probe で明示的に蹴る処理は残しています。root が見つからなければ前面左の LED を点滅させて止まるようにし、「起動 USB は読めたが SSD が見えていない」をシリアル無しで判別できるようにしました。
ついでに、(1) の診断用に入れていた「dmesg を起動 USB 側に書く」「rootfs の読み込みテスト」「chroot での glibc 実行テスト」は配布版では落としました。起動直後の dmesg と pstore を root 側の /var/log/qua-initramfs/ に残す処理だけは、起動失敗の切り分けに使えるので残しています。
rootfs を x86 の PC で組む
ARM 実機で chroot するのが素直ですが、本番機を使いたくないので x86_64 の開発 PC で組みました。Ubuntu 26.04 では qemu-user-static は仮想パッケージ名になっていて、実体は qemu-user-binfmt です。
sudo apt install qemu-user-binfmt
cat /proc/sys/fs/binfmt_misc/qemu-aarch64
# enabled
# interpreter /usr/bin/qemu-aarch64
# flags: POF
flags: POF の F があるので、chroot 先に qemu バイナリをコピーしなくても arm64 の実行ファイルがそのまま動きます。ビルドスクリプトの骨格は次の 7 段です。
tar -xzf ubuntu-base-26.04.1-base-arm64.tar.gz -C "$R"
chroot "$R" apt-get install ... systemd-networkd 系 / openssh-server / wpasupplicant / bluez / gpiod ...
cp -a overlay/. "$R"/ # unit・スクリプト・firmware・network 設定
cp -a lib/modules/6.18.52-qua1+ "$R/usr/lib/modules/"; chroot "$R" depmod -a 6.18.52-qua1+
chroot "$R" useradd -m -G sudo,adm,dialout,plugdev qua; echo qua:qua | chroot "$R" chpasswd; chroot "$R" chage -d 0 qua
chroot "$R" systemctl enable systemd-networkd systemd-resolved ssh qua-firstboot qua-uart1-pinmux rtk-bluetooth qua-boot-led ...
rm -f etc/ssh/ssh_host_*; : > etc/machine-id; rm -rf var/log/journal/* # 秘密と個体識別子を残さない
tar --numeric-owner --xattrs -czf quastation-ubuntu2604-rootfs.tar.gz -C "$R" .
出来上がりは展開 374 MB、tar で 106 MB です。
詰まった 3 点
| 症状 | 原因 | 対処 |
|---|---|---|
cp: cannot overwrite non-directory '…/rootfs/./lib' with directory |
overlay に lib/firmware/ を置いていた。usrmerge 済み rootfs の /lib は usr/lib への symlink なので、実ディレクトリで上書きできない |
overlay 側を usr/lib/firmware/ に移す。(1) で tar が usrmerge の symlink を壊した話と根は同じ |
systemctl enable が Unit fake-hwclock.service is masked で失敗 |
26.04 の fake-hwclock は fake-hwclock-load.service / -save.service / -save.timer に分かれ、旧名は mask されている |
enable リストから外す(出来上がった tar を見ると sysinit.target.wants/fake-hwclock-load.service と timers.target.wants/fake-hwclock-save.timer がパッケージ導入時点で張られていた) |
passwd -l root の直後にスクリプトが終了する |
ubuntu-base の /etc/shadow では root が最初から *(パスワード無し)。chroot 内の passwd -l が非 0 で終了し set -e に引っかかった(出力を捨てていたので理由は取れていない。同じ chroot で手で実行すると 0 が返る) |
` |
3 つとも「スクリプトを 1 回通せば出る」類で、手順を手で追っていたら気づかなかったはずです。再現スクリプトにする利点は、配布のためというより自分の手順の穴が見えることでした。
カーネル側の配布物
カーネルは symops/monarch-6.18(WD My Cloud Home 用。同じ RTD1295)の fork に Qua 用の DTS・SATA クロック/電源・PCIe の MSI 修正・USB2.0・LED・initramfs を足したもので、qua-dist ブランチに config と initramfs のソースも入れています。LOCALVERSION=-qua1 にして、自分の run40 と /lib/modules/ が混ざらないようにしました(CONFIG_MODVERSIONS が無いので vermagic が同じだと別ビルドのモジュールが黙って載ります)。
uImage は mkimage で包んだものではなく、素の arm64 Image のヘッダ text_offset を 0x280000 に書き換え、末尾に 512 KB のゼロを足しただけです((1) 参照)。これも build/make-uimage.py として同梱しました。
残っていること
-
6.18 では eMMC (
mmcblk2) が見えません。ベンダー 4.9 では読めていたので、README に「読める」と書きかけて実機で確認したら/dev/mmcblk*が存在しませんでした。配布物に書く前に実機でlsする、を徹底する必要があります - Bluetooth のファームウェア
rtl8761a_fwは自分の機体の eMMC(Android 領域)から取り出したもので、linux-firmware 収録の同名ファイルとはハッシュが一致しません。再配布の可否がグレーなので README に出所を明記し、差し替え方を書くに留めました。linux-firmware 版で動くかは未検証です - 実機起動テストは、自分の SSD に 9 月末の再パーティションで空けた 40 GB の空きがあるので、そこに
qua-rootを作って現行環境を壊さずにやる予定です。結果は本記事に追記します - GitHub への push で
push declined due to email privacy restrictionsに当たりました。コミットの author を<id>+<user>@users.noreply.github.comにfilter-branchで書き換えて解決。公開前に 1 回は踏む罠だと思います
まとめ
「動いている環境を配布する」は、イメージを吸い出して秘密を消す作業ではなく、最初から秘密を入れない手順を書く作業でした。手順にした時点で自分の環境の暗黙知(固定 PARTUUID、手で enable した unit、手で置いたファームウェア)が全部表に出てきて、それを「どの機体でも同じ配置で置ける形」に直すのが実作業の大半です。
同じ機種を持っている方、あるいは他の RTD1295 機(WD My Cloud Home 系)で同じことをやりたい方の足がかりになれば幸いです。
参考文献
- okura1234/quastation-linux — 本記事の配布セット
- symops/monarch-6.18 — カーネルの土台(WD My Cloud Home 向け)
- tsukumijima/QuaStation-Ubuntu — ベンダー 4.9 カーネルでの Ubuntu 20.04 rootfs 構築(先行プロジェクト)
-
systemd.network(5) —
Driver=マッチとRequiredForOnline=