2012/09/10

QemuでARM上にDebianをインストールしたので…

 諸般の事情で、ARMの実行環境が欲しくなったので、Qemuを使ってARM上のDebian Linux環境を用意しましたよ。

 基本的な方法としては、Qemuを使ってDebianのネットブートインストーラを使うだけなんだけど、ところどころハマったので、自分用にメモっときますよ。
というわけで、以下メモ。

教訓1: MacじゃなくてUbuntuを使う

 Mac上の(Homebrewでインストールした)Qemuがうまく動かなかったので、さっさとあきらめてUbuntuで作業することにしました。
VMware Fusionで適当に仮想マシンを作成して、普通にインストール完了。
Macの上にUbuntuの仮想マシンを用意して、さらにその上にQemuとか、豪勢な時代になったもんですね。

 インストール対象がDebianなのに、なんでUbuntuなのか、とかはツッコまない方向で><!

教訓2: Qemuを直接使う

 ここからはUbuntuの上で作業。
まず、apt-getでQemuをインストールします:

$ sudo apt-get update
$ sudo apt-get install qemu qemu-kvm-extras

 今回インストールされたバージョンは 1.0.50 でした。

 本当はGUIで操作できるQemulatorを使おうと思ったんだけど、GUIがフリーズするわ、正しくイメージ作れないわ で、さんざんな目にあったので、おとなしくCUIでやることにします。
まぁ、この手の作業にGUIはいりませんね…

教訓3: ディスクイメージはrawで作成する

 DebianをインストールするQemuのディスクイメージを作成します。
適当に10GBで作っておきます:

$ qemu-img create Debian-ARM.img 10G
Formatting 'Debian-ARM.img', fmt=raw size=10737418240 

 オプションでQemuの圧縮形式とか選べるのですが、ここではデフォルトのraw形式で作っておきます。あとでこれが重要になってきます!
ちなみに、Ubuntuで普通にext4とか使っていれば、10GBのディスクイメージを作成しても、本当に利用されている領域しか物理ディスクには割り当てられないので、容量はそんなに気にしなくて大丈夫です↓

 実際には2GBもあれば足りるかと。
qemu-img convert を使えば、あとで形式を変更することもできます。

教訓4: インストールはネットブートで

 i386系の場合は、普通にインストールCDのISOイメージから起動すればインストールできると思うのですが、ARMの場合は起動するのにもLinuxカーネルがいるんです><
幸いにも、Debian公式でARM用のネットブート用のファイルが配布されています。
ここでLinuxカーネル(vmlinuz)と、initrd2つのファイルを取得してください。

 インストール前に、Qemu仮想マシンからネットワークが使えるように準備します。
こちらの團長さんの記事を参考に(っていうか、そのまま使わせていただいて)スクリプトを用意します。

/etc/qemu-ifup:
#!/bin/sh
echo "Executing /etc/qemu-ifup"
sudo /sbin/ifconfig $1 0.0.0.0 promisc up
echo "Adding $1 to br0..."
sudo /usr/sbin/brctl addif br0 $1
sleep 3
#switch=$(/sbin/ip route list | awk '/^default / { print $5 }')
#/sbin/ifconfig $1 0.0.0.0 up
#/usr/sbin/brctl addif ${switch} $1
/etc/qemu-ifdown:
#!/bin/sh
# NOTE: This script is intended to run in conjunction with qemu-ifup
#       which uses the same logic to find your bridge/switch
sudo /usr/sbin/brctl delif br0 $1
sudo /sbin/ifconfig $1 down
#switch=$(/sbin/ip route list | awk '/^default / { print $5 }')
#/usr/sbin/brctl delif $switch $1
#/sbin/ifconfig $1 0.0.0.0 down

 これで、準備完了です。
ターミナルから以下のようにコマンドを入力します:

$ sudo qemu-system-arm -M versatilepb -kernel vmlinuz-3.2.0-3-versatile \
                       -initrd initrd.gz -hda Debian-ARM.img            \
                       -net nic -net tap,ifname=tap0 -m 256

 ここで、vmlinuz-3.2.0-3-versatile と initrd.gz はDebianサイトから取得したファイル、Debian-ARM.img は上で作成したディスクイメージのファイル名です。

 はい、インストールはじまりましたー。

 あとは、Debianのインストーラに従って進めてください。
簡単ですね><!

教訓4: パーティショニングはディスク全体を使う

 色々聞かれる質問は、好きなように答えてください。
ただ、ひとつだけ、パーティショニングの際にディスク全体を使うようにします↓

 ここ重要です!
これはディスクイメージをrawにしたのとあわせて、次に効いてきますからね。

 順調にインスールが終わり、あとは再起動するだけです。

 「続ける」をクリックして再起動します。
まだかなまだかな〜+(0゚・∀・) + ワクテカ +

 て、エッ( ゚д゚)!

 またインストーラが起動しちゃった><;

 これは、Qemuを起動する際に渡しているinitrdが、ネットブートインストール用のものだからです。(※initrdの細かい話は、他のサイトを参照のこと)
ハードディスクのファイルシステムをマウントしてそっちから起動してくれるinitrdが必要なのですが、それが公式では見つからない……initrdは、通常mkinitrdコマンドを使って作成されるからだそうです。

 こまけぇこたぁいいから、とにかく動くinitrdがいるんだよ(#゚Д゚)ゴルァ!!

 というわけで、あれこれ考えた結果、正しくDebianがインストールされていれば、今ここにあるディスクイメージの中の/bootに、Linuxカーネルと一緒にinitrdも入ってるはずです。
なので、ディスクイメージの中身を読み取ることができれば、手に入るはず!

 で、調べていたら、ディスクイメージがマウントできることを知った!
これはディスクイメージをraw形式で作っているからできることです(ついでに、LVMを使用していないから簡単にできます)。
これまでの教訓はここで生きてくるんですね!

 というわけで、fdiskでパーティションの位置を調べて、その位置をマウントします:

$ fdisk -lu Debian-ARM.img          

Disk Debian-ARM.img: 10.7 GB, 10737418240 bytes
255 heads, 63 sectors/track, 1305 cylinders, total 20971520 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0003f91b

         Device Boot      Start         End      Blocks   Id  System
Debian-ARM.img1   *        2048    20013055    10005504   83  Linux
Debian-ARM.img2        20015102    20969471      477185    5  Extended
Debian-ARM.img5        20015104    20969471      477184   82  Linux swap / Solaris

 先頭パーティションの位置を指定してマウントするわけですが、Startの値の単位はシリンダ数なのでバイト単位に換算する必要があります。
この場合、512 * 2048 = 1048576 ですね。
とりあえず、/mnt/temp にマウントすることにします:

$ sudo mkdir /mnt/temp
$ sudo mount -t ext4 -o loop,offset=1048576 Debian-ARM.img /mnt/temp
$ ls -l /mnt/temp/boot
total 4772
-rw-r--r-- 1 root root   89689 Jul 24 15:06 config-3.2.0-3-versatile
lrwxrwxrwx 1 root root      28 Sep 10 00:24 initrd.img -> initrd.img-3.2.0-3-versatile
-rw-r--r-- 1 root root 2268482 Sep 10 00:59 initrd.img-3.2.0-3-versatile
-rw-r--r-- 1 root root 1118575 Jul 24 15:06 System.map-3.2.0-3-versatile
lrwxrwxrwx 1 root root      25 Sep 10 00:24 vmlinuz -> vmlinuz-3.2.0-3-versatile
-rw-r--r-- 1 root root 1404680 Jul 24 15:05 vmlinuz-3.2.0-3-versatile

 (゚∀゚)キタコレ!!

 ここにある initrd.img-3.2.0-3-versatile がお目当てのinitrdです。
これをコピーして、Qemuの起動に使います。また、ハードディスクから起動するために、-appendオプションを追加します:

$ cp /mnt/temp/boot/initrd.img-3.2.0-3-versatile .
$ sudo qemu-system-arm -M versatilepb -kernel vmlinuz-3.2.0-3-versatile              \
                       -initrd initrd.img-3.2.0-3-versatile -hda Debian-ARM.img      \
                       -append "root=/dev/sda1" -net nic -net tap,ifname=tap0 -m 256

 キタ━(゚∀゚)━!

 起動には毎回、Linuxカーネルイメージ・initrd・ディスクイメージが必要ですので、このセットは大切に保存しておいてください。

 あとは、お好きなように!