大破ログ

日々大破、それと側転少々。PC関連その他、気になったことなどをつらつらと。

Aterm WR8750N(進捗報告)

2023/03/12 追記: このデバイスのサポート作業については完全に中止とし、実機は処分しました。今後再開する可能性は限りなく低いです

既に雑記で書き散らかしている通り、メーカーファームがNetBSDベースであるNEC Aterm WR8750NのOpenWrtにおけるサポート作業を行っています。
最近多少進展があったため、ここで一度進捗をまとめておきます。

きっかけ

今に至るまで少しずつデバイスサポートを進めてきたものの、国内メーカーの中で現状サポートできているのが2機種のみ(WG800HP, WG2600HP)とほとんど手つかずになっているNEC機をどうにかできないか、と思ったため。
また、単純にNetBSD機でもLinuxであるOpenWrtをブートできるのか、という単純な興味もあった。

仕様

ソフトウェア面が家庭向けルータとしては独特であるものの、ハードウェアはRAMの サイズが大きい以外はおおよそ一般的な構成。

SoC Atheros AR9344
RAM DDR2 128MB
Flash SPI-NOR 8MB
WAN/LAN
(switch)
1000Mbps x1 / 1000Mbps x4
(AR8327)
WLAN Atheros AR9382
USB USB 2.0 Type-A x1
Bootloader original ?
OS NetBSD based

サポート作業状況

repo: devadd/wr8750n in musashino-build/openwrt

現状動作するもの
  • initramfsファームでのブート
  • イーサネット(有線)
  • 無線 (2.4/5G) 認識(動作未確認)
  • LED
  • ボタン, スライドスイッチ
現状動作しないもの
  • sysupgradeファームでのブート
  • USBポート

作業についての詳細

ブートできるファームのフォーマット
WR8750Nではオリジナルと思われるBootloaderを搭載しており、それ故ブートできるファームのフォーマットもよく用いられるuImage等ではなく、独特なヘッダを付加したものである必要がある。
アップデート用に提供されるファームはファーム自体のヘッダ、ライセンス表記部、テストプログラム部、OSイメージ部に分かれており、ファームヘッダ部以外の各データにはそれぞれデータ用のヘッダが付加されている。
このデータ用ヘッダは、自分での推測に加え、やもり氏より多分に情報を頂いた。ヘッダのフォーマットは以下の通り。
     |  0x0 - 0x3  |  0x4 - 0x7  |  0x8 - 0xB  |  0xC - 0xF  |
     +-------------+-------------+-------------+-------------+
 0x0 |  Data Flag  |  Data Len.  | Header Len. |   checksum  |
     +-------------+-------------+-------------+-------------+
0x10 |  Load Addr  | Entry Point |                           |
     +-------------+-------------+                           +
0x20 |                         Data                          |
     +                                                       +
...
Note: checksumは上位2 byteのみ、下位2 byteは0埋め 例 (loader + initramfs, LOADER_TYPE := bin):
     |  0x0 - 0x3  |  0x4 - 0x7  |  0x8 - 0xB  |  0xC - 0xF  |
     +-------------+-------------+-------------+-------------+
 0x0 |  0002 FFFD  |  0031 3000  |  0000 0018  |  4C81 0000  |
     +-------------+-------------+-------------+-------------+
0x10 |  8006 0000  |  8006 0000  |  4080 9000     4080 9800  |
     +-------------+-------------+                           +
0x20 |  4080 6800     4008 6000     3C09 1000     3529 001F  |
     +                                                       +
...
  • "Data Flag" はデータの種類を示す。詳細はやもり氏の記事を参照。
  • "Data Len." はデータ用ヘッダを含めたデータの長さ (hex)。
  • "Header Len." はデータ用ヘッダの長さ (hex)。通常 0x18 の模様。
  • "checksum" は "Data Len." からデータ末尾までのチェックサム。前半2byteのみで、後半2byteは0埋め。このチェックサムの算出方法が不明で、やもり氏から情報を頂いていたものの正確と思われる算出方法を中々見つけられなかった。
    対象データのサイズを "4"(多分 "2" でも良い)で割り切れるようにデータ末尾をpaddingしてchecksum部分 (0xC - 0xF) を "00000000" としてヘッダを付加、以下のスクリプトにより算出し、前半2桁と後半2桁を入れ替えたものがおおよそアタリと思われる。
    ddのログが邪魔な場合は、2> /dev/null を付ける。
    dd if=fw.bin ibs=4 skip=1 | od -A n -t u2 | tr -s ' ' '\n' | awk '{s+=$0}END{printf "%04x", 0xffff-(s%0x100000000)%0xffff}'
    ibs=4 skip=1 は "Data Flag" をスキップして算出するため。
    (s%0x100000000) のカッコは無くても四則演算の優先順位上問題無いけれども、わかりやすいので付けた。
  • "Load Addr", "Entry Point" は、自分の知識不足もありAtheros/QCAで一般的に使用される 0x80060000 を使用した。
現状ではinitramfsファームに上記ヘッダを付加し、WR8750NのBootloaderでTFTPによって転送してブートできている。
Watchdog Timer
当初WR8750Nでgzip-compressedなOpenWrtファームをブートさせた際、途中でSOFT-RESETが掛かってブートが中断され、再起動されてしまっていた。(雑記の記事を参照)
複数の方から「watchdogでは」という指摘を頂いて調べたところ、WR8750NのBootloaderがWatchdog Timerのカウンタに設定する値が小さく、OpenWrtのLinux KernelがブートしてWatchdogのドライバがロードされるタイミングに間に合わず、その結果resetが発生していることを特定。
対処としては、Kernelをlzmaによる圧縮に変更したうえでOpenWrtのlzma-loaderを先頭に付加し、loader内でWatchdog Timerのカウンタが格納されるレジスタを操作して最大値を書き込むようにした。
これにより、途中でresetされることなくブートが完了するようになった。(雑記の記事1記事2を参照)
イーサネット(有線部)
Atheros/QCA SoCではネットワーク周りで様々なパラメータを設定する必要があるが(正しい値が設定されていない場合、NA(P)T速度が著しく低下したりそもそも通信できない)、BootloaderやOSにかなりクセがあるため手探りで調整するしかないかと考えていたものの、Bootloaderのdebugコマンドを利用して必要な値を取得できた。
詳細については雑記の記事を参照。
ただ、iperfでテストした際に瞬間的に速度が落ちることが何度か発生したため、要調整と思われる。
無線周り
無線を動作させる際に、調整に必要なcalibration dataはもしかしたらNetBSDAtermでも持っているのでは、と予想していたら、やはりFlash内に存在していた。また、データの存在するoffsetやsizeも一般的なLinux機と同じ様に格納されていた。
当然ながら、法律の関係上無線は実際には使用しない。
LED
SoCのGPIOからLEDを調べた際、一つもLEDが点灯しなかった。結局のところ、WR8750Nの搭載するLEDは5か所 x 各2色 = 10個すべてが5GHz帯用として搭載されているath9kチップ (AR9382)のGPIOコントローラに接続されていた。
Flashからのブート
正直厳しい感じ。メーカーファームではOSイメージをFlash上に存在するファイルの様に扱っており、通常OpenWrtで行うようなmtdによる単純な区切りではなかった。このため、単に直接ファームをFlashに書き込んだだけでは "データが破損している" とBootloaderに判断されてしまい、リカバリが発生して書き込んだデータを削除されてしまった。
USB周り
AR9344のUSBが直接出ておらず、途中にNECのハブチップ(刻印: D720114, 型番μPD720114?)を経由して出ている。複数のGPIOを操作するとUSBポートに接続したデバイスLinux Kernelから認識される状態にできるものの、何故かFull Speedまででしか認識されない(AR9344, μPD720114自体はHigh Speedまで対応)。
どの様に構成すればHigh Speedまで利用できるようになるかは、現状では自分の知識不足により不明。

今後

Flashからのブートについては、NECのBootloaderをそのまま利用するのが非常に厳しいと思われるため、U-Bootへの置き換えを検討。現状initramfsファームで起動できる状況ではあるため、ユーザーがインストールする際はそれを踏み台にすることで、SPI-NOR Flashを取り外したりする必要無しにU-BootとOpenWrtへの書き換えをできるようにする状態を目指す。
ただし、U-Bootについての知識は非常に乏しいため、まだ時間が掛かる。また、この作業はBootloaderレベルでの試行錯誤になるので、Flashを直接読み書きできるようにハードウェアに変更を加える必要もあり、少々難易度も上がるし時間も更に掛かる。
USB周りについては現状理解が追い付いていないため、一旦保留。
この機種をサポートできればNECの他のNetBSD機もおおよそ同じ手法でサポートできると思われるため、じっくり進めていきたい。