BroadStation も積もれば山となる。先日 HARD OFF のジャンクコーナにて 105 円でたたき売られていたブロードバンドルータ BBR-4MG を捕獲したので早速フルボッコにしてみようと思います。とりあえずびんずめ堂さんや Thomas さん、bird.dip.jp さんの記事を参考に Linux をインストールして LED を操作するところまで。
と言っても Linux はびんずめ堂さんが既にファームウェア化してくれているので WEB 画面上から更新するだけで終わってしまいます。それでは面白くありませんのでびんずめ堂さんの Linux ソースに bird.dip.jp さんの LED ドライバを組み込んでビルドしてみます。
環境構築
ビルド環境は Linux なら何でも良いと思います。今回は Arch Linux を使用します。何はともあれびんずめ堂さんの Linux ソースをビルドできる状態にしたいところです。Buildroot を使って試行錯誤していましたが結局ビルドできず、どうしたものか?と悩んでいたところ bird.dip.jp さんの Wiki に方法が載っていました。
以下、bird.dip.jp さんの記事の通り進めていきます。
http://www.edimax.at/download/Linux-SC.zip
こちらからコンパイル済みのツールチェーンを取得します。
wget http://www.edimax.at/download/Linux-SC.zip unzip Linux-SC.zip
解凍して出てきたファイル 6114-GPL.tgz と 6114-tool-chain.tgz をさらに展開します。
tar zxf 6114-GPL.tgz tar zxf 6114-tool-chain.tgz
出来上がった EdiLinux ディレクトリはホームディレクトリに、export ディレクトリはルート直下に移動させます。
mv EdiLinux/ ~/ mv export/ /
忘れないうちに開発ツール類にパスを通しておきましょう。
PATH=$PATH:/export/tools/bin:/export/tools/mipsel-linux-uclibc/bin
ソースの修正とビルド
びんずめ堂さんからソースを頂いてきます。
wget http://www.binzume.net/library/bbr-4mg/linux-src.tar.gz tar zxf linux-src.tar.gz
展開できたら EdiLinux ディレクトリの中に既にある linux-2.4.18-adm を削除して代わりにびんずめ堂さんのソースを配置します。現在 EdiLinux の配下は状態はこんな感じです。
ls 6104IPC-BUILD AP MAKE-CONF.sh build.tmp define enter image linux-2.4.18-adm make.def mode.def target.def
びんずめ堂さんのソースから .depend ファイルを削除します。
find linux-2.4.18-adm/ -name .depend | xargs rm
私の BBR-4MG は Intel 製の Flash メモリでしたがびんずめ堂さんのソースは AMD 用になっていましたのでソースを修正します。drivers/mtd/maps/mx29lv320b.c の下の方にある "for AMD" の行をコメントにして "for CFI" の行のコメントを解除します。
vi drivers/mtd/maps/mx29lv320b.c
// mymtd = do_map_probe("amd_flash", &pnc_map); // for AMD mymtd = do_map_probe("cfi_probe", &pnc_map); // for CFI
びんずめ堂さんの解説にあるように AP ディレクトリの一部のアプリはコンパイルエラーになるので不要なものは削除しておきます。
rm -r AP/clockspeed-0.62/ rm -r AP/ppp-2.4.1/
とりあえず上記の二つを削除すればビルドが通りました。
./6104IPC-BUILD
ファームウェアに付けるバージョン情報などを聞かれるので適当に Enter を押します。ビルドが終わると linux-2.4.18-adm の下に vmlinux.bin が作成されていますのでこれを BBR-4MG に転送すれば Linux が起動するはずです。
LED ドライバの組み込み
さて問題の LED ドライバです。まずは bird.dip.jp さんのところからドライバを頂いてきます。driver.zip を展開すると led.c と led.h が出てきます。これをびんずめ堂さんのソースに組み込んでみます。
cd linux-2.4.18-adm/arch/mips/am5120 ls 5120_int.c 5120_rtc.c Makefile cmdline.c irq.c led.c led.o memory.o mipsIRQ.o pci.o prom.o serial.o setup.c time.c 5120_int.o 5120_rtc.o am5120.o cmdline.o irq.o led.h memory.c mipsIRQ.S pci.c prom.c serial.c serial_ref.c setup.o time.o
念のためバックアップを取り、先ほど展開した driver の配下にある led.c と led.h に差し替えます。
mv led.c led.c.bak mv led.h led.h.bak cp ~/driver/led.c ./ cp ~/driver/led.h ./
さすがにこれだけだとエラーが出てコンパイルできないようですね。
led.c:81:38: asm-mips/adm5120/adm5120.h: そのようなファイルやディレクトリはありません
仕方が無いのでソースを修正してみます。led.c の 81 行目付近の include のパスです。
#include <asm-mips/adm5120/adm5120.h>
#include <asm-mips/am5120/adm5120.h>
adm5120 というディレクトリ名の部分のみ am5120 に変更します。これで linux-2.4.18-adm ディレクトリに移動して make を走らせます。
cd ~/EdiLinux/linux-2.4.18-adm/ make
コンパイルが通りました。
BBR-4MG に転送
出来上がった vmlinux.bin を XMODEM で転送します。BBR-4MG をシリアル接続して起動します。
BBR-4MG が起動したらすぐに適当なキーを押すと画面が止まります。ここで "!" を押すと管理者メニューが表示されますので "m" キーを押して転送先のアドレス "0x80002000" を入力します。
転送待ちの状態になったら vmlinux.bin を転送します。完了したら「y」を押し、ジャンプ先のアドレス「0x800026d8」を入力すると運が良ければ Linux が起動します。
=========================================================== BUFFALO BBR-4MG Loader v1.80 build Dec 12 2003 10:13:58 Broad Net Technology, INC. =========================================================== manu_id=6000 chip_id=401A INTEL TE28F160C3-B bottom boot 16-bit mode found Copying boot params.....DONE Press any key to enter command mode ... Press Reset button to enter Tiny_ETCPIP_KERNEL ... [BBR-4MG Boot]:! Enter Administrator Mode ! ====================== [U] Upload to Flash [E] Erase Flash [G] Run Runtime Code [M] Upload to Memory [R] Read from Memory [W] Write to Memory [T] Memory Test [Y] Go to Memory [A] Set MAC Address [#] Set Serial Number [V] Set Board Version [P] Print Boot Params ====================== [BBR-4MG Boot]:m RAM upload destination: (default:0x80001000) : 0x80002000 Starting XMODEM download...(press Enter to abort) CC [BBR-4MG Boot]:y Go to Memory Address: (default:0x1000050) : 0x800026d8 LINUX started... ADM5120 Demo board CPU revision is: 0001800b Primary instruction cache 8kb, linesize 16 bytes (2 ways) Primary data cache 8kb, linesize 16 bytes (2 ways) Linux version 2.4.18-MIPS-01.00 (root@archlinux) #1125 2014a1年 1a?月 10a?日 e?T am5120_setup() starts. System no PCI BIOS Determined physical RAM map: memory: 006a3000 @ 0015d000 (usable) On node 0 totalpages: 2048 zone(0): 2048 pages. zone(1): 0 pages. zone(2): 0 pages. Kernel command line: root=/dev/ram0 console=ttyS0 CPU clock: 175MHz Calibrating delay loop... 174.48 BogoMIPS Memory: 6656k/6796k available (1116k kernel code, 140k reserved, 72k data, 52k ) Dentry-cache hash table entries: 1024 (order: 1, 8192 bytes) Inode-cache hash table entries: 512 (order: 0, 4096 bytes) Mount-cache hash table entries: 512 (order: 0, 4096 bytes) Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes) Page-cache hash table entries: 2048 (order: 1, 8192 bytes) Checking for 'wait' instruction... available. POSIX conformance testing by UNIFIX Linux NET4.0 for Linux 2.4 Based upon Swansea University Computer Society NET3.039 Initializing RT netlink socket Starting kswapd HDLC line discipline: version $Revision: 1.1.1.1 $, maxframe=4096 N_HDLC line discipline registered. block: 64 slots per queue, batch=16 RAMDISK driver initialized: 16 RAM disks of 3072K size 1024 blocksize loop: loaded (max 8 devices) ADM5120 Switch Module Init initrd image at bfd10000 ADM5120 flash mapping: 200000 at bfc00000 NET4: Linux TCP/IP 1.0 for NET4.0 IP Protocols: ICMP, UDP, TCP IP: routing cache hash table of 512 buckets, 4Kbytes TCP: Hash tables configured (established 512 bind 512) ip_conntrack version 2.1 (64 buckets, 512 max) - 360 bytes per conntrack ip_tables: (C) 2000-2002 Netfilter core team NET4: Unix domain sockets 1.0/SMP for Linux NET4.0. adm5120gpio: Checking GPIO pins: GPIO 0: OUTPUT normal GPIO 1: OUTPUT inverted GPIO 2: OUTPUT normal GPIO 3: OUTPUT inverted GPIO 4: INPUT: 0 normal GPIO 5: INPUT: 0 normal GPIO 6: INPUT: 0 normal GPIO 7: INPUT: 0 normal GPIO 8: LINK_ACT GPIO 9: SPEED GPIO 10: DUPLEX_COL GPIO 11: LINK_ACT GPIO 12: SPEED GPIO 13: DUPLEX_COL GPIO 14: LINK_ACT GPIO 15: SPEED GPIO 16: DUPLEX_COL GPIO 17: LINK_ACT GPIO 18: SPEED GPIO 19: DUPLEX_COL GPIO 20: LINK_ACT GPIO 21: SPEED GPIO 22: DUPLEX_COL adm5120gpio: ADM5120 GPIO driver V2.5 ready. RAMDISK: bzip2 compressed image found at block 0 VFS: Mounted root (ext2 filesystem). Freeing prom memory: 0kb freed Freeing unused kernel memory: 52k freed init started: BusyBox v1.00 (2005.10.10-01:34+0000) multi-call binary Starting pid 10, console /dev/ttyS0: '/etc/init.d/rcS' mount: Mounting /dev/mtd1 on /flash failed: No such device info, udhcpc (v0.9.9-pre) started info, udhcpc (v0.9.9-pre) started warning, Could not load seed from /dev/urandom: No such file or directory debug, Sending discover... debug, Sending select for 192.168.0.81... warning, Could not load seed from /dev/urandom: No such file or directory info, Lease of 192.168.0.81 obtained, lease time 172800 debug, Sending discover... deleting routers route: SIOC[ADD|DEL]RT: No such process adding dns 192.168.0.1 debug, Sending discover... debug, Sending discover... Fri Jan 10 20:53:21 JST 2014 Starting pid 72, console /dev/ttyS0: '/bin/sh' BusyBox v1.00 (2005.10.10-01:34+0000) Built-in shell (ash) Enter 'help' for a list of built-in commands. # Jan 10 20:53:21 crond[73]: crond 2.3.2 dillon, started, log level 8
LED を光らせる
GPIO のドライバがうまく組み込まれていれば起動ログに GPIO の情報が表示されているはずです。下記のコマンドでも確認することができます。
cat /proc/driver/led 0: OUTPUT normal 1: OUTPUT inverted 2: OUTPUT normal 3: OUTPUT inverted 4: INPUT: 0 normal 5: INPUT: 0 normal 6: INPUT: 0 normal 7: INPUT: 0 normal 8: LINK_ACT 9: SPEED 10: DUPLEX_COL 11: LINK_ACT 12: SPEED 13: DUPLEX_COL 14: LINK_ACT 15: SPEED 16: DUPLEX_COL 17: LINK_ACT 18: SPEED 19: DUPLEX_COL 20: LINK_ACT 21: SPEED 22: DUPLEX_COL
次に mknod でデバイスファイルを作成します。
i=0 while [ $i != 23 ] do mknod /dev/gpio$i c 167 $((i++)) done
LED として使用可能なのは 8 から 22 番までです。led.c によると下記のような状態を設定できるようです。
- 0 = INPUT
- 1 = OUTPUT
- 2 = OUTPUT_1
- 3 = OUTPUT_0
- 4 = LINK
- 5 = SPEED
- 6 = DUPLEX
- 7 = ACTIVITY
- 8 = COLLISION
- 9 = LINK_ACT
- 10 = DUPLEX_COL
- 11 = 10M_ACT
- 12 = 100M_ACT
- 13 = FLASH
LED を光らせるには "LED SWITCH" で OUTPUT モードに設定し "LED ON"、"LED OFF" で点灯・消灯を切り替えます。ON と OFF を反転させるには "LED INVERT" を使用します。
echo "LED SWITCH 2">/dev/gpio20 echo "LED OFF">/dev/gpio20 echo "LED ON">/dev/gpio20
各 LED は隣のピンの状態によって緑と橙に切り替えることができます。
echo "LED SWITCH 3">/dev/gpio21 echo "LED OFF">/dev/gpio21 echo "LED ON">/dev/gpio21
とこんな感じで LED を操作するところまではできましたがこの状態ですと電源を落としたらすべて消えてしまいますので、なんとか Flash メモリにインストールする方法を考えてみます。
Flash メモリにインストールする
びんずめ堂さんの記事を見ると vmlinux.bin の先頭に 0x80002000 に移動して 0x800026d8 にジャンプするプログラムを埋め込み、ZIP で固めて CRC32 を計算し 512 KB になるように末尾を 0xFF で埋めてサイズやら CRC32 やらを末尾に書き込めば良いと書かれています。「やら」というのがやっかいですがびんずめ堂さんのカーネルイメージを調べてみたところ末尾はファイルサイズ + "00" + "12345678" + CRC32 になっているようです。
私は Stirling というバイナリエディターを使わさせて頂きました。初めはびんずめ堂さんの記事に従って色々いじくり回しておりましたが、結局ファイルサイズや CRC32 は無くても動くことがわかりました。
vmlinux.bin の先頭にプログラムを埋め込む作業だけで済みそうです。もちろん私はアセンブリなど書いたことがありませんのでびんずめ堂さんのカーネルイメージの先頭 0x000013FF までをバイナリエディターで切り取って vmlinux.bin の先頭のバイナリと差し替えました。
そして vmlinux.bin を SOHO.BIN にリネームして zip コマンドで圧縮して /dev/mtd3 に転送します。ファイル名を SOHO.BIN にしておかないとうまく動きませんでした。また、TFTP による転送では成功率が低かったため XMODEM で転送しました。
バイナリ時計を動かす
せっかく LED を操作することができるようになったので、何か使い道は無いかと考えてみたところ時間が分かりにくくてお洒落なバイナリ時計を作ってみることにします。と言っても使えそうな LED が 5 つしかありませんので 31 までしか数えることができません。緑と橙で区別するとして 60 秒ならなんとか行けそうです。
echo "LED SWITCH 2">/dev/gpio8 echo "LED SWITCH 3">/dev/gpio9 echo "LED SWITCH 2">/dev/gpio11 echo "LED SWITCH 3">/dev/gpio12 echo "LED SWITCH 2">/dev/gpio14 echo "LED SWITCH 3">/dev/gpio15 echo "LED SWITCH 2">/dev/gpio17 echo "LED SWITCH 3">/dev/gpio18 echo "LED SWITCH 2">/dev/gpio20 echo "LED SWITCH 3">/dev/gpio21 while : do a=$(date +"%S") b=$(expr $a / 30) c=$(expr $a % 30) if [ $b -eq 0 ]; then echo "LED OFF">/dev/gpio9 echo "LED OFF">/dev/gpio12 echo "LED OFF">/dev/gpio15 echo "LED OFF">/dev/gpio18 echo "LED OFF">/dev/gpio21 else echo "LED ON">/dev/gpio9 echo "LED ON">/dev/gpio12 echo "LED ON">/dev/gpio15 echo "LED ON">/dev/gpio18 echo "LED ON">/dev/gpio21 fi if [ $(($c & 1)) -eq 0 ]; then echo "LED OFF">/dev/gpio8 else echo "LED ON">/dev/gpio8 fi if [ $(($c & 2)) -eq 0 ]; then echo "LED OFF">/dev/gpio11 else echo "LED ON">/dev/gpio11 fi if [ $(($c & 4)) -eq 0 ]; then echo "LED OFF">/dev/gpio14 else echo "LED ON">/dev/gpio14 fi if [ $(($c & 8)) -eq 0 ]; then echo "LED OFF">/dev/gpio17 else echo "LED ON">/dev/gpio17 fi if [ $(($c & 16)) -eq 0 ]; then echo "LED OFF">/dev/gpio20 else echo "LED ON">/dev/gpio20 fi sleep 1 done
こんな感じで適当にシェルを書いて動かしてみたところ、少しだけ楽しい気持ちになれました。httpd が入っているので簡単な WEB サーバーとして使ってみたり、100Mbps ですがハブとして使ってみたり、他には wget と二進数で簡単な温度計、LED の色で天気予報、cron と ping でサーバー監視などはできるかもしれません。
で?っていうツッコミは勘弁してください。
バイナリをいじるなんてそうそうしないですよね。
昔、画像に任意のJavaScriptを埋め込めるか試した時に、少し使ったような…
サクっと書かれてますが、読まれたコード量は私からしたら半端無さそうです!
> 昔、画像に任意のJavaScriptを埋め込める
一体、何をなさろうとしていたのか、気になりますw
今回参考にさせていただいた元のサイトの人たちはガチで半端ない感じでした。
私はコードを読むのは好きですが、組み込み系の知識がないので全く理解できず、むっちゃ時間がかかりましたw
でも 105 円でここまで遊べたらお得ですね。
画像もアップされるポータルサイトみたいなのを作っていた時に、セキュリティ上ちょっと調べまして。
当時は確か画像内のコメント欄にJSが書けてIEでは実行できたような…
知識なしで挑んだんですか、スゲー!
調べてみると,gif でバッファオーバーランを利用してプログラムを実行させる手法が存在したようです.
当然正規ではなく,ブラウザクラッシャー的な悪意ある動作だったようですが.
最近だと svg は javascript を正式に埋め込めるみたいですね.
そういえば昔、そんなセキュリティホールが話題になってましたね。
なるほど、スッキリしましたw
話が続いていたのですね ^^
当時チェックしたのはこの画像で、IEでJSが実行できました。今(IE11)ではさずがに大丈夫でした。
http://www.tokumaru.org/d/images/20070717_0.png
テキストエディタでファイルを見ると、先頭のJSコードを確認できると思います。
IEのバージョン移行期だったので、特に対処しませんでした…
gifの話は知りませんでした。勉強になります。