はじめに
SonyのNCP-HG100/Cellularというヤクオクやメルカリで未使用品が投げ売りされているガジェットがあります。こいつはLTEモデム(Telit LN940A9)を積んだルータで楽天モバイルを家で使う人などに愛用されていてインターネットには様々な情報があります。
- Sony NCP-HG100/Cellular - 大破ログ
- NCP-HG100のOpenWrtと実験の記録 : 暇暇つぶし
- 楽天モバイルを固定回線化 SONY NCP-HG100使用して光回線を解約する
- OpenWrt NCP-HG100 #openwrt - Qiita
- Sony NCP-HG100/CellularにOpenWrtを入れる | Beyond The Horizon
- ADSL終了作戦のまとめ | ぼちぼちFIRE始めます
普通に入れたら動くぽいんですけど、USBメモリからブートできるって複数記事に書いてあるので素朴にやってみたら3日溶けた。以下、記録です。
TL;DR
- OpenWRT Firmware Selectorで落とせるsysupgradeはUSBストレージ関係のkoがkernelに入ってなくて、USB storageにrootfs置くとkernelがmountできない
- ~/.openwrt/.configでkmod入れてもkernelに入らないことがあるようで、target/linux/ipq40xx/config-5.151を直接いじる必要がある
- 自力でビルドするときWSLをつかってはいけない
Firmware Selectorで取得するsysupgradeについて
OpenWRT Firmware Selectorからはinitramfsつきのkernel(itb)と、squashfsのrootfsとkernel itbをtarしたsysupgradeをダウンロードできます。また、インストールパッケージをカスタマイズしたsysupgradeを作ってダウンロードすることができます。カスタマイズ時はkernelは変わらずsquashfsに入ってるrootfsの中身のみが変更されます。
ここで取得できるkernelにはUSB Mass Storageサポートなどが入ってないので、USBメモリのストレージを認識してくれません。なので、rootfsのマウントで止まってしまう。
また、kernelが変わらないのでオプションをいじってカスタムイメージにしてもだめ。
sysupgradeの中身について
binwalkすると、tarって出てきます。
walkure@nozomi:~$ binwalk ./openwrt-23.05.2-ipq40xx-generic-sony_ncp-hg100-cellular-squashfs-sysupgrade.bin DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 POSIX tar archive (GNU), owner user name: "de-sony_ncp-hg100-cellular/"
というわけで展開すると、kernel
とroot
が出てくる。
walkure@nozomi:~$ tar xvf ./openwrt-23.05.2-ipq40xx-generic-sony_ncp-hg100-cellular-squashfs-sysupgrade.bin sysupgrade-sony_ncp-hg100-cellular/ sysupgrade-sony_ncp-hg100-cellular/CONTROL sysupgrade-sony_ncp-hg100-cellular/kernel sysupgrade-sony_ncp-hg100-cellular/root
こいつもbinwalkすると、以下のような結果が出てくる。
walkure@nozomi:~$ binwalk sysupgrade-sony_ncp-hg100-cellular/kernel DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 Flattened device tree, size: 4217876 bytes, version: 17 228 0xE4 gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date) 4194880 0x400240 Flattened device tree, size: 21628 bytes, version: 17 walkure@nozomi:~$ binwalk sysupgrade-sony_ncp-hg100-cellular/root DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 4624504 bytes, 1808 inodes, blocksize: 262144 bytes, created: 2023-11-14 13:38:11
rootは一目瞭然ですが、kernelは3エントリある。これ、itb落としてbinwalkしたときと結果が同じなので、同じだろって判断しました。
USBメモリからのブートについて
こいつが積んでるU-BootはUSBからの読み込みに対応してるので、itbをUSBに書いたら読んでくれます。bootcmdでUSBから起動できなかったら積んでるFROMから起動するようにしておくと、なんかあったらすっこ抜くだけでいいので安心ですね。USBメモリは適当に小さいエレコムの16GBを買ってみました。
USBメモリは1セクタ512バイトだと勝手に決め打ちして、セクタを適当に配分。表を作ったらfdiskでえいやと最初の29999999セクタまでプライマリパーティションを切る。
開始セクタ | 終了セクタ | サイズ | なかみ |
---|---|---|---|
2048 | 29999999 | 14.4G | rootfs(f2fs) |
30000000 | 30322688 | 157.6M | kernel(raw) |
書き込みはこんな感じ。書き込む前に、rootfsを適当にフォーマットしてマウントしておきます(わたしは/mnt/sdfs
にした)。あと、blkidで事前にPARTUUIDを調べておきます。fsはf2fsにしてみたけど、ext4でもなんでも。
sudo dd if=./build_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/linux-ipq40xx_generic/sony_ncp-hg100-cellular-uImage.itb of=/dev/sdb bs=512 seek=30000000 sudo tar -xzf ./bin/targets/ipq40xx/generic/openwrt-23.05.2-ipq40xx-generic-sony_ncp-hg100-cellular-rootfs.tar.gz -C /mnt/sdfs
その上で、U-Bootに設定を書く。usb read
ではkernelを読み込むセクタ番号を16進数で書く2ので、30000000 = 0x1C9C380
になります。
set bootusb 'set bootargs console=ttyMSM0,115200n8 root=PARTUUID=xxxxxxxx-01 rw rootfstype=f2fs rootwait; usb start; usb read 0x84000000 0x1C9C380 0x4000; bootm' set fallback 'set bootargs console=ttyMSM0,115200n8; bootipq' set bootcmd 'run bootusb; run fallback'
console指定しておくとブートログをUART繋いだ際に読めて安心です。
kernel(itb)にドライバをもたせる
cloneしたOpenWRTのカスマイズは.config
をよしなにする感じで、わたしは参考記事のパッチを読んだりして色々入れました。ここで色々kmod入れてますが、どうやらこいつらrootfsに置かれるっぽく、これだけではrootfsマウントできずブートできない。これも参考記事のパッチを睨んでいてようやく気づけた。
kernelビルドの設定はtarget/linux/ipq40xx/config-5.15なので、こいつを直接いじります
CONFIG_SCSI=y CONFIG_PHY_QCOM_IPQ4019_USB=y CONFIG_PHY_QCOM_QUSB2=y CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_COMMON=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_HOST=y CONFIG_USB_DWC3_QCOM=y CONFIG_USB_STORAGE=y CONFIG_USB_SUPPORT=y CONFIG_USB_UAS=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_PLATFORM=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_SCSI_REQUEST=y CONFIG_F2FS_FS=y CONFIG_EXT4FS_FS=y
こんな感じで、雑に書き足します。これに対応するkmod-*を消したほうがいいような気もしますが、面倒なので一旦放置…。
OpenWRTのビルドについて
というわけで、kernelでUSBストレージを認識してもらうのを目標にOpenWRTをビルドします。
まず大事なこととして、Windows上でビルドする場合はWSL2を使わずVirtualBoxなどでVM立ててビルドすること。公式3にも「A native GNU/Linux environment is recommended.」って書いてあり、わたしはWSL2でビルドしようとして様々4な苦労をして2日ぐらい溶かしました。ちなみにVirtualBoxはUSBデバイス認識がVMのメニューから認識させたいやつ選ぶだけなので超ラク(対WSL25比)。
ビルドそのものは、[OpenWrt Wiki] Build system setupを参考にapt-getでパッケージ放り込んで[OpenWrt Wiki] Build system usageにあるようにmakeするだけ。
するだけですが、初回はクロスビルド用コンパイラを落とすなどの準備をするので相当な時間がかかります。終わってみるとストレージ24Gぐらい使っていたので、VM作るときは30GぐらいvDisk用意する必要がある。
最初のcloneもつらいんですが、shallow cloneするとちょっとだけ速くなります。
git clone --depth=1 -b v23.05.2 https://github.com/openwrt/openwrt.git
- これはOpenWRT 23.05のとき。kernel version変わると、当然ファイル名も変わる。↩
- u-boot/doc/README.usb at master · u-boot/u-boot · GitHub↩
- [OpenWrt Wiki] Build system setup WSLには空白のあるWindows由来のPATHを消せとだけ書いてあるが、これやってもビルドが途中でコケてしまった。↩
- WSL2なぜかkernelがUSBストレージ対応してない(お前もか!!!)ので、せっかく最近のstock kernelはusbipd-win対応してるのにkernelをbuildする必要があります。また、f2fsみたいなマニアックなのも対応してないので、こいつを使うにもbuildする必要がある。↩
- USB デバイスを接続する | Microsoft Learn にあるように、ホスト側でCLI叩く必要がある。↩