仙石浩明の日記

2008年4月1日

本日4月1日、KLabエージェント株式会社を設立しました

本日4月1日、KLab株式会社の 100% 子会社として、
KLabエージェント株式会社を設立いたしました。

DSAS開発者の部屋を見て、 「いっしょにDSASをつくりたい」と言ってくださるかたは、 おかげさまで徐々にですが増えつつあります。 技術が心の底から好きで、 自身のスキルを最大限伸ばすにはどんな会社がいいのか真剣に考え、 そして KLab が考える 「技術者の成長にとって一番役に立つ会社」に共感して頂けるかたには、 ぜひ仲間になって頂きたいですし、 そういった方々に応募していただけるのは大変ありがたいことです。

ところが!

DSAS開発者の部屋を見て、 DSAS開発者と一緒に働きたいと希望していながら、 何を血迷ったか (失礼)、 転職斡旋会社に KLab への転職を依頼するかたが、 少なからずいらっしゃいます。

一般論でいえば、 転職斡旋会社 (正式名称で言えば、職業紹介会社) に求職者が登録するのは、 どの会社が自分に適しているか探しきれないから、ですよね? 世の中には星の数ほど会社があり、 個人の力では自分に適した会社を探しきれないからこそ、 職業紹介会社の存在意義があるわけです。

すでに転職したい会社が決まっているなら、 その会社に直接応募したほうが話が早いですし、 「転職エージェントは、誰の『エージェント』なのか?」ということを考えれば、 実は「話が早い」どころではないことが分かるはずだと思うのです。 したがって、 転職したい会社が決まっているのに転職エージェントを利用するというのは、 百害あって一利無し (暴言) であるはずなのですが、 私ごときには推し量ることができない、 海よりも深い理由が応募者にはきっとあるのでしょう。

そこで、一計を案じました。 KLab に直接応募するのをためらっている人のために、 KLab への転職を斡旋する会社を作ろう。 名付けて「KLabエージェント株式会社」。 もちろん、職業安定法が定める有料職業紹介事業者 (求人企業から斡旋料を頂くので、求職者は無料) ですから、 KLab 以外の求人企業への職業紹介も行ないますが、 一番の強みはもちろん KLab への転職斡旋が最速であること。 なんたってオフィスが KLab 内にありますから、 採用面接のスケジュール調整から待遇等の条件交渉まで一気通貫、 応募者にとって最も有利な KLab への転職をお約束します。

登録は、 担当者宛に直接メールで 今すぐ! お申し込み下さい。

KLabエージェント株式会社
代表取締役 CEO & CTO
& 職業紹介責任者
仙石浩明
Filed under: 技術者の成長 — hiroaki_sengoku @ 18:00
2008年3月19日

フレッツ・ドットネットを解約したら、フレッツ網 router へ ping6 できなくなった!

昨年12月26日に、 NTT東日本から 「BフレッツにおけるIPv6映像視聴等機能の標準装備について」 というお知らせが来た。 3月3日より、 「Bフレッツ」に IPv6 映像視聴等機能を標準装備するので、 フレッツ・ドット・ネットの契約が不要になるとのこと。

現在、IPv6映像視聴等機能は「フレッツ・ドットネット」にて 提供しておりますが、 平成20年3月3日(月)以降は、 ブロードバンド映像サービスのみ をご利用の場合は、 「フレッツ・ドットネット」のご契約が不要になります。 これにより解約を希望されるお客さまにつきましては、 平成20年3月3日(月) より※3受付を開始いたします。  なお、ブロードバンド映像サービス以外で、 「FdNネーム」「FdNディスク」「FdNディスクビューセレクト」「FdNナンバー」等 「フレッツ・ドットネット」サービス※4をご利用の際には、 引き続き「フレッツ・ドットネット」のご契約が必要となりますのでご注意ください。

私は IPv6 機能のためだけに「フレッツ・ドットネット」を契約していて、 「FdNネーム」「FdNディスク」「FdNディスクビューセレクト」「FdNナンバー」等の サービスを利用したことはない (「ブロードバンド映像サービス」も利用していない) ので、 フレッツ・スクウェアトップから、 サービス申込受付を選んで、「フレッツ・ドットネット」を解約した。

ところが!

フレッツ網側の v6 ルータが ping に反応しなくなった。

senri % ping6 -n router.flets.gcd.org
PING router.flets.gcd.org(2001:c90:XXXX:XXXX:2d0:2bff:fe30:b91a) 56 data bytes
From 2001:c90:XXXX:XXXX:2d0:2bff:fe30:b91a icmp_seq=1 Destination unreachable: Administratively prohibited
From 2001:c90:XXXX:XXXX:2d0:2bff:fe30:b91a icmp_seq=2 Destination unreachable: Administratively prohibited

--- router.flets.gcd.org ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1000ms

ちなみに、 この v6 ルータからの router advertisement は正常に流れてきている:

senri # tcpdump -i eth1 -vvv ip6
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
        ...
13:02:02.904899 fe80::2d0:2bff:fe30:b91a > ff02::1: icmp6: router advertisement(chlim=64, pref=medium, router_ltime=1800, reachable_time=0, retrans_time=0)(src lladdr: 00:d0:2b:30:b9:1a)(mtu: mtu=1500)[ndp opt] [class 0xe0] (len 64, hlim 255)

v6 ルータ越えの通信が全て禁止されてしまったらしく、 フレッツ網に接続している他サイトとの IPv6 通信も同様に禁止されて (Administratively prohibited) しまった。 例外は、フレッツ・スクウェアv6 へのアクセス:

senri % ping6 -n flets-v6.jp
PING flets-v6.jp(2001:c90:ff:1::1) 56 data bytes
64 bytes from 2001:c90:ff:1::1: icmp_seq=1 ttl=52 time=5.05 ms
64 bytes from 2001:c90:ff:1::1: icmp_seq=2 ttl=52 time=4.55 ms

--- flets-v6.jp ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 4.554/4.803/5.053/0.258 ms

おそらく「ブロードバンド映像サービス」を提供するサーバへの IPv6 通信も 許可されているのだろう。 つまり、 「BフレッツにIPv6映像視聴等機能を標準装備」 という NTT東日本の発表のココロは、 IPv6 映像サービスへの IPv6 通信*のみ*許可するということであって、 それ以外の IPv6 通信は対象外ということのようだ。

「フレッツ・ドットネット」サービスの概要には、 「フレッツ・ドットネットサービス機能一覧」として、

・FdNネームが1つ利用できます。
・FdNディスク(100MB)で、ファイル共有が利用できます。
・FdNディスク(100MB)には、最大10のグループメンバーを登録できます。
※NTT東日本が無料で提供する専用ソフトウェア「FLET'S.Netメッセンジャーにより、 ファイル転送やビデオチャットが利用できます。

が列挙されているのみであって、 IPv6 通信の許可/不許可について言及していないのは、 とてもミスリーディングな記述だと思う。

慌てて再度フレッツ・ドットネット契約を (フレッツ・スクウェアで) 申込むと、 10分ほどで再び IPv6 通信ができるようになった:

senri % ping6 -n router.flets.gcd.org
PING router.flets.gcd.org(2001:c90:XXXX:XXXX:2d0:2bff:fe30:b91a) 56 data bytes
64 bytes from 2001:c90:XXXX:XXXX:2d0:2bff:fe30:b91a: icmp_seq=1 ttl=64 time=3.11 ms
64 bytes from 2001:c90:XXXX:XXXX:2d0:2bff:fe30:b91a: icmp_seq=2 ttl=64 time=0.920 ms

--- router.flets.gcd.org ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.920/2.019/3.118/1.099 ms

フレッツ網を経由した IPv6 通信を利用しているかたは、 たとえフレッツ・ドットネットサービスを利用していなくても、 フレッツ・ドットネットを解約すべきではないので、 ご注意のほどを!

Filed under: IPv6,システム構築・運用 — hiroaki_sengoku @ 15:32
2008年3月14日

HP ProLiant ML115 と DELL PowerEdge SC440 を買ってみた hatena_b

HP と DELL がエントリ・サーバ (タワー型) のキャンペーン販売を行なっていたので、 試しに買ってみた。 どちらも 2万円以下。

HP ProLiant ML115 DELL PowerEdge SC440
価格 15,750円 (21,000円割引) 19,800円 (46,875円割引)
プロセッサ AMD Athlon 3500+ Pentium Dual-Core E2180
チップセット nVidia MCP55S Pro Intel 3000
グラフィック Matrox G200e (ServerEngines) ATI ES1000
メモリ PC2-5300 ECC Unbuffered DDR2 SDRAM 512MB
HDD 80GB SATA 7200rpm
光学ドライブ TSSTcorp CD-ROM TS-H192C TSSTcorp DVD-ROM TS-H352C

PowerEdge というと (ラック・マウント型の) 爆音サーバのイメージが強かったので、 自宅で 24時間通電は難しいのではないかと思っていたのだが、 普通のデスクトップPC 並に静かで驚いた。 ProLiant のほうは、爆音というほどではないがそれなりにファンの音がする。

ProLiant ML115 は、 ビデオ・メモリが 2MB しかなくて画面の解像度の限界が 1024x768 16bit だったり、 光学ドライブが DVD でなかったり、 PCI が 3.3V 専用だったりと、 デスクトップPC として使うには少々難がある (もちろんサーバとして使う場合は問題無い)。

それに比べると PowerEdge SC440 は、 デスクトップPC としても使える。 手持ちのサウンド・カード Vortex2 SQ2500 (5V PCI なので ProLiant ML115 では使用不可) を差して Ubuntu をインストールしてみた。 ただし、DRI (Direct Rendering Infrastructure) は使えないので、 ビデオ再生などには向かない。

また、PowerEdge SC440 は ECC 付メモリしか使えないので、 安価なメモリを使いたい場合は不便。 一方 ProLiant ML115 はECC 無しメモリも利用できるので、 私は ProLiant ML115 の 512MB ECC 付 DDR2/667 メモリを PowerEdge SC440 へ移し、 ProLiant ML115 には、 4800円で購入した KINGBOX 1GB ECC 無し DDR2/800 2枚組を差して使っている。

Filed under: ハードウェアの認識と制御 — hiroaki_sengoku @ 08:27
2008年1月31日

リモートの p0f (passive fingerprinting) の結果を参照してスパム対策を行なう hatena_b

p0f は、 通信相手の OS を受動的に特定するツールで、 迷惑メール送信などの スパム行為を行なう「敵」を知る手段として有用である。 例えば、もし (あくまで仮定の話だが) 受信するメールのほとんどすべてが Linux や FreeBSD などの UNIX 系サーバから送信されるメールであって、 Windows マシンから送られてきたメールのほとんどすべてが迷惑メールであったなら、 Windows マシンからのメールを排除するという対策は合理的なものとなるだろう。

もちろん、Windows を使ってマトモなメールを送ってくるケースもあるだろうから、 Windows から送られたメールを全て排除するのは現実的ではないが、 p0f での判定結果と、 その他の手段 (例えば送信元 IP アドレス) での判定結果を組合わせて 迷惑メールであるか否かの判断を行なえば、 より精度の高い迷惑メール排除が可能になる。

ところが、 p0f は通信相手から送られてくる IP パケットを元に、 通信相手の OS を特定するツールであるから、 間にファイアウォールや NAT (IPアドレス・ポート変換) を行なう機器があると、 通信相手ではなくファイアウォールや NAT について調べてしまう。 だから、メールを受信するサーバがファイアウォールの内側にある場合は、 意味ある結果が得られないし、 外側にある場合だとメールを受信するサーバとは別の場所 (つまりファイアウォールの内側) で スパム判定を行ないたくなるものだろう。 例えばメールサーバは DMZ 上にあるが、 迷惑メール判定は LAN 内のマシンで行ないたい場合など。

私の個人サイト GCD は、 b フレッツに PPPoE 接続している。 p0f は調べる通信のインタフェース名を -i オプションで指定する必要があるが、 (1) PPPoE だからインタフェース名 (ppp0~) が変わることがある。 また、 PPPoE を行なうゲートウェイマシンは二台ある (冗長構成) ので、 (2) アクティブ側で p0f を実行しないと意味がない。 さらに、 メールサーバは (メールボックスを一ヶ所にまとめたかったので) 一台だけであり、 (3) 異なるサーバ上 (アクティブ側のゲートウェイ) で動いている p0f の結果を メールサーバから参照しなければならない。

以上 (1) ~ (3) の 3点を満たすための構成を考えてみた。

まず (1) と (2) は、pppd の ip-up スクリプトから p0f を実行すればよい。 例えば、ip-up で

command=$0
interface=$1
        ...
case $command in
    *ip-up)
        p0f -i $interface -Q /var/run/p0f-sock \
            'port 25 and (not src net 192.168.0.0/16)' \
            -u stone -d -t -o /var/log/p0f.log
        ;;
    *ip-down)
        killall p0f
        ;;
esac

などと p0f を起動し、ip-down で p0f を終了させる。 これでアクティブ側のゲートウェイ上でのみ p0f が動く。

p0f による判定結果は、 p0f の -Q オプションで指定した UNIX ドメイン・ソケット (上記の例では、 /var/run/p0f-sock) を介して 問合わせることができるが、 UNIX ドメイン・ソケットなので当然のことながら 別のマシンからは問合わせることができない。 そこで stone に転送させる:

stone /var/run/p0f-sock 12345 &

アクティブ側のゲートウェイは、 仮想ルータの IP アドレス 192.168.1.1 を持っているので、 「192.168.1.1:12345」へアクセスすれば、 それを stone が /var/run/p0f-sock へ中継してくれるので、 (3) p0f の結果を参照できる。

p0f の結果を参照するサンプルプログラムとして、 p0f には perl で書かれた p0fq.pl と、 C で書かれた p0fq.c が付属しているが、 あいにくどちらも UNIX ドメイン・ソケットにしか対応していない (当たり前)。 ちょっといじってリモート上の p0f へ (stone 経由で) アクセスできるようにしてみる。

p0fq.pl へのパッチ:

--- test/p0fq.pl.org        2006-08-21 23:11:10.000000000 +0900
+++ test/p0fq.pl        2008-01-31 08:00:14.652880068 +0900
@@ -30,8 +30,14 @@
                  $src->intip(), $dst->intip(), $ARGV[2], $ARGV[4]);
 
 # Open the connection to p0f
-my $sock = new IO::Socket::UNIX (Peer => $ARGV[0],
+my $sock;
+if ($ARGV[0] =~ /^[\-\w]+:\d+$/) {
+    $sock = new IO::Socket::INET (PeerAddr => $ARGV[0],
                                  Type => SOCK_STREAM);
+} else {
+    $sock = new IO::Socket::UNIX (Peer => $ARGV[0],
+                                  Type => SOCK_STREAM);
+}
 die "Could not create socket: $!\n" unless $sock;
 
 # Ask p0f

「IO::Socket::UNIX」を「IO::Socket::INET」に変更するだけで済む。

p0fq.c へのパッチ:

--- test/p0fq.c.org        2006-08-21 21:29:49.000000000 +0900
+++ test/p0fq.c        2008-01-31 08:05:55.499326450 +0900
@@ -16,6 +16,7 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <netdb.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -40,6 +41,7 @@
   struct p0f_response r;
   _u32 s,d,sp,dp;
   _s32 sock;
+  char *str;
   
   if (argc != 6) {
     debug("Usage: %s p0f_socket src_ip src_port dst_ip dst_port\n",
@@ -55,12 +57,37 @@
   if (!sp || !dp || s == INADDR_NONE || d == INADDR_NONE)
     fatal("Bad IP/port values.\n");
 
+  if ((str=strchr(argv[1], ':'))) {
+    struct addrinfo *ai = NULL;
+    struct addrinfo hint;
+    int err;
+    *str++ = '\0';
+    hint.ai_flags = 0;
+    hint.ai_family = AF_INET;
+    hint.ai_socktype = SOCK_STREAM;
+    hint.ai_protocol = IPPROTO_TCP;
+    hint.ai_addrlen = 0;
+    hint.ai_addr = NULL;
+    hint.ai_canonname = NULL;
+    hint.ai_next = NULL;
+    err = getaddrinfo(argv[1], str, &hint, &ai);
+    if (err) {
+      if (err == EAI_SYSTEM) pfatal("getaddrinfo");
+      else fatal("getaddrinfo(%s,%s): %s\n",
+                 argv[1], str, gai_strerror(err));
+    }
+    memcpy(&x, ai->ai_addr, ai->ai_addrlen);
+    sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+    freeaddrinfo(ai);
+    if (sock < 0) pfatal("socket");
+  } else {
   sock = socket(PF_UNIX,SOCK_STREAM,0);
   if (sock < 0) pfatal("socket");
 
   memset(&x,0,sizeof(x));
   x.sun_family=AF_UNIX;
   strncpy(x.sun_path,argv[1],63);
+  }
 
   if (connect(sock,(struct sockaddr*)&x,sizeof(x)))  pfatal(argv[1]);
 

getaddrinfo を呼び出すための準備に行数を費やしているので 複雑に見えるかも知れないが、 本質は プロトコル・ファミリ (protocol family) を AF_UNIX から AF_INET に変更しただけである。

(p0f を実行しているマシンとは異なるマシン上で) p0fq を実行してみる:

% p0fq 192.168.1.1:12345 81.36.137.136 2943 60.32.85.220 25
Genre    : Windows
Details  : 2000 SP4, XP SP1+
Distance : 21 hops
Link     : pppoe (DSL)

上記は、 メール送信元 (81.36.137.136 のポート 2943番) が GCD の MX (60.32.85.220 のポート 25番) へメールを送ってきた通信の p0f による判定結果。 メールサーバで、 メールヘッダにメール送信元のポート番号も出力するようにしておけば、 メールを受信するユーザが自前のメール振り分けプログラム (procmail など) を使って p0f の判定結果を参照できる点がミソ。

81.36.137.136 はスペインのプロバイダの IP アドレスらしいが、 逆引きしてみると 136.Red-81-36-137.dynamicIP.rima-tde.net となるので 動的に割当てられているアドレスなのだろう。 これは p0f の結果に pppoe (DSL) と出ていることと符合する。 そして Windows 2000 SP4 か Windows XP SP1 以降を使って 送信していることが分かる。

Filed under: システム構築・運用 — hiroaki_sengoku @ 08:55
2008年1月22日

BIOS アップデートにより、ハードディスクが Power-Up In Standby 状態になっていても起動できるようになった hatena_b

1/9 以降、Windows VISTA 搭載 レッツノートのハードディスクが突然死する可能性がある」問題を解決するための BIOS が公開された。

レッツノート (1/21):

本BIOSの導入によって現象を回避することが可能ですが、 詳細が判明次第、弊社Webサイトにてご報告いたしますので、 引き続き弊社Webサイトからお知らせを覧いただきますようお願いします。
ただし、本現象がすでに発生している場合は、 対策のBIOSアップデートプログラムを導入できません。
大変お手数ですが、下記の修理相談窓口に修理のご相談をお願いします。

Lenovo ThinkPad (1/15):

注意:Windows Vistaを使用しているシステムで、 電源投入時に"2100: Initialization error on HDD0 (Main hard disk drive)"と 表示され、 HDDから起動できなくなることがある問題を修正しました。

レッツノートの BIOS アップデートは Windows 上から実行する必要があるので、 「本現象がすでに発生している場合は」、 まず「Windows VISTA 用の更新プログラム KB943899 が原因で突然死したハードディスクを復旧させる方法」などを用いてハードディスクをスピン・アップさせ、 Windows を正常起動させておく必要がある。 「修理相談窓口に修理のご相談を」するのは「大変お手数」なので、 ハードディスク以外の方法 (USB メモリからの起動など) で 起動する手段を提供すべきだと思うのだが...

さっそくレッツノートで BIOS アップデートを行なってみた。

試しに、 ハードディスクを故意に Power-Up In Standby 状態にしてみる。 すなわち、 「Windows VISTA 用の更新プログラム KB943899 が原因で突然死したハードディスクを復旧させる方法」 の 「お手軽パック」などを使って Linux を起動し、 hdparm コマンドを使って Power-Up In Standby 状態にしてみる:

# mount -t vfat /dev/sdb1 /mnt
# /mnt/hdparm -s1 /dev/sda

/dev/sda:
Use of -s1 is VERY DANGEROUS.
This requires BIOS and kernel support to recognize/boot the drive.
Please supply the --yes-i-know-what-i-am-doing flag if you really want this
Program aborted
# 

おお、fool proof 機能付とは、なかなか親切なコマンドだ。 とても危険なので、 「何をしようとしているか分かっている」場合のみ、 「--yes-i-know-what-i-am-doing」オプションを付けて再実行する:

# /mnt/hdparm -s1 --yes-i-know-what-i-am-doing /dev/sda

/dev/sda:
 setting power-up in standby to 1 (on)
# /mnt/hdparm -I /dev/sda | grep Power-Up
           *    Power-Up In Standby feature set
# 

これで、ハードディスクが Power-Up In Standby 状態になった。 つまり電源投入時にスタンバイ・モードに入り、 明示的に spin up 命令を送らない限りは回転を始めない。 だから、 レッツノートの以前の BIOS ではハードディスクを認識できず起動に失敗していた。

Ctrl-Alt-Del を押して再起動すると、 ハードディスクから正常にブートした。 再び「お手軽パック」を使って Linux を起動し、 ハードディスクの状態を確認してみる:

# /mnt/hdparm -I /dev/sda | grep Power-Up
                Power-Up In Standby feature set
# 

Power-Up In Standby 機能が無効になっていた。 新しい BIOS は、 ハードディスクに spin up 命令を送るだけでなく、 Power-Up In Standby 機能を無効にする命令も送っているようだ。

Filed under: ハードウェアの認識と制御 — hiroaki_sengoku @ 11:02
2008年1月18日

Windows VISTA 用の更新プログラム KB943899 が原因で突然死したハードディスクを復旧させる方法 hatena_b

昨日書いた 「1/9 以降、Windows VISTA 搭載 レッツノートのハードディスクが突然死する可能性がある 」を大変多くの方に読んで頂けた。 頂いたコメントで目立ったのが、 復旧方法が万人向けではない、という点。 確かに Linux 2.6.22 以上の LiveCD を自前で調達しなければならないというのは、 よほど普段から Linux を使いこなしていない限りは難しいだろう。

というわけで、 突然死したハードディスクを復旧させる「お手軽パック」を作ってみた。 もちろん無保証である。 いかなる損害が発生しても私は何の責任も負えない、 ということに同意して頂けるかたのみに対して使用を許諾する。

まず、この zip アーカイブ をダウンロードして、 USB メモリへ展開する。 以下の例では USB メモリが「ドライブ D」になっているが、 実際の USB メモリのドライブ名で読み替えて欲しい。

D:\>dir
 ドライブ D のボリューム ラベルがありません。
 ボリューム シリアル番号は 0000-0000 です

 D:\ のディレクトリ

2007/07/16  08:49            23,040 syslinux.exe
2008/01/18  07:33           537,844 hdparm
2007/12/25  08:07         2,411,333 initz
2007/12/24  09:50         1,423,768 linuz
2008/01/18  08:18                58 syslinux.cfg
               5 個のファイル           4,396,043 バイト
               0 個のディレクトリ     510,672,896 バイトの空き領域

D:\>

Windows のコマンド プロンプト にて、 D:\syslinux.exe を以下のように実行する。 もちろん、引数の「D:」は USB メモリのドライブ名で読み替える。

D:\>syslinux.exe -ma D:

D:\>

これで Linux 2.6.23.12 がブート可能な USB メモリができた。 このメモリをレッツノートに差して起動する。 BIOS 設定で USB から起動可能にしておくのを忘れずに。

ハードディスクが回転しないのであるから、 以下のメッセージが表示されて止まってしまうが、

Phoenix TrustedCore(tm) NB
Copyright 1985-2004 Phoenix Technologies Ltd.
All Rights Reserved

Copyright (C) Matsushita Electric Industrial Co.,Ltd. 2007
BIOS Version 1.00-L13

CPU = 1 Processors Detected, Cores per Processor = 2
Intel(R) Core(TM) Duo CPU      U2400  @ 1.06GHz
2048MシステムRAMテスト完了。
システムBIOSがシャドウされました。
ビデオBIOSがシャドウされました。
ハードディスク0:
マウスが初期化されました。
エラー
0200: ハードディスクエラーです。 0

<F2>キーを押すとセットアップを起動します。

ここで構わず <F1>キーを押すと、 USB メモリからの起動が始まる。

linux が起動すると /bin/sh が実行されてプロンプト「#」が表示されるが、 その後 USB メモリが認識されてカーネル・ログが出力される。

        ...
PWD='/'
ROOTPARM=' -o ro'
TERM='linux'
initrd='initz'
/bin/sh: can't access tty; job control turned off
# [   31.556958] scsi 6:0:0:0: Direct-Access     Multi    Flash Reader     1.00 PQ: 0 ANSI: 0
[   32.077952] sd 6:0:0:0: [sdb] 1006592 512-byte hardware sectors (515 MB)
[   32.079952] sd 6:0:0:0: [sdb] Write Protect is off
[   32.080089] sd 6:0:0:0: [sdb] Mode Sense: 03 00 00 00
[   32.080094] sd 6:0:0:0: [sdb] Assuming drive cache: write through
[   32.085449] sd 6:0:0:0: [sdb] 1006592 512-byte hardware sectors (515 MB)
[   32.087574] sd 6:0:0:0: [sdb] Write Protect is off
[   32.087699] sd 6:0:0:0: [sdb] Mode Sense: 03 00 00 00
[   32.087704] sd 6:0:0:0: [sdb] Assuming drive cache: write through
[   32.087830]  sdb: sdb1
[   32.090803] sd 6:0:0:0: [sdb] Attached SCSI removable disk
[   32.091527] usb-storage: device scan complete

プロンプトの後にカーネル・ログが出力されてしまっているため紛らわしいが、 Enter キーを押せばプロンプトが表示される。

このカーネル・ログでは [sdb] と表示されているが、 レッツノートに接続した USB デバイスが他にもあれば、 sdc や sdd になっているかもしれない。 その場合は、以下の sdb を sdc なり sdd なりで読み替えて欲しい。

以下のように mount コマンドを実行して、 USB メモリを /mnt へマウントする。 そして USB メモリ上の hdparm コマンドを実行してみる:

# mount -t vfat /dev/sdb1 /mnt
# /mnt/hdparm -i /dev/sda

/dev/sda:

 Model=Hitachi HTS541612J9SA00                 , FwRev=SBDOC70P, SerialNo=      SBXXXXXXXXXXXX
 Config={ HardSect NotMFM HdSw>15uSec Fixed DTR>10Mbs }
 RawCHS=16383/16/63, TrkSize=0, SectSize=0, ECCbytes=4
 BuffType=DualPortCache, BuffSize=7516kB, MaxMultSect=16, MultSect=?16?
 CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=234441648
 IORDY=on/off, tPIO={min:120,w/IORDY:120}, tDMA={min:120,rec:120}
 PIO modes:  pio0 pio1 pio2 pio3 pio4 
 DMA modes:  mdma0 mdma1 mdma2 
 UDMA modes: udma0 udma1 udma2 udma3 udma4 *udma5 
 AdvancedPM=yes: mode=0x80 (128) WriteCache=enabled
 Drive conforms to: ATA/ATAPI-7 T13 1532D revision 1:  ATA/ATAPI-2,3,4,5,6,7

 * signifies the current active mode

# 

以上のように、 レッツノートのハードディスク (/dev/sda) の諸元が表示されれば成功である。 以下のように hdparm を実行して「Power-Up In Standby feature」を無効にすれば、 ハードディスクの復旧が完了する。

# /mnt/hdparm -s0 /dev/sda

/dev/sda:
 spin-up: setting power-up in standby to 0 (off)
# 

後は、Ctrl-Alt-Del を押すなどして再起動すれば、 ハードディスクから正常にブートする。 USB メモリを抜くのを忘れずに。

Filed under: ハードウェアの認識と制御 — hiroaki_sengoku @ 09:40
2008年1月17日

1/9 以降、Windows VISTA 搭載 レッツノートのハードディスクが突然死する可能性がある hatena_b

先日 1/10 (運悪く出張初日だった *_*) に、 レッツノート CF-R6MWVAJP のハードディスク・ドライブ (以下、HDD と略記) が 回転しなくなり (スピン・アップしない) 往生した。 電源を入れても、 BIOS が

Phoenix TrustedCore(tm) NB
Copyright 1985-2004 Phoenix Technologies Ltd.
All Rights Reserved

Copyright (C) Matsushita Electric Industrial Co.,Ltd. 2007
BIOS Version 1.00-L13

CPU = 1 Processors Detected, Cores per Processor = 2
Intel(R) Core(TM) Duo CPU      U2400  @ 1.06GHz
2048MシステムRAMテスト完了。
システムBIOSがシャドウされました。
ビデオBIOSがシャドウされました。
ハードディスク0:
マウスが初期化されました。
エラー
0200: ハードディスクエラーです。 0

<F2>キーを押すとセットアップを起動します。

というメッセージをビープ音とともに出力して止まってしまう。 HDD が壊れたのかと思い、 BIOS で HDD を起動ドライブから外して USB メモリからブートを試みたが、 起動ドライブから外しても内蔵 HDD に問題があると先に進めないようだ。

HDD を完全に取り除いてしまえば USB メモリからブートするらしいが、 このような中途半端な死にかただとスピン・アップ待ちになってしまって、 そこから先に進めなくなる (後で知ったのだが、 実は上記画面で止まっているとき <F1> を押すと、 ブートを継続できて USB メモリ等からブートできる)。

昔、HDD のスピンドル (spindle) が固着して、 スピン・アップ (spin up) しなくなる症状に見舞われたことがあったが、 今回はつい数分前まで全く正常に動いていた HDD が、 突然スピン・アップしなくなったのであって、 あからさまに症状が異なるように思われた。 しかもごく短い距離を移動するためにレッツ・ノートを閉じただけなので、 途中衝撃なども一切与えていない。 機械的な障害ではないように思われた。

とはいえ、 いちおー無駄な抵抗は試みた (^^;)。 すなわち、 HDD が回転しなくなったときに、 HDD を振り回すことによってトルクを与える手法や、 あるいは結露等で回路に異常がおきたときに、 結露を霧散させる手法 (平たく言うとしばらく放置しただけ ;) を試したのだが、 HDD が回転音を発することは無かった。 出張初日で、 代替マシンの調達もままならず、 Advanced/W-ZERO3[es] に USB キーボードをつないで急場をしのいだものの、 えらく難儀した。

- o -

結論から言うと、 想像通りハードウェア的にはなんら故障していなかった。 単に HDD が 「電源投入時にスタンバイ・モードに入る (power-on in standby)」 状態になっていただけだった。

1/9 に行なわれた Windows Update KB943899 が原因らしいです。 おそらくこの Update のバグで、 HDD に power-on in standby を有効にする命令が 送られてしまうことがあるのでしょう。 私の CF-R6 は 1/10 に発症しましたが、 他にも同様の発症例が多数あるとか。

例えば、 Linux の hdparm コマンドのマニュアルには、 次のような記述がある。

NAME
    hdparm - get/set hard disk parameters

SYNOPSIS
    hdparm [ flags ] [device] ..

OPTIONS

    -s   Enable/disable  the power-on in standby feature, if supported by
         the drive.  VERY DANGEROUS.  Do not use  unless  you  are  abso-
         lutely  certain  that both the system BIOS (or firmware) and the
         operating system kernel (Linux >= 2.6.22)  support  probing  for
         drives  that  use this feature.  When enabled, the drive is pow-
         ered-up in the standby mode to allow the controller to  sequence
         the  spin-up of devices, reducing the instantaneous current draw
         burden when many drives share a power supply.

VERY DANGEROUS」と書いてある通り、 HDD がひとたびこの「power-on in standby」モードになってしまうと、 電源を投入してもスピン・アップしなくなる (スタンバイ状態になる)。 HDD が沢山あるサーバなどで、 全ディスクが一斉に回転を始めると、 突入電流が電源の許容範囲を超えてしまったりするわけで、 それを回避するためのモードらしい。 つまり、 電源を投入したあと、 おもむろに HDD を一台づつスピン・アップしていくことにより、 回転開始にともなう突入電流を分散させることができるというわけ。

実験してみる (非常に危険なので何をやっているか完全に理解するまでは 真似しないでください):

# hdparm -s1 /dev/sda

/dev/sda:
 setting power-up in standby to 1 (on)
# hdparm -I /dev/sda

/dev/sda:

ATA device, with non-removable media
        Model Number:       Hitachi HTS541612J9SA00                 
        Serial Number:      SBXXXXXXXXXXXX
        Firmware Revision:  SBDOC70P
Standards:
        Used: ATA/ATAPI-7 T13 1532D revision 1 
        Supported: 7 6 5 4 
Configuration:
        Logical                max        current
        cylinders        16383        16383
        heads                16        16
        sectors/track        63        63
        --
        CHS current addressable sectors:   16514064
        LBA    user addressable sectors:  234441648
        LBA48  user addressable sectors:  234441648
        device size with M = 1024*1024:      114473 MBytes
        device size with M = 1000*1000:      120034 MBytes (120 GB)
Capabilities:
        LBA, IORDY(can be disabled)
        Queue depth: 32
        Standby timer values: spec'd by Vendor, no device specific minimum
        R/W multiple sector transfer: Max = 16        Current = 16
        Advanced power management level: 128 (0x80)
        Recommended acoustic management value: 128, current value: 254
        DMA: mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 udma4 *udma5 
             Cycle time: min=120ns recommended=120ns
        PIO: pio0 pio1 pio2 pio3 pio4 
             Cycle time: no flow control=120ns  IORDY flow control=120ns
Commands/features:
        Enabled        Supported:
           *        SMART feature set
           *        Security Mode feature set
           *        Power Management feature set
           *        Write cache
           *        Look-ahead
           *        Host Protected Area feature set
           *        WRITE_BUFFER command
           *        READ_BUFFER command
           *        NOP cmd
           *        DOWNLOAD_MICROCODE
           *        Advanced Power Management feature set
           *        Power-Up In Standby feature set
           *        SET_FEATURES required to spinup after power up
                    SET_MAX security extension
                    Automatic Acoustic Management feature set
           *        48-bit Address feature set
           *        Device Configuration Overlay feature set
           *        Mandatory FLUSH_CACHE
           *        FLUSH_CACHE_EXT
           *        SMART error logging
           *        SMART self-test
           *        General Purpose Logging feature set
           *        WRITE_{DMA|MULTIPLE}_FUA_EXT
           *        64-bit World wide name
           *        IDLE_IMMEDIATE with UNLOAD
           *        SATA-I signaling speed (1.5Gb/s)
           *        Native Command Queueing (NCQ)
           *        Host-initiated interface power management
           *        Phy event counters
                    Non-Zero buffer offsets in DMA Setup FIS
                    DMA Setup Auto-Activate optimization
                    Device-initiated interface power management
                    In-order data delivery
           *        Software settings preservation
Security: 
        Master password revision code = 2007
                supported
                enabled
        not        locked
                frozen
        not        expired: security count
        not        supported: enhanced erase
        Security level maximum
        72min for SECURITY ERASE UNIT. 
Checksum: correct
# 

「Power-Up In Standby feature set」が有効になっていることが分かる。 この状態で再起動する (HDD の電源をいったん切る) と、 冒頭に引用した「0200: ハードディスクエラーです。 0」を表示して止まってしまう。 <F1> を押して HDD 以外から起動させると、

[    0.000000] Linux version 2.6.23.12 (sengoku@senri.gcd.org) (gcc version 4.1.2) #1 SMP Mon Dec 24 09:50:41 JST 2007
        ...
[   72.479025] ata3.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
[   72.479031] ata3.00: irq_stat 0x40000001
[   72.479044] ata3.00: cmd c8/00:08:00:00:00/00:00:00:00:00/e0 tag 0 cdb 0x0 data 4096 in
[   72.479047]          res 51/04:08:00:00:00/00:00:00:00:00/e0 Emask 0x1 (device error)
[   72.481033] ata3.00: configured for UDMA/33
[   72.481043] sd 2:0:0:0: [sda] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE,SUGGEST_OK
[   72.481051] sd 2:0:0:0: [sda] Sense Key : Aborted Command [current] [descriptor]
[   72.481060] Descriptor sense data with sense descriptors (in hex):
[   72.481066]         72 0b 00 00 00 00 00 0c 00 0a 80 00 00 00 00 00 
[   72.481082]         00 00 00 00 
[   72.481089] sd 2:0:0:0: [sda] Add. Sense: No additional sense information
[   72.481099] end_request: I/O error, dev sda, sector 0
[   72.481114] ata3: EH complete
[   72.481738] sd 2:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[   72.481794] sd 2:0:0:0: [sda] 234441648 512-byte hardware sectors (120034 MB)
[   72.481818] sd 2:0:0:0: [sda] Write Protect is off
[   72.481824] sd 2:0:0:0: [sda] Mode Sense: 00 3a 00 00
[   72.481861] sd 2:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA

何度も HDD へリクエストを再送した末、「I/O error」になる。 Linux 2.6.22 以降の場合、 I/O error にはなるものの HDD デバイス自体は認識しているので、 hdparm コマンドからコントロールすることができる。

逆に言うと、古いカーネルだとデバイス認識も行なわれないので、 hdparm コマンドすら使えなくなってしまい 以下の方法では復旧できない。 現時点では Knoppix などの LiveCD の多くは、 2.6.21 以前のカーネルのまま (例えば Knoppix v5.1.1 は 2.6.19) なので注意。

hdparm を使って「Power-Up In Standby feature」を無効にする:

# hdparm -I /dev/sda | grep Power-Up
           *        Power-Up In Standby feature set
# hdparm -s0 /dev/sda

/dev/sda:
 setting power-up in standby to 0 (off)
# hdparm -I /dev/sda | grep Power-Up
                    Power-Up In Standby feature set
# 

これで、電源投入時に HDD は自動的に回転を始めるようになる。
再起動すれば HDD から正常にブートする。

Filed under: ハードウェアの認識と制御 — hiroaki_sengoku @ 08:59
2008年1月15日

自身の能力をアピールすることは技術者として必須だが、上司にだけアピールするのは最悪! hatena_b

私自身は、 KLab 社内の技術者たちと、 いつまでも技術者同士の関係でいたいと思っているのですが、 技術者の人数が増えてくると、 仕事上の接点がほとんどない人もでてきます。 そして社員の側からすると、 私は (いちおー ;-) 取締役なので、 おいそれとは話せない恐い人などと根拠無く思い込んでるケースも、 残念ながら皆無というわけではありません。

それではいけないということで、 日頃あまり接点のない人たちを中心に、 無理矢理 (^^;) ランチに誘って話する、ということをしています。 先日も隣の部署の N さんと二人でランチへ行きました。 彼とは入社直後の社員旅行で少し話をしただけで、 その後は話す機会がほとんどなかったのです。

それまで私は知らなかったのですが、 実は彼は高専時代にず抜けた存在で、全校で表彰されたこともあったそうです。 プログラミングが大好きで、いろんなものを作っては、 学校内でアピールし注目を集めていたとか。 しかしながら KLab 社内ではどちらかといえば目立たない存在だった (目立たなかったので私も話す機会がありませんでした) ので、 高専での活躍ぶりとのギャップを感じざるを得ませんでした。

そこで、 何がきっかけで自身の成果をアピールするのを止めてしまったのか尋ねました。 すると、

新卒で就職した会社 (≠ KLab) で、 開発ではない部署に配属されてしまった。 何事も挑戦ということでしばらくは配属された部署で頑張ったが、 やっぱりプログラミングを仕事にしたいと思い、 上司に何度も自身の能力をアピールしたところ、 ことごとく却下されてしまった。 それどころかアピールすればするほど周囲の評価も下がるぐらいで、 ついにはアピールするのを止めてしまった。

という答が返ってきました。

確かにそういう人は多いのだろうなぁと思います。 日頃、アピールすることの重要性を説いている私としては残念でなりません。 そもそも誰だって、 他の人より得意なことがあれば、 それを自慢したくなるのがフツーでしょう。 だからアピールする習慣がない人って、 元々アピールするのが嫌いだったというわけではなくて、 何らかのきっかけでアピールするのを止めてしまったのだろうと思います。

きっかけにはいろいろあるでしょうが、 N さんのように、 アピールしても周囲から評価されなかったり、 それどころか怒られたり、 周囲から浮いてしまって仕事が進めにくくなったり、 そういう嫌な経験をすれば、 だんだんとアピールするのが億劫になってしまうのは仕方がないところだと思います。 N さんの話に頷きながら、 ふと一つのフレーズが頭の中に浮かんできました:

自身の能力をアピールすることは技術者として必須だが、
上司にだけアピールするのは最悪!

技術者にとって重要な能力というと、 一つは間違いなく「スキルアップする能力」でしょう。 誰だって最初は初心者です。 プログラミングの勘所が最初から分かっていたなんて人は (たぶん) 皆無で、 初めて書いたプログラムを後に読んでみると、 その稚拙さ加減にあきれてしまう、というのはよくある話です。

最初は誰しも稚拙なプログラムを書いていたのに、 どんどん能力を伸ばす人がいる一方で、 多少は「形」を覚えて「それなりの」プログラムが書けるようになるものの、 本質的には初心者と代わり映えしない人 (偽ベテラン) もいて、 いつのまにか両者の間には生産性で 3桁の差がついていた、 なんてことが起こり得ます。

技術者にとって重要な能力がもう一つあります。 それが「アピールする能力」。 言うまでもなく技術者だけではお金にはなりません。 技術者の能力をお金に換える人 ──例えば技術者が作ったものを他の誰かに売り付ける人──と、 一緒になって初めてお金が稼ぐことができるわけです。 でも、どうやってその「換金してくれる人」を探せばよいのでしょうか?

実は「換金してくれる人」も技術者を探しています。 そりゃ、売るものがなければお金を稼げませんから、 技術者の能力を換金しようと思っている人が技術者を探すのは当たり前ですね。 だからわざわざ技術者の側からアクションを起さなくても、 学校には「求人票」が貼られ、 巷には転職斡旋会社の広告が氾濫しているわけです。 テキトーな会社を選んで面接を受ければ雇ってもらえてお金をもらえます。

とはいえ、受け身の姿勢よりは自ら動いたほうが有利になるのは世の常です。 学校に貼ってある求人票に限定した就職活動や、 あるいは転職エージェントの勧めに従うばかりの転職活動よりは、 自ら主体的に会社探しをしたほうが「高く」換金してもらえる可能性が高まります。

会社に雇ってもらった場合、 配属された部署の上司が「換金してくれる人」になります。 もちろん上司が一人でお金を稼いでくるわけではありませんが、 技術者から見れば、 自身の能力に対して評価し給料を決めてくれるわけですから、 自身の能力を「換金してくれる人」と言ってもいいでしょう (正確に言えば、換金してくれる人たちの集団の窓口的存在ですね)。

ところが、ここに一つ問題があります。 技術者に得手不得手があるのと同様、 「換金してくれる人」にも得手不得手があります。 技術者からすれば、 私はこんなに優れた能力を持っているのに、 どーして換金してくれないんだと思うのと同様、 「換金してくれる人」からすれば、 私はこーいう技術ならお金に換えられるのに、 どーしてそういう技術を持っている人がいないんだと思っていたりします。

「能力を上司が正当に評価してくれない」と不満に思っている場合、 十中八九その上司は、 「求める能力を部下が持っていない」と不満に思っているはずです。 このような状況で、 部下が上司に自身の能力をアピールして事態が改善するでしょうか。 きっと上司はこう思うはずです: 「そんな能力はお金にならない」。

より正確に言えば、 その上司が換金できる分野と、 技術者である部下の得意分野とが一致していないだけなんですが、 部下が自分の得意分野以外のことに興味がないのと同様、 上司は自分が換金できない分野には興味がありません。 そんな上司に執拗にアピールすれば、 事態を改善するどころか悪化させかねません。 技術者がすべきことは、 自身の能力を上司が換金できないのであれば、 他の「換金してくれる人」を探すことです。

ところが、 前述の N さんをはじめ多くの技術者は、 逆のことをやってしまいます。 「換金してくれる人」を探すのではなく、 上司に「換金してくれ」と懇願したり、 あるいはそれが却下されると、 もう世界にはただ一人も換金してくれる人はいないと 探すのをあきらめてしまったりするのです。

冷静に考えれば、 これは全くナンセンスであることが分かりますよね? 一口に IT (情報技術) と言っても、 様々な分野があります。 ある技術者の得意分野を最もうまく換金できる人が、 たまたまその人の上司だった、 なんてことがもし起これば、 それはすごくラッキーなことだと思いますが、 そんな幸運がそうそう起こるはずはありません。

自身の技術を上司が換金してくれなかったとしても、 そんなことは確率からいえば 「よくあること」 なわけで、 決してその技術が 「お金にならない」 ことを意味しません。 自身の技術が上司に評価されないときこそ、 より積極的に、上司以外の人に向かって、 自身の技術をアピールすべきでしょう。

より多くの人にアピールすれば、 それだけ「運命の人」にめぐりあう確率は高まります。 「この分野にかけては誰にも負けない」という得意分野を持っている人は、 より多くの人へ、 部署内だけでなく社内全体へ、 社内だけでなくより広い世界に対して、 どんどんアピールしていって欲しいと思います。 探す範囲を広げていけば、 その能力を換金してくれる人がきっと見つかるはずです。

Filed under: 元CTO の日記,技術と経営 — hiroaki_sengoku @ 11:15
2008年1月5日

ガンダム サウンドロップ の音を変えてみた hatena_b

妻が、ガシャポン (ガチャガチャ) で サウンドロップを買ってきた。

サウンドロップ ガンダム ~青い巨星編~

なんでも、最初に出てきたのが「ヒート・ロッド電流音」だったそうで、 「効果音」ではない「セリフ」バージョン (アムロの声とか) が欲しくて、 ついつい二個三個と買ってしまったらしい。 馬鹿だねぇ...

で、サウンドロップを改造するページを見つけてきて、 同じように改造してくれという。

ネジを外してバラすと、 基板上隅に S1 S2 S3 S4 とシルク印刷したパターンがある。 このパターンのいずれかをショートすると対応する音声を選択できるらしい。 右下隅に「P36C」とシルク印刷してあるが、 これは基板のID と思われる。 「P36」というのが「~青い巨星編~」シリーズを意味していて、 末尾の「C」がシリーズに含まれる各バリエーションを表す記号なのだろう。

サウンドロップ 基板

上の写真の赤枠で囲った部分を拡大:

サウンドロップ 基板 S2 ショート

S2 がショートしてある。 S2 の半田を取り除いて S1 をショートしてみると、
ヒート・ロッド電流音がセイラさんの「あなたなら出来るわ」に変わった。

サウンドロップ 基板 S1 ショート

ショートするパターンと音声をまとめると次のようになる。

P36A S? 1ランバ・ラルA ザクとは違うのだよ! ザクとは!
S? 2 ランバ・ラルB いい目をしているな
P36B S1 5アムロ・レイB 親父にもぶたれたことないのに!
S2 4 アムロ・レイA おだてないでください
P36C S1 3セイラ・マス あなたなら出来るわ
S2 6 ヒート・ロッド電流音 シュビンッ! ビビビビ…
P36D S1 7ビーム・サーベルを抜いた音 ブォンッ!
S2 8 ビーム・サーベルで斬り付けた音~爆発音 ズギャン! ビゴゴゴ… ドォォン!
Filed under: その他 — hiroaki_sengoku @ 17:36
2008年1月4日

La Fonera をディスクレス (flash less) ブートする hatena_b

あけましておめでとうございます。 今年もよろしくお願いします。

La Fonera (La Fonera+) のブート・ローダ RedBoot は、 TFTP サーバに置いたカーネルを load して起動することができる。 したがって、 TFTP サーバから load したカーネルで root ファイル・システムを NFS マウントすれば、 フラッシュ・メモリを使わずにブートすること (ディスクレス・ブート、というか flashless boot) ができる。

La Fonera のようなルータをディスクレスにして 何が嬉しいのかと思う人もいるかもしれないが、 ルータのように常時ネットワークにつなぐものだからこそ、 ネットワークにつないでいないと使えないという ディスクレス最大の欠点が欠点にならないわけで、 むしろルータこそ積極的にディスクレスにすべきではなかろうか。

ディスクレス化することによるメリットは数多い。 なんといっても最大のメリットは、 フラッシュ・メモリを書き換えること無く、 手軽にファームウェアを入れ替えられる (OpenWrt や DD-WRT など) こと。 フラッシュ・メモリを書き換える時間が節約できるし、 書き換え回数を気にする必要もなくなるわけで、 心置き無くファームウェアのデバッグを行なえる。 また、 NFS を使えばフラッシュ・メモリの容量をはるかに超えるディスク領域を使えるので、 セルフ・コンパイル環境の構築なども容易に行なうことができる。

試しに、 La Fonera のフラッシュ・メモリを書き換えること無く DD-WRT をブートさせてみる。

まず、 DD-WRT の root ファイル・システムを NFS サーバ上に展開する。 ここでは例として /nfs/dd-wrt に展開した。 /usr/sbin/udhcpc の実行を抑制するため (理由は後述) に、 /nfs/dd-wrt/usr/sbin/udhcpc を削除しておく。

senri:/tmp # wget "http://www.dd-wrt.com/dd-wrtv2/downloads/release candidates/DD-WRT v24 RC6.2/Atheros WiSoc/Fonera/root.fs"
--09:22:37--  http://www.dd-wrt.com/dd-wrtv2/downloads/release%20candidates/DD-WRT%20v24%20RC6.2/Atheros%20WiSoc/Fonera/root.fs
           => `root.fs'
        ...
09:22:46 (335.56 KB/s) - `root.fs' saved [2834432/2834432]

senri:/tmp # unsquashfs.dd-wrt -dest /nfs/dd-wrt root.fs
Reading a different endian SQUASHFS filesystem on root.fs

created 347 files
created 61 directories
created 159 symlinks
created 0 devices
created 0 fifos
senri:/tmp # rm /nfs/dd-wrt/usr/sbin/udhcpc

次に DD-WRT のカーネルを改変して、 root ファイル・システムを NFS マウントできるようにする。 DD-WRT のソースを取得:

senri:/usr/local/src % svn co svn://svn.dd-wrt.com/DD-WRT
A    DD-WRT/tools
A    DD-WRT/tools/addpattern_gs
A    DD-WRT/tools/uemf.h
        ...

La Fonera 用のカーネルは、 DD-WRT/src/linux/ar531x/linux-2.6.23 にある。
SVN revision 8745 の場合は Linux 2.6.23.12 ベース。
ビルド用ディレクトリ /usr/local/src/linux-2.6.23.12-dd-wrt を作って、 DD-WRT のデフォルトのカーネル設定ファイル .config_generic をコピーし、 make menuconfig を実行:

senri:/usr/local/src % mkdir /usr/local/src/linux-2.6.23.12-dd-wrt
senri:/usr/local/src % cd DD-WRT/src/linux/ar531x/linux-2.6.23
senri:/usr/local/src/DD-WRT/src/linux/ar531x/linux-2.6.23 % make O=/usr/local/src/linux-2.6.23.12-dd-wrt menuconfig
        ...
senri:/usr/local/src/DD-WRT/src/linux/ar531x/linux-2.6.23 % cp .config_generic /usr/local/src/linux-2.6.23.12-dd-wrt/
senri:/usr/local/src/DD-WRT/src/linux/ar531x/linux-2.6.23 % cd /usr/local/src/linux-2.6.23.12-dd-wrt
senri:/usr/local/src/linux-2.6.23.12-dd-wrt % make menuconfig

root ファイル・システムを NFS マウントするために必要な変更は以下の通り:

まず、 カーネルによる IP アドレス自動取得機能を有効にする:

-> Networking
  -> Networking support (NET [=y])
    -> Networking options
      -> TCP/IP networking (INET [=y])
        -> IP: kernel level autoconfiguration (IP_PNP [=y])
          -> IP: DHCP support (IP_PNP_DHCP [=y])

DD-WRT のデフォルト設定では、 ネットワーク・ドライバ AR2313 がモジュールになっているので、 カーネル組み込み (built-in) に変更する:

-> Device Drivers
  -> Network device support (NETDEVICES [=y])
    -> Ethernet (10 or 100Mbit) (NET_ETHERNET [=y])
      -> AR2313 Ethernet support (AR2313 [=y])

そして NFS サポートを有効にする:

-> File systems
  -> Network File Systems
    -> NFS file system support (NFS_FS [=y])
      -> Provide NFSv3 client support (NFS_V3 [=y])
    -> Root file system on NFS (ROOT_NFS [=y])

root ファイル・システムはカーネルがマウントするので mount コマンドは使用しないが、 La Fonera 用の DD-WRT の mount コマンド (busybox に含まれる) は、 NFS をサポートしていないので注意が必要である。 NFS サーバ上の root ディレクトリ /nfs/dd-wrt には、 NFS マウントをサポートした mount コマンドをインストールしておいたほうが便利。

RedBoot の exec コマンドでカーネル・コマンドラインを指定しても、 なぜか無視される (バグ?) ので、 カーネルのデフォルト・コマンドラインを変更しておく:

-> Kernel hacking
  -> Default kernel command string (CMDLINE)

カーネル・コマンドラインとして以下を設定:

console=ttyS0,115200 ip=on root=/dev/nfs nfsroot=/nfs/dd-wrt,nolock

以上まとめると、 カーネル設定ファイル .config の変更箇所は以下の通り:

CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y

CONFIG_AR2313=y

CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y

CONFIG_CMDLINE="console=ttyS0,115200 ip=on root=/dev/nfs nfsroot=/nfs/dd-wrt,nolock"

make して TFTP サーバに置く:

senri:/usr/local/src/linux-2.6.23.12-dd-wrt % make
make -C /usr/local/src/DD-WRT/src/linux/ar531x/linux-2.6.23 O=/usr/local/src/linux-2.6.23.12-dd-wrt
  GEN     /usr/local/src/linux-2.6.23.12-dd-wrt/Makefile
        ...
  LD      vmlinux
  SYSMAP  System.map
        ...
senri:/usr/local/src/linux-2.6.23.12-dd-wrt % mips-linux-uclibc-objcopy -O binary vmlinux /var/tftp/vmlinux.bin

La Fonera で読み込んでブートさせる... といいたいところだが、 DD-WRT のカーネルは、 flash RAM に「nvram」という名前の区画がないと Kernel panic を起こす:

RedBoot> load -r -b 0x80041000 vmlinux.bin
Using default protocol (TFTP)
Raw file loaded 0x80041000-0x8031cbb3, assumed entry at 0x80041000
RedBoot> exec
Now booting linux kernel:
 Base address 0x80030000 Entry 0x80041000
 Cmdline : 
Linux version 2.6.23.12 (sengoku@senri.gcd.org) (gcc version 4.1.2) #14 Wed Jan 2 13:20:19 JST 2008
        ...
Unhandled kernel unaligned access[#1]:
Cpu 0
$ 0   : 00000000 0000006e ffffffed 00000000
        ...
Kernel panic - not syncing: Attempted to kill init!

flash-less boot の主旨には反するが (^^;)、 nvram 区画を作って再度ブートを試みる。

もちろん、 flash を一切参照しないファームウェアを作ることも可能ではあるが、 わずか 64k byte の flash 領域を確保するだけで、 既存のファームウェアをほとんどそのまま流用できるのであれば、 費用対効果の高い flash の使い方と言えるのではないだろうか。

nvram 区画の内容は「空っぽ」でも構わないのであるが、 ついでなので他の DD-WRT マシンで設定した nvram (nvram.bin) をコピーすれば、 設定の手間が省ける。

DD-WRT のデフォルト設定では、 ath0 (無線LAN) と eth0 (WAN) がブリッジとして動作する設定になっていて、 ブート途中で一時的に eth0 を停止する (ifconfig eth0 down あるいは ifconfig eth0 0.0.0.0)。 当然、eth0 を止めた瞬間に NFS サーバと通信できなくなり、 「nfs: server not responding, still trying」という ログを出し続けてハングしてしまう。 したがって、 eth0 を止めない設定にしておく必要がある。 例えば、 NFS サーバ上の root ディレクトリから /usr/sbin/udhcpc を削除した上で、 「WAN Connection Type」を DHCP に設定する。

ついで^2 に、 La Fonera+ には、 「image2」という名前の普段は使われていない区画がある (「image」区画が壊れた場合の非常用) ので削除しておく (fis delete image2)。

RedBoot> fis delete image2
Delete image 'image2' - continue (y/n)? y
... Erase from 0xa8660000-0xa87a0000: ....................
... Erase from 0xa87e0000-0xa87f0000: .
... Program from 0x80ff0000-0x81000000 at 0xa87e0000: .
RedBoot> load -r -b 0x80041000 nvram.bin
Using default protocol (TFTP)
Raw file loaded 0x80041000-0x80050fff, assumed entry at 0x80041000
RedBoot> fis create -b 0x80041000 -f 0xA87D0000 -l 0x00010000 nvram
... Erase from 0xa87d0000-0xa87e0000: .
... Program from 0x80041000-0x80051000 at 0xa87d0000: .
... Erase from 0xa87e0000-0xa87f0000: .
... Program from 0x80ff0000-0x81000000 at 0xa87e0000: .
RedBoot> fis list
Name              FLASH addr  Mem addr    Length      Entry point
RedBoot           0xA8000000  0xA8000000  0x00030000  0x00000000
loader            0xA8030000  0x80100000  0x00010000  0x80100000
image             0xA8040000  0x80040400  0x00240230  0x80040400
nvram             0xA87D0000  0xA87D0000  0x00010000  0x80041000
FIS directory     0xA87E0000  0xA87E0000  0x0000F000  0x00000000
RedBoot config    0xA87EF000  0xA87EF000  0x00001000  0x00000000

flash がこの状態でも、 La Fonera+ のオリジナル・ファームウェアは正常に起動する。 また、 ここでは La Fonera+ を使用しているが、 La Fonera でも同様に nvram 区画を作ればよい。

より正確に言うと、 区画の個数が同じ (/dev/mtd9 が board_config) でないと、 オリジナル・ファームウェアでは fonsmcd が異常終了してしまって、 FON ルータが接続されていないと FON にみなされてしまう。 image2 を削除して nvram を追加すれば区画の個数は変わらないので、 fonsmcd を正常に動かすことができる。
ついでに言うと、 区画の個数が変化してしまっても、 /usr/sbin/fonsmcd ファイル中の「/dev/mtd9ro」という部分を変更すれば、 この問題は回避できる。 MTD パーティションの番号をハードコーディングしてしまっているのは、 この部分だけだと思われる。

再度ブート:

RedBoot> load -r -b 0x80041000 vmlinux.bin
Using default protocol (TFTP)
Raw file loaded 0x80041000-0x8031cbb3, assumed entry at 0x80041000
RedBoot> exec
Now booting linux kernel:
 Base address 0x80030000 Entry 0x80041000
 Cmdline : 
Linux version 2.6.23.12 (sengoku@senri.gcd.org) (gcc version 4.1.2) #14 Wed Jan 2 13:20:19 JST 2008
        ...
IP-Config: Got DHCP answer from 172.16.255.254, my address is 172.16.191.230
IP-Config: Complete:
      device=eth0, addr=172.16.191.230, mask=255.255.0.0, gw=172.16.255.254,
     host=172.16.191.230, domain=, nis-domain=(none),
     bootserver=172.16.255.254, rootserver=172.16.255.254, rootpath=
Looking up port of RPC 100003/2 on 172.16.255.254
Looking up port of RPC 100005/1 on 172.16.255.254
VFS: Mounted root (nfs filesystem) readonly.
Mounted devfs on /dev
Freeing unused kernel memory: 140k freed
        ...
DD-WRT v24 std (c) 2008 NewMedia-NET GmbH
Release: 01/02/08 (SVN revision: 8743)

DD-WRT login: root
Password: XXXXXXXX
==========================================================

 ____  ___    __        ______ _____         ____  _  _
 | _ \| _ \   \ \      / /  _ \_   _| __   _|___ \| || |
 || | || ||____\ \ /\ / /| |_) || |   \ \ / / __) | || |
 ||_| ||_||_____\ V  V / |  _ < | |    \ V / / __/|__   _|
 |___/|___/      \_/\_/  |_| \_\|_|     \_/ |_____|  |_|

                       DD-WRT v24
                   http://www.dd-wrt.com

==========================================================


BusyBox v1.4.2 (2008-01-02 03:34:20 CET) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

root@DD-WRT:~# cat /proc/mounts
rootfs / rootfs rw 0 0
/dev/root / nfs ro,vers=2,rsize=4096,wsize=4096,hard,nolock,proto=udp,timeo=10,retrans=2,sec=sys,addr=172.16.255.254 0 0
none /dev devfs rw 0 0
proc /proc proc rw 0 0
sysfs /sys sysfs rw 0 0
ramfs /tmp ramfs rw 0 0
devpts /dev/pts devpts rw 0 0
root@DD-WRT:~# 

NFS サーバに置いた DD-WRT の root ディレクトリ /nfs/dd-wrt が、 無事 / にマウントできている。

Filed under: La Fonera — hiroaki_sengoku @ 08:38
2007年12月25日

2行でできる高精度ハードウェア自動認識 (initramfs の init を busybox だけで書く) hatena_b

10行でできる高精度ハードウェア自動認識」にコメントを頂いた:

最近の modprobe は、 自分で勝手に modules.alias を探してくれるようになっているようです。 この機能を使うと、 より簡単かつ高速に自動認識が可能になります。

そうだったのか... orz

いままで、 modules.alias から modporbe すべきモジュールを検索するために、 以下のような感じで sh スクリプト (/tmp/dev2mod) を生成し、 それを読み込んで (. $tmp) いたのだが、

tmp=/tmp/dev2mod
echo 'dev2mod(){ while read dev; do case $dev in' > $tmp
sort -r /lib/modules/`uname -r`/modules.alias \
| sed -n 's/^alias  *\([^ ]*\)  *\(.*\)/\1)modprobe \2;;/p' >> $tmp
echo 'esac; done; }' >> $tmp
. $tmp
rm $tmp
cat /sys/bus/*/devices/*/modalias | dev2mod

modprobe が自分で modules.alias を探してくれるとなると、 sh スクリプトを動的生成する必要が無くなってしまい、 上記コードは次のように書けてしまう:

dev2mod(){ while read dev; do modprobe $dev; done }
cat /sys/bus/*/devices/*/modalias | dev2mod

わずかに 2行 (^^;)

/sys/bus/*/devices/*/modalias の内容を手当たり次第 modprobe するので、 modprobe が「failed to load module」というエラー・メッセージを出してしまうが、 特に問題は無さげである。

PCMCIA や USB につないだデバイスも、 以下のように dev2mod を二度呼び出すだけで、 自動認識してしまう。

dev2mod(){ while read dev; do modprobe $dev; done }
cat /sys/bus/*/devices/*/modalias | dev2mod
modprobe pcmcia
cat /sys/bus/*/devices/*/modalias | dev2mod

う~んすごい。

Filed under: プログラミングと開発環境 — hiroaki_sengoku @ 08:04
2007年12月21日

La Fonera+ へ ssh でログインする (3) root イメージの改変

前回抽出した ROOT ディレクトリ を改変する。 真っ先に変更すべきなのは /etc/inittab で、 以下のように 1行挿入して /bin/ash が立ち上がるようにしておく。 これだけで、 シリアル・コンソールでシェルが使えるようになる。

--- ROOT.org/etc/inittab        2007-06-19 03:47:32.000000000 +0900
+++ ROOT/etc/inittab        2007-12-15 10:28:06.317233846 +0900
@@ -1,2 +1,3 @@
 ::sysinit:/etc/init.d/rcS
+ttyS0::askfirst:/bin/ash --login
 #::respawn:/sbin/monit -Ic /etc/monitrc

この変更だけでも、 La Fonera+ がいじり放題になるので、 改変ファームウェアを作ってみる。

当然 kernel が必要になる。 FON のソースからビルドするのは難しくはないが、 クロスコンパイル環境の構築など、 それなりの時間がかかるので、 とりあえず純正ファームウェアのものをそのまま使って、 改変ファームウェアを作ってみる。 まず純正ファームウェアから取り出した image_full のヘッダを参照して、...

senri:/tmp % od -t x1 image_full | head -1
0000000 00 21 bf de a2 14 d3 9b 00 0a 50 34 6d 00 00 80

前回説明したように image_full は以下のフォーマットなので、 「lzma 圧縮したカーネル」は、 12 バイト目から 000A5034 (上記ヘッダ 8 バイト目~ に注目) バイトであることが分かる。

┌───────┬───────┬───────┬───<<───┬───<<───┐
│rootイメージの│チェック・サム│rootイメージの│lzma 圧縮した │root イメージ │
│サイズ   4byte│(CRC32)  4byte│位置     4byte│カーネル      │squashfs      │
└───────┴───────┴───────┴───>>───┴───>>───┘

000A5034 は 10進数に直すと 675892 なので、 以下のように dd コマンドに「count=675892」を指定して、 image_full から lzma 圧縮したカーネル「vmlinux.lzma」を取り出す:

senri:/tmp % dd if=image_full bs=1 skip=12 count=675892 of=vmlinux.lzma
675892+0 records in
675892+0 records out
675892 bytes (676 kB) copied, 1.25156 seconds, 540 kB/s

前述したパッチを前回抽出した ROOT ディレクトリへ適用し、 mksquashfs-lzma コマンドを使って root イメージ root.squashfs を作成する:

senri:/tmp # patch -p0 < patch
patching file ROOT/etc/inittab
senri:/tmp # mksquashfs-lzma ROOT root.squashfs -nopad -noappend -root-owned -be
Creating big endian 3.0 filesystem on root.squashfs, block size 65536.

Big endian filesystem, data block size 65536, compressed data, compressed metadata, compressed fragments
Filesystem size 1499.77 Kbytes (1.46 Mbytes)
        31.47% of uncompressed filesystem size (4766.19 Kbytes)
Inode table size 4802 bytes (4.69 Kbytes)
        23.45% of uncompressed inode table size (20479 bytes)
Directory table size 5571 bytes (5.44 Kbytes)
        56.99% of uncompressed directory table size (9776 bytes)
Number of duplicate files found 4
Number of inodes 639
Number of files 407
Number of fragments 28
Number of symbolic links  165
Number of device nodes 0
Number of fifo nodes 0
Number of socket nodes 0
Number of directories 67
Number of uids 1
        root (0)
Number of gids 0

以上で、 カーネルと root イメージの準備ができた。 vmlinux.lzma と root.squashfs をつなげて image ファイルを作成する:

senri:/tmp % fonimage.pl image vmlinux.lzma root.squashfs

fonimage.pl は、 FON のソース を展開すると、 fon/target/linux/fonera-2.6/image/fonimage.pl にある perl スクリプト。 CRC32 の算出 (前述した image_full のフォーマット参照) のため、 Digest::CRC モジュールが必要。

できた image を TFTP サーバに置いて、 La Fonera+ の flash へ書込む

試しに起動してみる:

RedBoot> fis load loader
RedBoot> go
Failsafe loader v0.2

Looking for board config data... found at offset 0xa87f0000
Reset button GPIO: 6
Reading flash from 0xa8040000 to 0xa825bf48... done.
Verifying CRC... OK - 0x766770d6
Uncompressing Linux... Ok, booting the kernel.
[sighandler]: No more events to be processed, quitting.
[cleanup]: Waiting for children.
[cleanup]: All children terminated.
Unlocking rootfs ...
Could not open mtd device: rootfs
switching to jffs2
init started:  BusyBox v1.4.1 (2007-09-03 10:39:50 UTC) multi-call binary

Please press Enter to activate this console. 


BusyBox v1.4.1 (2007-09-03 10:39:50 UTC) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

  ______                                           __      
 /\  ___\                                         /\ \     
 \ \ \__/  __     ___      __   _ __    __        \_\ \___ 
  \ \  _\/ __`\ /' _ `\  /'__`\/\`'__\/'__`\     /\___  __\
   \ \ \/\ \L\ \/\ \/\ \/\  __/\ \ \//\ \L\.\_   \/__/\ \_/
    \ \_\ \____/\ \_\ \_\ \____\\ \_\\ \__/.\_\      \ \_\ 
     \/_/\/___/  \/_/\/_/\/____/ \/_/ \/__/\/_/       \/_/ 

--------------  Fonera 1.5 Firmware (v1.1.1.1) -----------------

               * Based on OpenWrt - http://openwrt.org
             * Powered by FON - http://www.fon.com
      -----------------------------------------------------
root@OpenWrt:/# 

カーネルは改変していないので、 起動ログを見ることはできないが、 シェルが使えるのでいじり放題。

では早速...

root@OpenWrt:/# cat > /etc/ipkg.conf <<EOF
> src gcd http://www.gcd.org/fonera
> dest root /
> dest ram /tmp
> EOF
root@OpenWrt:/# ipkg update
Downloading http://www.gcd.org/fonera/Packages
Updated list of available packages in /usr/lib/ipkg/lists/gcd
Done.
root@OpenWrt:/# ipkg install dropbear
Installing dropbear (0.48.1-1) to root...
Downloading http://www.gcd.org/fonera/dropbear_0.48.1-1_mips.ipk
xsystem: ERROR: fork failed before execution: `wget --passive-ftp    -q -P /tmp/ipkg-0dCiiX http://www.gcd.org/fonera/dropbear_0.48.1-1_mips.ipk'
Nothing to be done
An error ocurred, return value: 22.
Collected errors:
Failed to download dropbear. Perhaps you need to run 'ipkg update'?
root@OpenWrt:/#

つまり GCD の ipkg feed から dropbear をインストールしようとしたのだが、 La Fonera+ の wget は busybox 内蔵のもので ipkg が期待する wget とは引数の形式が異なるようだ。 ipkg のためだけに GNU Wget をインストールするのも牛刀なので、 手作業で dropbear をインストールしてみる。

root@OpenWrt:~# wget http://www.gcd.org/fonera/Plus/dropbear_0.49-1_mips.ipk
Connecting to www.gcd.org [60.32.85.216:80]
dropbear_0.49-1_mips 100% |*****************************|    98 KB --:--:-- ETA
root@OpenWrt:~# tar xvzf dropbear_0.49-1_mips.ipk
./debian-binary
./data.tar.gz
./control.tar.gz
root@OpenWrt:~# cd /
root@OpenWrt:/# tar xvzf ~/data.tar.gz
./
./usr/
./usr/sbin/
./usr/sbin/dropbear
./usr/bin/
./usr/bin/scp
./usr/bin/ssh
./usr/bin/dbclient
./usr/bin/dropbearkey
./etc/
./etc/config/
./etc/config/dropbear
./etc/init.d/
./etc/init.d/dropbear
root@OpenWrt:/# /etc/init.d/dropbear start
root@OpenWrt:/#

これで外部から ssh でログインできるようになる。

La Fonera+ 起動時に自動的に dropbear (ssh サーバ) を立ち上げるには、

root@OpenWrt:/# /etc/init.d/dropbear enable

を実行すればよい。 以上は、 dropbear を La Fonera+ に直接インストール方法であるが、 もちろん前述した ROOT ディレクトリに対して dropbear をインストールして、 dropbear 入り image ファイルを作って flash メモリに書込んだ方がよい。

Filed under: La Fonera — hiroaki_sengoku @ 14:06
2007年12月19日

ひたすらコンピュータに没頭した学生時代

あすなろ blog の CTO キャリアライフインタビューを受けました。 私は普段、 昔話はできるだけしないように気をつけていた (だって「老害!」って思われちゃいますからね) のですが、 このインタビューでは冒頭いきなり

そもそもコンピュータに興味を持ったきっかけから教えていただけますか

と聞かれてしまい、 封印していた過去が一気に吹き出してしまいました。 なんせ 30年近い昔のことですから、 最近コンピュータを始めた人にとっては 何の興味も持てないんじゃないかとちょっと心配です (インターネット元年であり Windows ブレイクの年でもある 1995年も、 私の感覚だと「つい最近」の出来事だったりします ^^;)。

そして今日は、 「Commodore 64」の生みの親、J・トラミエル氏インタビュー という記事を見つけてしまいました。

Commodore !

Commodore PET 2001 !

Commodore VIC-1001 !

なにもかも懐かしい ! 昔の記憶がどんどんよみがえってきます。

パーソナルコンピュータの歴史に最も大きな影響を与えた人物について語るとき、 人はよく、Steve Jobs氏、Steve Wozniak氏、Bill Gates氏、Paul Allen氏、 Gordon Moore氏、Andy Grove氏などの名前を挙げる。
だが、確実に彼らと同じグループに属する人がもう1人いる。 Commodoreの創業者で、後にAtariの最高経営責任者(CEO)を務めた Jack Tramiel氏だ。 「Commodore PET」や「Commodore VIC-20」、 さらに、パーソナルコンピュータ史上最も販売台数が多いとされる 「Commodore 64」(C64)を世に送り出した人物として、 Tramiel氏は、他の誰よりも強い影響力を持っていたのかもしれない。

私に最も大きな影響を与えたのは、 Apple でもなく、MS Basic でもなく、8080 CPU でもなく、 PC-8001 でもなく、Commodore でした。 CTO インタビューでは、 「なぜかはじめからコンピュータが好きだった」と答えたのですが、 中学校での PET 2001 との出会いがなければ今の私は無かったかも知れません。

中学3年生になって、だんだんBasicでゲームを作るほかに、 もっと下のレベルでプログラミングができるということがわかってきて、 機械語と呼ばれていた言語に興味を持つようになりました。

インタビューの時は忘れていたのですが、 私が機械語 (マシン語。メモリ上で即実行可能なバイナリのことです) を学ぶきっかけになったのは、 当時コモドールジャパンが発行していた小冊子「VIC!」でした。 この小冊子のコラムに、 機械語の簡単な紹介があって、 EA (16進コード) も機械語の命令の一つ、といったことが書かれていたのでした。 0xEA は 6502 CPU では NOP 命令なのですが、 そのコラムは、 「NOP は何もしない、という命令ですが、 読者の皆さんは何もしないのではなく、 VIC をきっかけにコンピュータを学んでいって欲しい」といった主旨の言葉で しめくくられていました。

このコラムがきっかけとなって、 なんとかして EA 以外の命令も知りたいと思うようになりました。 今と違ってインターネットも検索エンジンもありませんから、 当時中学生だった私が 6502 の命令セットを見つけ出すことは難しく、 それだけに一層「切望感」がつのったのでした。

私が初めてコンピュータに触れたのは、中学一年生の終わり頃である。 「マイコン部」なるものがあって、 3台のCommodore PET 2001を 20人以上の部員で使っていた。 しかも「部活動」は週一回 50分ほどだったと記憶しているので、 PET 2001 に触れるのは、二週間に一度、25分だけ、 しかも二人で一台を使う形だった。 最初のうちは BASIC を使って簡単なゲームなどを書いていたが、 6502 のインストラクションセットをどこからか見つけてきて (どこで見つけたのだろう? 当時はその手の資料を中学生が見つけることは、かなり難しかったはず)、 ハンドアセンブルしたコードを BASIC の poke 文でメモリに書いて 実行させて遊んだりした。

いまさらですが、 現代は便利な世の中ですねぇ... the 6502 microprocessor resource なんてページが簡単に見つかるのですから... こんなページを中学生時代の私が見たら、 「宝の山」を発見した感激で卒倒したことでしょう。 当時の私が苦労の末ついに見つけたのは、 65CE02 Microprocessor の 10, 11 ページの表だったのではないかと思います。

Filed under: 技術者の成長 — hiroaki_sengoku @ 21:00
2007年12月18日

La Fonera+ へ ssh でログインする (2) root イメージの抽出

La Fonera+ の場合、 全てのソースが公開されているわけでは無い (例えば fonsmcd などが非公開)。 したがって La Fonera+ の機能を出来るかぎり損なわずに ファームウェアの改変を行なうには、 ソースから全てをビルドすることを目指すよりは、 純正ファームウェアの root イメージを入手して、 それをベースに改変を行なう方がよい。

純正ファームウェアの root イメージを入手する方法としては、 La Fonera+ をディスクレス (フラッシュメモリレス?) 起動させて フラッシュ・メモリの内容を丸ごとコピーする方法がまず考えられる。 実際、私はこの方法で La Fonera+ のフラッシュ・メモリの内容を抽出したのだが、 La Fonera+ は 純正ファームウェアがダウンロードできる。 わざわざ実機からファームウェアを抽出しなくてもいいのでお手軽である。 そこで今回はダウンロードした純正ファームウェアから root イメージを取り出して 改変を行なう方法を紹介する。

まず FON のダウンロードページ から foneraplus_1.1.1.1.fon をダウンロードする。 「.fon」という見慣れない拡張子だが、 このファイルの 519 バイト目以降が tar + gz アーカイブになっている。 519 という数字はバージョンによって変わるかも知れないので、 算出方法を説明しておく。 先頭 4 バイトは マジック・ナンバー「FON5」なのでスキップ。

余談だが、 La Fonera のファームウェア (例えば fonera_0.7.1.1.fon) の場合だと、 このマジック・ナンバーは「FON3」であり、 La Fonera のファームウェアの更新差分 (例えば upgrade.fon) の場合だと、 「FON4」になっている。

マジック・ナンバーの次、すなわち 4 バイト目 (先頭を 0 バイト目と数える) から 3 バイトに注目する。

% od -t a foneraplus_1.1.1.1.fon | head -1
0000000   F   O   N   5   5   1   2   !   V sub   ,  cr   ^   -   k   e

ASCII コードで「512」と入っていることが分かる。 この数値は、 tar + gz アーカイブの位置を表わしている。 すなわち、 この「512」の文字列の直後の位置 (つまり 7 バイト目) から数えて 512 バイト目、 先頭から数えれば 519 バイト目が、 tar + gz アーカイブの先頭位置である。 アーカイブを取り出して展開してみる:

% dd if=foneraplus_1.1.1.1.fon bs=1 skip=519 of=foneraplus_1.1.1.1.tgz
2213430+0 records in
2213430+0 records out
2213430 bytes (2.2 MB) copied, 4.95395 seconds, 447 kB/s
% tar xvzf foneraplus_1.1.1.1.tgz
-rwxr-xr-x iurgi/iurgi     666 2007-09-07 23:39 upgrade
-rw-r--r-- iurgi/iurgi 2293764 2007-09-05 23:28 image_full
-rw-r--r-- iurgi/iurgi     102 2007-04-23 21:12 hotfix

展開すると「image_full」というファイルが得られる。 これは、 kernel と root イメージをつなげて、 先頭にヘッダをつけた、 次のようなフォーマットのファイル。

┌───────┬───────┬───────┬───<<───┬───<<───┐
│rootイメージの│チェック・サム│rootイメージの│lzma 圧縮した │root イメージ │
│サイズ   4byte│(CRC32)  4byte│位置     4byte│カーネル      │squashfs      │
└───────┴───────┴───────┴───>>───┴───>>───┘

つまり 前回 flash へ書込んだ image ファイルと同じフォーマットである。

image_full から root イメージを取り出すには、 このファイルのヘッダから 「root イメージサイズ」と「root イメージの位置」を取り出せばよい。

% od -t x1 image_full | head -1
0000000 00 21 bf de a2 14 d3 9b 00 0a 50 34 6d 00 00 80

先頭 4 バイトは「0021BFDE」であり、 これを 10進数に変換すると 2211806 であるから、 root イメージサイズが 2211806 バイトであることがわかる。 また、 8 バイト目から 4 バイトは「000A5034」であり、 これを 10進数に変換すると 675892 であることから、 root イメージの位置がこの「000A5034」の直後の位置 (つまり 12 バイト目) から数えて 675892 バイト目、 すなわち先頭から数えれば 675904 バイト目であることがわかる。 root イメージを取り出して展開してみる:

% dd if=image_full bs=1 skip=675904 count=2211806 of=root.squashfs
1617860+0 records in
1617860+0 records out
1617860 bytes (1.6 MB) copied, 3.61499 seconds, 448 kB/s
# unsquashfs-lzma -dest ROOT root.squashfs
Reading a different endian SQUASHFS filesystem on root.squashfs
created 407 files
created 67 directories
created 165 symlinks
created 0 devices
created 0 fifos

これで、La Fonera+ の root ディレクトリ以下の全ファイルが、 ROOT ディレクトリ以下に展開される。 unsquashfs-lzma というコマンドが見慣れないかも知れないが、 これは squashfs に含まれる unsquashfs を lzma ライブラリとリンク して作ったコマンドである。

(つづく)

Filed under: La Fonera — hiroaki_sengoku @ 08:53
2007年12月17日

La Fonera+ へ ssh でログインする (1) flash への書込み hatena_b

FON ソーシャル・ルータ La Fonera+ へログインするのは、 La Fonera のときほど容易ではない。 La Fonera はシリアル・コンソールでシェル (/bin/ash) を使えたので、 dropbear (ssh サーバ) を立ち上げるだけで、 ssh でログインできるようになる。 しかし La Fonera+ はシリアル・コンソールをつなげても シェルが動いていないので、 Linux 起動後はコンソール出力を眺めることくらいしかできない。

ログインできないようにしてあると、 余計にログインしたくなるのは人の常であるようで、 すでに多くの方が挑戦し 成功しているようだ。 基本的には、 ファームウェアを書き換えてシリアル・コンソールを 有効にしてしまえばいいだけのことであるが、 いかに La Fonera+ の機能そのままに、 シリアル・コンソールだけ有効にするかが肝であろう。

というわけで、 先人が作ったファームウェアをそのまま使うのでは面白くないので、 FON が公開しているソース を元に、 改変ファームウェアを作ってみた。 作り方を書いていると長くなるので、 次回以降で説明するとして、 まずは作った改変ファームウェアを La Fonera+ に書込むところから。

RedBoot> load -r -b 0x80040400 image
Using default protocol (TFTP)
Raw file loaded 0x80040400-0x8028062f, assumed entry at 0x80040400
RedBoot> fis create image
... Erase from 0xa8040000-0xa8280230: .....................................
... Program from 0x80040400-0x80280630 at 0xa8040000: .....................................
... Erase from 0xa87e0000-0xa87f0000: .
... Program from 0x80ff0000-0x81000000 at 0xa87e0000: .

ここで TFTP サーバから読み込んでフラッシュへ書込んだ image というファイルが、 今回作成した改変ファームウェア。 これは、 kernel と root イメージをつなげて、 先頭にヘッダをつけた、 次のようなフォーマットのファイル。

┌───────┬───────┬───────┬───<<───┬───<<───┐
│rootイメージの│チェック・サム│rootイメージの│lzma 圧縮した │root イメージ │
│サイズ   4byte│(CRC32)  4byte│位置     4byte│カーネル      │squashfs      │
└───────┴───────┴───────┴───>>───┴───>>───┘

FON のソース に含まれる (fon/target/linux/fonera-2.6/image/fonimage.pl)、 fonimage.pl コマンドを 以下のように実行すると、 この image ファイルを作成できる。

fonimage.pl  image 《lzma圧縮したカーネルイメージ》 《squashfsなrootイメージ》

前回書いたように、 La Fonera+ は起動すると「loader」を起動する。 この loader プログラムが、 上記 image ファイルを読み込んで、 カーネルと root イメージに分解し、 カーネルを lzma 展開した上で起動する。

試しに起動してみる。 printk サポートを有効にしてある (CONFIG_PRINTK=y) ので、 Linux 起動ログを見ることができる。

RedBoot> fis load loader
RedBoot> go
Failsafe loader v0.2

Looking for board config data... found at offset 0xa87f0000
Reset button GPIO: 6
Reading flash from 0xa8040000 to 0xa8280224... done.
Verifying CRC... OK - 0x9ffc079a
Uncompressing Linux... Ok, booting the kernel.
Linux version 2.6.19.2 (sengoku@senri.gcd.org) (gcc version 4.1.2) #8 Sun Dec 16 16:52:31 JST 2007
CPU revision is: 00019064
Determined physical RAM map:
 memory: 01000000 @ 00000000 (usable)
Initrd not found or empty - disabling initrd
Built 1 zonelists.  Total pages: 4064
Kernel command line: console=ttyS0,115200 rootfstype=squashfs,jffs2 init=/etc/preinit
        ... 中略 ...
switching to jffs2
mini_fo: using base directory: /
mini_fo: using storage directory: /jffs
init started:  BusyBox v1.4.1 (2007-12-13 15:41:27 JST) multi-call binary

Please press Enter to activate this console. 
eth0.0: dev_set_promiscuity(master, 1)
device eth0 entered promiscuous mode
device eth0.0 entered promiscuous mode
: udhcpc (v1.4.1) started

        ... 中略 ...

: 21 2 * * * /bin/thinclient cron

: 13 5 * * * ntpclient -s -h ntp-1.cso.uiuc.edu

: fonsmcd successfully started

La Fonera と同様に mini_fo を使って、 squashfs の上に jffs2 を 重ねることによって、 / (root ファイル・システム) を書込み可能にしている。

La Fonera と同様、 cron から /bin/thinclient を実行しているが、 実はこれは機能していない。 つまり、 /bin/thinclient cron を実行してみると、 以下のように Usage が表示されてしまう。

root@OpenWrt:/# /bin/thinclient cron
Usage /bin/thinclient (dummy|start|config|upgrade) [voucher_file]

La Fonera の thinclient が果たしていた役割は、 La Fonera+ では /usr/sbin/fonsmcd が担っているようだ。 しかしながら fonsmcd のソースは公開されていない (少なくとも前述したソースには含まれていない) ので、 詳細は不明。

シリアル・コンソールで「Enter」を入力すれば、 シェルを使うことができるようにしてある。 さらに、ネットワーク経由で ssh ログインすることもできる:

% rsh -l root 172.16.191.252


BusyBox v1.4.1 (2007-12-13 15:41:27 JST) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

  ______                                           __      
 /\  ___\                                         /\ \     
 \ \ \__/  __     ___      __   _ __    __        \_\ \___ 
  \ \  _\/ __`\ /' _ `\  /'__`\/\`'__\/'__`\     /\___  __\
   \ \ \/\ \L\ \/\ \/\ \/\  __/\ \ \//\ \L\.\_   \/__/\ \_/
    \ \_\ \____/\ \_\ \_\ \____\\ \_\\ \__/.\_\      \ \_\ 
     \/_/\/___/  \/_/\/_/\/____/ \/_/ \/__/\/_/       \/_/ 

--------------  Fonera 1.5 Firmware (v1.1.0.2) -----------------

               * Based on OpenWrt - http://openwrt.org
             * Powered by FON - http://www.fon.com
      -----------------------------------------------------
root@OpenWrt:/# df
Filesystem           1k-blocks      Used Available Use% Mounted on
tmpfs                      512         0       512   0% /dev
/dev/mtdblock4            3840       284      3556   7% /jffs
/jffs                     1664      1664         0 100% /
root@OpenWrt:/# free
              total         used         free       shared      buffers
  Mem:        13612        12680          932            0         1064
 Swap:            0            0            0
Total:        13612        12680          932
root@OpenWrt:/# ifconfig eth0.1
eth0.1    Link encap:Ethernet  HWaddr 00:18:84:XX:XX:XX
          inet addr:172.16.191.252  Bcast:172.16.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1480  Metric:1
          RX packets:1367 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1212 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:129328 (126.2 KiB)  TX bytes:184394 (180.0 KiB)

root@OpenWrt:/# 

La Fonera+ には ether ケーブルのソケットが二つついているが、 カーネルから見ると WAN 側ソケットは eth0.1 つまり VLAN デバイスとして見える。 LAN 側ソケットは eth0.0 である。

(つづく)

Filed under: La Fonera — hiroaki_sengoku @ 07:59
« Newer PostsOlder Posts »