BUFFALO WXR-2533DHP

2018年1月に某氏より頂き、年を跨いでようやくサポートを追加することができました。
自分の知識不足でハードウェアの必要な構成情報を調べられず、長期間保留になっていましたが、別のアプローチにより構成情報を得て作業を行い、マージされました。まとめます。

仕様

以前投げ込んだNEC Aterm WG2600HPと同じ、IPQ8064搭載機です。WG2600HPと比べて非常に筐体が大きく、外部接続のアンテナ4本が非常に印象的。大型故にWG2600HPと比べて排熱周りは多少安心できるかもしれません。USB 3.0ポートは2つ搭載しています。
無線機能の使用は、法律の関係上非推奨です。

  • SoC: Qualcomm IPQ8064 (384 – 1,400MHz, 2C2T)
  • RAM: DDR3 512MB
  • Flash:
     SPI Flash 4MB
     NAND 256MB
  • WAN/LAN: 1000Mbps x1 / 1000Mbps x4
  • UART: 115200bps(J3, 並びはシルク印刷通り)
  • USB: 3.0 Type-A x2

その他様々な詳細情報等は雑記ブログを参照。

OpenWrt化

Factoryファームを生成させることも可能でしたが、色々な事情により用意していません。BUFFALO機でおなじみの、AOSSボタンを押しながらブートする方法を使用します。

TFTPサーバを用意
WXR-2533DHPのinitramfsファームを wxr2300dhp-initramfs.uImage へリネームしたうえでTFTPディレクトリへ設置し、IPアドレス: 192.168.11.10でTFTPサーバを開始
WXR-2533DHPをブート
AOSSボタンを押しながら電源スイッチを押し、WXR-2533DHPを起動
initramfsファームで起動
WXR-2533DHPが起動中にWireless LEDが点滅したら、AOSSボタンから指を離す。WXR-2533DHPがTFTPサーバからinitramfsファームをダウンロードし、それを用いてブートを行う
NAND FlashのOSイメージをバックアップ
initramfsファームで起動した状態でメーカーファームのバックアップを行う(任意)
バックアップ無しでもOpenWrtをインストールすることは可能なものの、バックアップしておくとメーカーファームへの復元が容易
/proc/mtd を参照してmtd0またはmtd1が "ubi" または "rootfs_1" であることを確認し、ddでmtd0またはmtd1を取り出す
例:

dd if=/dev/mtd0 of=/tmp/mtd0.ubi

sysupgrade
sysupgradeファームをダウンロードし、sysupgradeを実行
完了
sysupgrade後、FlashからOpenWrtが起動してくれば完了

メーカーファームへの復元

OpenWrt化の際バックアップしたファイルを用い、mtd1に対してubiformatを行う。

cat /proc/mtd


でmtd1が “rootfs_1” であることを確認し、

ubiformat -f mtd0.ubi /dev/mtd1


を行い再起動する。

備考

  • WXR-2533DHP2は実機を確認しておらず、あくまでWXR-2533DHP用のサポート。
  • サポート作業が遅延していたのは、SPIやNAND、GPIO等各種ピンの構成情報が不明であったことが理由。BUFFALOが公開しているWXR-2533DHPのGPLソースコード内で、WG2600HP等で構成情報が書き込まれていたCファイル内にデバイス固有と思われる情報が無く、構成情報が不明だった。
    長らくその状態のまま仮設定のまま保留になっていたものの、他targetでのサポート作業の経験からレジスタを見ることを知識として得、Linux Kernel (mainline)のコードからGPIO関連のレジスタと思われるアドレスを探り、WXR-2533DHPにてメーカーファーム上で参照して恐らくそれと思われる構成情報を得て、それをもとにOpenWrtのコードを構成した。
    電流値等を設定するため、不正な構成情報を使用した場合SoCや関連デバイスへの過負荷等で故障を招く恐れがある。
  • WXR-2533DHPは4MBのSPI-NOR FlashをBootloader (U-Boot)やハードウェア情報の格納に、256MBのNAND FlashをOSイメージの格納に使用する。このうちNAND Flashは実際に使用されているのは前半128MBのみであり、また、そこにOSイメージを2つ持つ構成であるため、OSイメージ1つ辺りのサイズは64MB程度となる。
  • NAND Flashに格納されるOSイメージは、UBIによってVolumeが分けられてそれぞれに Kernel, RootFS, RootFS Data が格納されている。このうちRootFSのVolumeには "ubi_rootfs" というvolume名が割り当てられていたが、この名前はOpenWrtでは直接使用することができない("rootfs" なら直接扱える)。
    しかしながら、起動時にU-Bootが "ubi_rootfs" のチェックを行うため、どうしてもこの名前が必要であり、OpenWrtが直接扱える "rootfs" に変更することができなかった。
    • サポート作業時、どうしてもOpenWrtでrootfsとして "ubi_rootfs" を使用することができず、ダミーのvolumeとして "ubi_rootfs" を用意し、OpenWrtは "rootfs" を使用するようにした。
    • PRを出した際、”bootargsに ubi.block を含めることで指定したUBI volumeからblockデバイスを作成する” という指摘を受け、その通りに追加して rootfs=/dev/ubiblock0_1 を追加で指定したところ、正常に "ubi_rootfs" をRootFSとして使用することができた。

色々

記事の最初に書いた通り2018年からおよそ1年掛かった作業がようやく終わって、ほっとした。
WXR-2533DHPはU-BootやKernelにパスワードが設定されているなどは無いものの、正確なハードウェア情報が得られず苦戦した形になった。正確な情報が予め公開されているGPLソースコードから得られてすぐに組み上げられたものの、U-BootもKernelもガチガチで投入に苦戦したWG2600HPと比べてどっちもどっち、という感じ。
兎にも角にも、この機種でも非常に多くの知見が得られたので、結果としてはとても良かったのではないかなと。実機を提供して頂いた某氏には本当に感謝です。
ubiblockの件はもっと早く知りたかった…。

広告

NEC WG2600HP

PRを5月17日に投げ、それ以降かなり時間がかかりましたが、6月20日にマージされました。WN-AX1167GRやETG3-Rのサポート作業等で後回しになっていましたが、この機種についてもまとめます。

仕様

以前経過報告として記事を書いたとおり、BUFFALO WXR-2533DHPと同じくIPQ8064を搭載しています。おおよそ構成は似通っているものの、WXR-2533DHPの大型筐体に対して、こちらは厚みのある金属板を基板両側に持たせてチップ等からの熱を伝達させるなどして廃熱を処理し、かなりコンパクトにまとめられています。

  • SoC: Qualcomm IPQ8064 (384 – 1,400MHz, 2C2T)
  • RAM: DDR3 512MB
  • Flash: SPI Flash 32MB
  • WAN/LAN: 1000Mbps x1 / 1000Mbps x4
  • UART: 115200bps (電源コネクタ側からRX, TX, NC, GND, Vcc)
  • USB: 3.0 Type-A x1

その他Kernel等の詳細は雑記ブログを参照。

OpenWrt化

現状メーカーのアップデートファームの形式が判明していないため、factoryファームはありません。
WG2600HPのU-BootやKernel周りの仕様上、OpenWrt化にはシリアルコンソールが必須であるほか、非常に複雑な手順で導入する必要があります。また、U-Bootが元々持っている復旧手段が無いに等しいため、文鎮化のリスクが高めです。

  • WG2600HPのfailsafeモードに入る

    WG2600HPをシリアルコンソールを接続した状態で電源を投入し、途中
    Press the [f] key and hit [enter] to enter failsafe mode
    と表示されたタイミングで “f” -> “Enter” の順にキーを押下してfailsafeモードに入る

  • fw_env.configを作成

    fw_printenv, fw_setenvコマンドを使用できるようにするため、/etc/fw_env.configを以下の内容で作成する

    /dev/mtd9 0x0 0x10000 0x10000
    

  • U-Bootの環境変数を設定

    以下のコマンドを上から下まで全て実行し、OpenWrtをブートするのに必要なU-Bootの環境変数を設定する
    追記: LAN側のリンクがある場合、延々とTFTPを試行し続ける問題があったので変更しました。ipaddrとserveripは、ローカル環境で使用することが無いアドレス帯に設定してください。

    fw_setenv ipaddr "192.168.0.1"
    fw_setenv serverip "192.168.0.2"
    fw_setenv autostart "yes"
    fw_setenv bootcmd "ping ${serverip} && tftpboot 0x44000000 wg2600hp-initramfs.bin; bootipq"
    

  • PC側でTFTPサーバを準備

    PC側のIPアドレスを 192.168.0.2 に設定し、WG2600HP用のinitramfsファームを wg2600hp-initramfs.bin にリネームしたうえでTFTPディレクトリに置き、TFTPサーバを起動

  • WG2600HPをinitramfsファームでブート

    WG2600HPから電源ケーブルを抜き差しして再起動させる。ブートする際に自動的にinitramfsファームをTFTPサーバからダウンロードしてRAMに読み込み、それを使用してブートされる
    追記: PC側でWG2600HPからのpingに応答できる状態にしておく。Windowsの場合、ファイアウォールの “パブリック” でファイアウォールを一旦無効化、またはICMP requestの許可を行う。
    pingが失敗した場合、TFTPでinitramfsが取得されずFlashからのブートが試行されてしまう。

  • sysupgradeファームの書き込み

    initramfsファームで起動後、
    mtd erase firmware
    でfirmwareパーティションのメーカーファームを消去したうえでsysupgradeコマンドでWG2600HP用のsysupgradeファームを書き込む

  • 完了

    sysupgradeファームを書き込み後、OpenWrtが正常に起動してくれば完了。
    sysupgradeが完了して再起動される前に、TFTPサーバが起動しているPCは切断しておく(initramfsファームでの起動を試行してしまうため)。

備考

  • WG2600HPは、以前の記事でも書いた通りU-BootとKernelのどちらもログインパスワードが設定されており、通常の方法では直接操作することができない。
    ファームはOpenWrtベースのQSDKを利用しているため、failsafeモードを利用していく。
  • U-BootはCtrl + Cでブートプロセスを中断させコンソールに入る方法が提供されているものの、前述のとおりパスワードがかけられており入ることができない。
    ただしLinux Kernelが破損している場合は非常時であるためか、そのままU-Bootのコンソールに落ちる。
    注意するのはKernelが破損している場合のみという点で、もしKernelが問題なくてもRootfsが破損するなどしてKernelがRootfsを読み込めずKernel Panicになった場合、U-Bootに落ちず再起動が繰り返されるのみとなり、Flashを直接ライタ等で書き換えるなどするしか復旧できなくなる。
  • 上記に関連して、OpenWrt化の手順でU-Bootに設定する環境変数のうち、
    "ping ${serverip} && tftpboot 0x44000000 wg2600hp-initramfs.bin; bootipq"
    はまずserveripに対してpingを試行し、成功すればTFTPサーバがあるものとしてinitramfsファームの読み込みを試行する。pingが失敗した場合、TFTPでのinitramfsファーム転送を行わないものとしてそのまま bootipq に進み、Flashからのブートが行われる。
    initramfsファームを介してOpenWrtを導入した後も、この設定は復旧手段としてそのまま残すことを強く推奨
    また、この関係上 “wg2600hp-initramfs.bin が存在するTFTPサーバが起動されているPCが接続されている” 場合は先に読み込まれるinitramfsファームが優先されるため、必要がなくなったら切断する。
  • メーカーファームでは、32MBのFlashのうち
    0x860000 - 0xa60000 の0x200000 (2MB)をKernel、
    0xa60000 - 0x2000000 の 0x15a0000 (21.625MB)をRootfs
    として使用している。
    しかしOpenWrtではもう既にKernelが2MBでは全く不足すること、またFlash内を効率的に利用したいことから、ramips等で行われているようにKernel + Rootfsをひとまとめにした “firmware” パーティションを利用するようにした。なお、これについてはForumで頂いたアドバイスがきっかけ。
    これにより、他機種では “kernel” パーティションを4MBまで拡張するコミットが入るなどしているものの、WG2600HPではKernelのサイズに縛られたりすることなく柔軟にFlash内の領域を利用できる。
    余談として、この “firmware” パーティションの仕組みを採用したことにより、”Netgearの一部機種でsysupgradeが失敗する” という問題が起きた。これはNetgear機のdts内にあった潜在的な問題が原因で、今回WG2600HPが “firmware” パーティションをipq806x targetで初めて採用したために偶然踏み抜いた模様。既に修正が行われ、snapshotと18.06のいずれも問題は解消済み。
  • メーカーファームに戻す場合、initramfsを投入した際に “firmware” パーティションをバックアップしたものを
    mtd write stock_firmware.bin firmware
    として書き込むことで可能。
    ただし、OpenWrt投入前のメーカーファームではU-Bootの環境変数が格納される “APPSBLENV” 内の設定は利用されておらず、U-Bootが持っているデフォルト値が使用されている。上記のOpenWrt導入手順では、OpenWrtにおいては “bootargs” の設定は不要であるため手順に含めていないものの、メーカーファームではbootargsでカーネルログ出力先のttyやbaudrateの指定が必要であり、もしこれが無いと何もコンソールに出力されない。
    そのため、メーカーファームに戻す場合は以下によってbootargsを追加しておく。

    fw_setenv bootargs "console=ttyHSL1,115200n8 root=mtd:rootfs rootfstype=squashfs reboot=0"
    


    このbootargsはOpenWrtにおいては無視されるため、予め追加しておいても問題ない。

  • SoCの動作クロックは 384MHz – 1,400MHz の間で負荷に応じて変動。

雑感

今回、WG2600HPが非常に厄介な仕様であったため、以前の記事で書いた通り文鎮化スレスレでメーカーファームでのアップデート作業から意図的にKernelを破損させたりと、なかなかにヒヤヒヤする作業の連続だった(最初に作業していた個体は、基板上のシリアル用ピンを修正する際に誤って破損させてしまい、文鎮化してしまったが)。factoryを作れなかった故に導入の難易度が高いことが心残りであり、そのうちなんとかしたいなとも思う。
また、偶然踏み抜いたものではあるものの、結果的にNetgear機でのトラブルを引き起こしてしまったのが若干申し訳ない。

WG2600HP(経過報告)

さて再びやり始めた新機種のサポートですが、今回は最後の1つがコケておりPRにたどり着かない状況です。

  • きっかけ

    雑記にも書きましたが、3月24日の東海道らぐ横浜当日に「何か面白そうな機種無いかな」と秋葉原に寄ってフラフラ徘徊した際、駅近くのソフマップでWG2600HPを一部部品欠損で¥6,500弱で見つけ(パネルが無いとされていたが全部揃っていた)、ipq806x機と予想されることから購入しました。

  • サポート作業

    • 流れ

      • 筐体を開ける
        ここがしんどい。WPSボタンのある側がまず黒いカバーを外すことができ、その下にさらに金属板が取り付けられたベージュとグレーの中間程度の色をしたカバーが取り付けられている。この2つ目のカバーの取り外しに手間取った。フロント側(USB, RJ-45等と反対側)のツメが銀色の帯と反対側にあり、奥まった位置にあるため上手く引っ掛けてツメを外すことができない。
        最終的に強く力を掛けた際にツメが1つ破損し、その結果大きく開くようになったのでなんとか残りのツメを外して開けた。
      • シリアルを繋ぐ
        基板上にスルーホールで出ており、ハンダ埋めも無いのであまり難しい点は無し。USBやRJ-45側から RX, TX, NC, GND, Vcc。ケーブルは TX, RX, (接続無し), GND, (接続無し)とする。
      • コンソールで色々確認する(失敗)
        WG2600HPではコンソールにパスワードが掛けられており、アクセス不可。OpenWrtベースのQSDKが使用されておりfailsafeへ落ちることはできるものの、ある程度時間が経過すると “watchdog barked!” と出て再起動されてしまい、行動が著しく制限される。そこでrootのパスワードハッシュを見つけはしたものの、パスワードまでは現状特定できずログインもできていない。
        また、U-Bootもブートを中断してコンソールに入ることなどができない上に、何らかのボタンを押しながらブートすることでinitramfsイメージを受け付けるといった機能が無いようで、ビルドしたファームを流し込むことができない。
      • とりあえずファームをビルド
        流し込む手段が見つけられていないものの、とりあえずファームをベース部分だけ組んでビルド。OpenWrtのipq806xでサポート済みの機種のうち “Qualcomm IPQ8064/AP148 (dts: qcom-ipq8064-ap148.dts)” がリファレンスボードらしくWXR-2533DHPでもこれを流用できたので、このdts等をコピーしてWG2600HP用の機種サポートを暫定的に追加する。
        mtdパーティションについてはfailsafeやbootlogから確認できていたので、それを基に定義を追加。
      • U-Bootの環境変数を弄れた
        failsafeで利用できるコマンドを見て回っていたところ、U-Bootの環境変数を表示するfw_printenv、その変更を行うfw_setenvを発見。そのまま叩いてもuciに設定が入っておらず、/etc/fw_env.config も無いのでエラーになるが、/etc/fw_env.config をAPPSBLENVパーティションで記述したところ環境変数の取得と設定を行うことができた。
      • initramfsイメージを投げ込む
        fw_setenvが利用できたので、bootcmdを書き換えてinitramfsイメージをTFTPで取らせてブートする様に変更する。
        コマンドが少々長いので、”ramboot” として分離した。rambootはWXR-2533DHPのものを参考にした。

        fw_setenv autostart yes
        fw_setenv ipaddr 192.168.10.1
        fw_setenv serverip 192.168.10.2
        fw_setenv ramboot "rootfstype=ramfs; tftpboot 0x44000000 wg2600hp.bin"
        fw_setenv bootcmd "run ramboot"
        

        ipaddrでルータ側のIPアドレスを、serveripでTFTP側のIPアドレスを設定する。
        rambootでは、rootfstypeをramfsとして指定、TFTPを利用してサーバから wg2600hp.bin を取得してメモリ上 0x44000000 にロードしてブートする。ただしこれだけではロードしただけで止まってしまうため、自動でブートも行うよう “autostart=yes” を設定する。
        bootcmdでは、rambootに設定したコマンドを実行 (run) する。

      • mtdをバックアップ
        initramfsイメージでブートできたら、弄る前に各mtdパーティションをバックアップしておく。ddしてscpでダウンロードした。
        また、WG2600HPでは バックアップしたうちの “ART” ではなく “PRODUCTDATA” パーティションにMACアドレスが格納されているため、メーカーファーム上で確認しておいた各インターフェースに割り当てられているMACアドレスと比較して始点アドレスを確認する。
      • 各種情報を確認する
        initramfsイメージでブートし、各種情報(主にGPIO周辺)を確認する。
        NECが公開しているWG2600HPのソースコードでは “CONFIG_BOARD_AKRO” として #ifdef にWG2600HPの情報が記述されており、これと合致しているかを確認する。
        WG2600HPのRJ-45ポートにPCなどとケーブルを接続し、リンク状態も確認する。すると、OpenWrtで既にサポートされている他機種とはポート構成が異なっており、ほんとか?という気持ちになった(そうリンクするんだからそれしか無いのだが)。
      • コードを修正してテスト
        確認した情報を基にコードを修正し、再度投入して正常に機能するかテスト。問題が見つかれば再度修正してトライ。
        USBポートやPCIe、各インターフェースのMACアドレス辺りを何度か修正を重ねた。
      • Flashに焼き込み
        initramfsイメージでできる作業がおおよそ完了したら、最後にFlash周りの確認のため焼き込む。
        mtdパーティション等の構成からipq806x内のTP-LINK VR2600vと同じ書き込み方法が使えると判断し、その通りに platform.sh を記述。
        initramfsイメージからsysupgradeで焼き込む前に、FlashからブートできるようにU-Bootのbootcmdを変更する。この際、bootipqを設定するだけだと、kernel自体が破損しているのであればU-Bootのコンソールに自動で落ちるものの、そうではない問題があった場合にブートが止まってしまったり、再起動を繰り返すのみで復旧不能に陥るため、rambootも残すようにする。

        fw_setenv bootcmd "run ramboot || bootipq"
        


        上記でまずrambootを受け付け、それが失敗すればbootipqを実行する。
        bootcmdを設定したらsysupgradeを実行してFlashに焼き込む。ここまでは問題無く成功。

  • 問題

    • sysupgradeで設定を引き継げない

      sysupgradeの際、本来であれば “kernel”, “rootfs” パーティションに新しいファームウェアが書き込まれると同時にバックアップされていたconfig類が書き戻されるはずが、コンソール上にメッセージは出るものの再起動すると初期状態になってしまっている。
      SPI Flash環境でのsysupgradeに通常使用される “default_do_upgrade” を実行した後に “jffs2_copy_config” を実行すればconfig類が引き継がれたものの、コードを確認しても本来であれば “default_do_upgrade” だけでできるはずであり、他に “jffs2_copy_config” を実行している機種は無い。この問題が解決できずしばらくここで作業がストップしてしまっている。
      config類がどこか別のパーティションに書き込まれてしまっているのかと確認したものの、WinMerge等でバイナリのdiffを取ってもkernelとrootfs以外に変更されたパーティションは無かった。
      もう少し追加で詳しく調べてみる予定。

  • 所感とか

    作業中、ミスによってkernelがコンソールに何も吐かない状態にしてしまい、故意にメーカーファームのkernelを破損させる羽目になるなどかなり綱渡りの作業になった(それも、kernelを破損させられずにrootfsをやってしまったらたぶんアウト)。しんどいけど楽しい。
    気になる個所はいくつかあるものの、現状問題らしい問題は上記のsysupgradeの問題1つのみ。さすがにこの状態でPR投げるわけにもいかないため、解決できずストップしてしまっている。
    それまでは(initramfsイメージを投げ込めてからは)サクサクと進んでいたため、まさかそこでコケるとは思わず早いうちにPR投げるまで行けそうと思っていた。
    今のところ解決策が全く思いつかないため、今後Forumで質問してみようかなと思う。場合によってはjffs2_copy_configでPR投げてしまおうかとも考えたものの、メンテナ氏に迷惑かけてしまうのもどうかというところがある。

WXR-2533DHP(経過報告2)

前回の経過報告から10日くらい経過し、いくらか進んだのでここで再び経過報告です。

状況

  • U-Bootのbankチェックをパスできるようになった
    • rootfs checksumがどんな値かも判明。xeditで以下の様に出すことができ、
      wxr-2533dhp_133.PNG
      Linuxでの算出方法は某氏より以下を教えて頂いた。

      od -A n -t u1 | tr -s ' ' '\n' | awk '{s+=$0}END{printf "%x", 255-s%256}'
      
    • 上記により、ブート時にU-Bootのコンソールからbootipqを叩いてチェックをスキップさせる必要が無くなった(→ 何もせずブートできる)
  • KernelのRootfsとU-BootのRootfsチェック用にrootfsボリュームを2つ作る必要が生じた
    • U-Bootは “ubi_rootfs” ボリュームのみを、OpenWrtのKernelは “rootfs” ボリュームのみをそれぞれ固定で参照しようとするため。
      • 当初U-Boot側に合わせてOpenWrt側rootfsのボリューム名をubinizeで “ubi_rootfs” に変更したが、何度試してもrootfsの認識に失敗した。結局、OpenWrt側が target/linux/generic/pending-4.9/491-ubi-auto-create-ubiblock-device-for-rootfs.patch でrootfsとして使えるボリュームを “rootfs” のみに固定していることが判明、やむなく別個で作ることにした。
      • OpenWrtビルド時に生成されるrootfsを “ubi_rootfs” にもそのまま使用するとNAND Flash上のスペースを無駄に占有する(OpenWrt側では使用されない)ため、空のフォルダ1個をsquashfs化して、そこにU-Bootのチェックをパスするのに必要なchecksumを付加するようにした。
  • U-Bootの挙動に絡み、KernelはBank1を、RootfsはBank2のモノを使用することにした
    • U-Bootが、Bank2を “破損している” と判定しない限りBank2⇒Bank1の向きで書き戻しを行い、またその際 “kernel” と “ubi_rootfs” のみの書き戻ししか行わないため。
      • WXR-2533DHPでは、メーカーファームでは当然ながらBank1の “kernel”, “ubi_rootfs”, “ubi_rootfs_data” がブートに使用される。
      • その状態でアップデートを行った場合、更新先のファームはBank1ではなくBank2に書き込み、リブートしてU-Bootのbankチェックが実行された際、イメージが異なるとしてBank2からBank1へイメージが書き込まれ、アップデートが完了する仕組みになっている。
      • OpenWrtの場合、KernelはメーカーファームでもOpenWrtでも “kernel” なのでU-Bootにより問題なくBank2⇒Bank1へ書き込まれるが、RootfsはU-Boot用の “ubi_rootfs” がU-Bootに認識され書き戻されるのみで、Bank2にあるOpenWrt用の “rootfs” は何もされない(= Bank1のrootfsが更新されない)。
      • もしOpenWrtでKernelとRootfsを両方ともBank1から起動できるようにする場合、”kernel” と “ubi_rootfs” はBank2に、”rootfs” とデータ領域の “rootfs_data” はBank1にと2か所に書き込まなければならず、手順が面倒になる。
        また、sysupgrade時も両方への書き込みが必要になり、複雑化してしまう。
      • 対して、kernelはBank1、RootfsはBank2としてしまえば、Bank2に書き込まれたOpenWrtの “kernel” とU-Boot用の “ubi_rootfs” は自動でBank1に書き込まれU-Bootはそれをブートするほか、RootfsはBank2に書き込み済みの “rootfs” を読み込ませれば良いのでだいぶ簡単になる。
      • メーカーファームと現時点でのOpenWrtファームにおけるUBIボリュームの使用状況については、雑記にまとめた。
      • ただし、ぶっちゃけ上記の雑記で改めて表にしてみると「ひどいなこれ」という感想しか出てこない。
      • というのを書きながら、’Bank1にイメージ書き込んだ後Bank2から意図的に “kernel” だけボリューム削除して破損扱いにさせれば、通常とは逆向きのBank1⇒Bank2の書き戻しが発生するから、使用するボリュームをBank1にまとめることもできるかな?’ というのが思い浮かんだ。後で試す。
  • sysupgradeまで機能するようにできた
    • WXR-2533DHPでは上の項目で長々と書いた通り “ubi_rootfs” を上手く扱わなくてはならず、その関係上OpenWrtに存在しているsysupgradeスクリプト(というかNAND向けスクリプトのnand.sh)では対応できない。そのため、いくらか引用したうえでbuffalo.shを作成し、 “ubi_rootfs” をバックアップ/書き戻しすることでsysupgradeを行えるようにした。
    • ただし、テスト回数とテスト条件はあまり多く試せていないため、確実性は不安。
    • また、上のBankの取り扱いで最後に書いた思いついたことを試す場合、再度sysupgrade用スクリプトの改変が必要になるため、どうなることやら。
  • PCI周りがエラーらしきものを吐く
    • ブート時にPCI周辺で “無線のFirmwareが読めない” というようなエラーが吐かれる。
      ただしブート完了後無線は正常に機能しているように見え、また少し検索してみても “問題ない” というような記述が見られる。

      ログ

      [   19.985388] ath10k_pci 0000:01:00.0: enabling device (0140 -> 0142)
      [   19.985940] ath10k_pci 0000:01:00.0: pci irq msi oper_irq_mode 2 irq_mode 0 reset_mode 0
      [   20.172091] ath10k_pci 0000:01:00.0: Direct firmware load for ath10k/QCA99X0/hw2.0/firmware-6.bin failed with error -2
      [   20.172147] ath10k_pci 0000:01:00.0: Falling back to user helper
      [   36.077329] firmware ath10k!QCA99X0!hw2.0!firmware-6.bin: firmware_loading_store: map pages failed
      [   36.492146] ath10k_pci 0000:01:00.0: qca99x0 hw2.0 target 0x01000000 chip_id 0x003b01ff sub 168c:0002
      [   36.492179] ath10k_pci 0000:01:00.0: kconfig debug 0 debugfs 1 tracing 0 dfs 1 testmode 1
      [   36.502471] ath10k_pci 0000:01:00.0: firmware ver 10.4.1.00030-1 api 5 features no-p2p crc32 d2901e01
      [   36.600352] ath10k_pci 0000:01:00.0: board_file api 2 bmi_id 1:1 crc32 08fa09f2
      [   37.865657] ath10k_pci 0000:01:00.0: htt-ver 2.2 wmi-op 6 htt-op 4 cal pre-cal-file max-sta 512 raw 0 hwcrypto 1
      [   37.953404] ath10k_pci 0001:01:00.0: enabling device (0140 -> 0142)
      [   37.953970] ath10k_pci 0001:01:00.0: pci irq msi oper_irq_mode 2 irq_mode 0 reset_mode 0
      [   38.156469] ath10k_pci 0001:01:00.0: Direct firmware load for ath10k/QCA99X0/hw2.0/firmware-6.bin failed with error -2
      [   38.156515] ath10k_pci 0001:01:00.0: Falling back to user helper
      [   38.307675] firmware ath10k!QCA99X0!hw2.0!firmware-6.bin: firmware_loading_store: map pages failed
      [   38.307815] ath10k_pci 0001:01:00.0: qca99x0 hw2.0 target 0x01000000 chip_id 0x003b01ff sub 168c:0002
      [   38.315640] ath10k_pci 0001:01:00.0: kconfig debug 0 debugfs 1 tracing 0 dfs 1 testmode 1
      [   38.327131] ath10k_pci 0001:01:00.0: firmware ver 10.4.1.00030-1 api 5 features no-p2p crc32 d2901e01
      [   38.389439] ath10k_pci 0001:01:00.0: board_file api 2 bmi_id 1:2 crc32 08fa09f2
      [   39.664713] ath10k_pci 0001:01:00.0: htt-ver 2.2 wmi-op 6 htt-op 4 cal pre-cal-file max-sta 512 raw 0 hwcrypto 1
      

今後

  • できればfactoryイメージを作りたいものの、単にKernelとRootfsを投入しただけではリブート後OpenWrtのKernelがRootfsを見つけられなくなるので、どうしたものか

雑感とか

  • SoC(IPQ8064)は負荷に応じてコアごとにクロックが変動していた(384MHz – 1,400MHz)
  • LuCIのページ遷移が体感的に速い
  • どこかで有線のiperf計測したい

お知らせっぽいもの

  • 今のところ今年2月のOSC 2018 Tokyo/Springにて、東海道らぐブースの場所をお借りしてWXR-2533DHPを動態展示させていただく予定です。
    色々詳しい方にご意見等頂ければと思います。

WXR-2533DHPをメーカーファームに書き戻す

弄るうえで一番重要な気がする。書くのを忘れていた。

WXR-2533DHPでのfirmware

WXR-2533DHPでは、U-Bootやデバイス固有の情報(WPS PIN、無線の事前共有鍵、MACアドレス、その他色々)を4MBのSPI Flashに持ち、KernelとRootfs、Rootfs_data は256MBのNAND Flashに持っている。

このうちNANDでは、前半128MB分が 0x0 – 0x4000000 と 0x4000000 – 0x8000000 にそれぞれ分割され、それぞれ mtd0, mtd1 として割り当てられており、それぞれに Kernel + Rootfs + Rootfs_data の同一のイメージが格納されている。ちなみに、後半128MB分は使用されず空。
ただしデータは直接mtdに書き込まれているのではなく、書き込み分散などのウェアレベリング機能を有するUBIにより “kernel”, “ubi_rootfs”, “ubi_rootfs_data” パーティションが形成され、その中にそれぞれ格納されている。

このためか、mtdに対してそのバックアップを直接

# mtd write mtd0.bin /dev/mtd0

として書き込んでも、エラーが大量に出るようになってしまう。

書き戻し

そこで、書き戻しには ubiformat または ubiupdatevol を使用する。

  • ubiformat
    mtdをUBIとしてフォーマットするコマンドではあるものの、-f オプションでイメージの書き込みも可。
    # ubiformat -f  
    

    上記コマンドを使い、メーカーファームで

    # dd if=/dev/mtd0 of=/tmp/mtd0.bin
    

    などとして取得したイメージを投入する。現状ビルドできているOpenWrt initramfsイメージ上からも可。
    例:

    # ubiformat -f mtd0.bin /dev/mtd0
    

    ただし指定したmtdがUBIでattachされている場合は書き込みができずエラーが出るため、先に ubidetach でdetachしておく。

    # ubidetach -p /dev/mtd0
    
  • ubiupdatevol
    mtd上に存在するUBI Volumeに対して、個別で更新を実行するコマンド。メーカーファームでのファームアップデートでもこれが使われていた。
    ubiformatとは異なり、先にmtdがUBIでattachされている必要がある。

    # ubiattach -p /dev/mtd0
    # ls -al /dev/ubi*
    

    /dev/ubi*_* の最初の数字は、マウントされた順番で割り当てられる。2つ目は 0: kernel, 1: ubi_rootfs, 2: ubi_rootfs_data 。
    基本はそれぞれにkernelやrootfsの単体のイメージを焼き込む。単一のイメージから位置とサイズを指定して実行することも可能。
    位置の指定は、メーカーファームではoffsetを意味する -o オプションが該当、OpenWrtでは –skip オプションが該当すると思われる。

    ubiupdatevol  
    

    例:

    ubiupdatevol /dev/ubi0_1 /tmp/ubi0_1.bin
    

    メーカーファームでのkernelやrootfsの取り出しは、/dev/ubi*_* をcatでファイルに出力することで可能だった。