お遊び記録

最近の活動記録

FreeBSD-arm を Pandaboard に乗せてみた (3) FreeBSD-arm 起動イメージを作成してみた

さて、いよいよFreeBSD-armの起動イメージを作成し、Pandaboradで 動かしてみます。 FreeBSD-armの起動イメージ作成手順は大変複雑です。 この複雑な手順の大半を自動化してくれる スクリプトを、Tim Kientzleさんという方が作成して下さっています。 ここでは、このスクリプトfreebsd-beagleboneを使用して行きます。




FreeBSD-arm 導入のおおまかな流れ

Intelアーキテクチャ環境にFreeBSDを導入する際に使用した bsdinstallは、arm環境にはありません。 インストールの全ては、基本的には手作業で行わねばなりません。 ちょうどNetBSDGentooを導入するようなものでしょうか。

このインストールのおおまかな流れは以下のようなものです。

  1. arm用クロスコンパイル環境を作成する
    armで動作するOSバイナルリは一般では配布されていません。 そこで自分でコンパイルする必要があります。 コンパイルする際にも、まだpandaboardではコンパイラはおろかOSも入っていませんから、 手元の母艦でコンパイルします。 母艦はインテルアーキテクチャであり、デフォルトではインテル系CPUのバイナリしか コンパイルできません。 そのため、armで動作するバイナリを出力するコンパイラ(クロスコンパイラ)を、 まず導入してやります。 ちなみに、このコンパイラやリンカなどのセットをツールチェインとも呼びます。
  2. ブートローダをコンパイルする
    arm環境ではu-bootという汎用のブートローダを使いFreeBSDのローダであるubldrを起動し、 そこからFreeBSDのカーネルを起動する、という起動手順を取ります。 そのブートローダを先に作成したツールチェインでコンパイルします。
  3. 必要ならば、FreeBSDのOSソースにpatchをあてます。 稼働させるためにまだcommitされていないpatchが必要、という事態はよくある話です。
  4. make buildworldします。もちろん、arm用バイナリを得たいので、クロスコンパイルします。
  5. make buildkernelします。やはりarm用のkernelを得るためなので、クロスコンパイルします。
  6. SDHCカードにパーティションを設定し、フォーマットします。armではブートローダの制約で 先頭にブートローダを置くfatフォーマットのパーティション、残りにUFSのFreeBSD本体を収める パーティションを設定します。
  7. SDHCカードのfatパーテョションにブートローダなどを入れます。
  8. SDHCカードのUFSパーティションにmake installkernel/make installworldします。
  9. SDHCカード上の/etc/fstabなど必要なファイルの設定を行います。

以上が手動で導入を行う際のおおまかな手順となります。

freebsd-beaglebone を入手する

freebsd-beaglebone は Tim Kientzle さんが作成したシェルスクリプトです。 先の手順の多くを自動化し、必要な手順が行われているか否かをチェックしてくれます。 以下の環境用の起動イメージを作成出来ます。

  • Beaglebone
  • Rasbery Pi
  • Pandaboard

freebsd-beagleboneはgithubで公開されています。 以下のようにして、github からclone します。

% git https://github.com/kientzle/freebsd-beaglebone.git
% cd freebsd-beaglebone

Pandaboard 用の設定を行う

入手したら、README ファイルを熟読しましょう。 その後で、  Pandaboard 用の設定を行います。 設定ファイルはconfig.sh です。サンプルファイルからコピーして設定を開始します。

% cp config.sh.sample config.sh
% vi config.sh

以下、設定のポイントをまとめます。

# REQUIRED:
# Uncomment one to choose the default configuration for your board
#
# board_setup BeagleBone
# board_setup RaspberryPi
board_setup PandaBoard

board_setup は、どの環境用のイメージを作成するかを指定します。 ここではPandaboard用のイメージを作成したいので最後の行のコメントを外します。

# REQUIRED: SD_SIZE
#
...
#
# SD_SIZE=$((100 * MB)) # for kernel-only images
# SD_SIZE=$((1950 * MB)) # for 2 Gigabyte card
# SD_SIZE=$((3900 * MB)) # for 4 Gigabyte card
SD_SIZE=$((7900 * MB)) # for 8 Gigabyte card
# SD_SIZE=$((15900 * MB)) # for 16 Gigabyte card
# SD_SIZE=$((31900 * MB)) # for 32 Gigabyte card

SD_SIZE は使用するSDカードのサイズを指定します。 大容量サイズのカードを使いたくなるのは人情ですが、 このサイズのイメージファイルを作成して書き込みを行いますので、 容量が大きいほど書き込み時間が必要になります。

ここでは8GBカードの設定を選択しています。

以上が必須の設定項目です。以下は使うと嬉しいかもしれない項目です。

# KERNCONF=MYCONF

KERNCONF はカーネル設定ファイルを指定出来ます。Pandaboardでの デフォルト値はPANDABOARDで、これは /usr/src/sys/arm/conf/PANDABPARD にあります。 カスタマイズしたい場合はこれを変更します。

# FREEBSD_SRC=/usr/src

armで使用する場合、ソースにpatchをあてることが多くなります。 インテル系の母艦のOSメンテナンスに影響を与えたくない場合は、 ソース木を分離してしまうといいでしょう。 例えばarm用ソース木は/usr/headにsvn coしておき、 そのパスをFREEBSD_SRCで指定するのです。

# INSTALL_USR_SRC=yes

コメントを外すと、起動イメージ中に/usr/src も入ります。 デフォルトは入りません。 入れておけば、Pandaboard上でmake buildworld に挑戦出来ます。

# INSTALL_USR_PORTS=yes

コメントを外すと起動イメージ中に/usr/portsもインストールされます。 Pandaboard上でportsを使った導入を行えます。

以上が主な設定項目です。この他いくつかの項目が存在します。 詳細はファイルのコメントに書かれていますので参照してください。

起動イメージを作成する

いよいよ起動イメージを作成します。その手順は、以下のとおりです。

1.クロスコンパイル環境を構築する

FreeBSDでは、クロスコンパイル環境のソースコードも/usr/src に収められています。 そこでコンパイルするだけで、必要なクロスコンパイル環境を入手出来ます。 以下のコマンドをrootになって実行します。

# cd /usr/src
# make xdev XDEV=arm XDEV_ARCH=arm

これでarm用ツールチェインが/usr/arm-freebsd 下に導入されます。 なお特に環境変数などを設定しなくとも、デフォルトのmakeファイルに必要な設定は書かれていますので 使用できます。

2.ブートローダu-bootのソースを準備する

u-bootのソースを取得し、freebbsd-beaglebone直下に展開します。

# cd freebsd-beaglebone
# fetch ftp://ftp.denx.de/pub/u-boot/u-boot-2012.07.tar.bz2
# bzcat u-boot-2012.07.tar.bz2 | tar xvf -
# mv u-boot-2012.07 u-boot-panda

3.FreeBSDのソースにpatchをあてる

2013年1月中旬現在、FreeBSD-10.0-CURRENT revision 245505 では、patchをあてることなく Pandaboard 上で起動することはできないようです。 起動途中でpanic を起こしkernel が abort します。

現時点で起動させるためには、まだcommit されていないpatch をあてる必要があります。

なお、これらpatch はいずれcommit されるかと思われます。 その場合、ここにある手順でpatchあてしようとしてもrejectされるでしょう。 あくまでも参考にのみしてください。

# cd ~
# mkdir patch
# cd patch

まず、arm/174461 にsend-pr されているキャッシュメンテナンスルーチンの 問題を修正するpatch です。これはIan Lepore さんが書かれています。

# fetch -o PR174461-patch 'http://www.freebsd.org/cgi/query-pr.cgi?pr=174461;cat=&getpatch=1'

次にOleksandr Tymoshenko さんが書かれた一連のpatch を取得します。

# fetch http://people.freebsd.org/~gonzo/patches/queue/arm-autotune-fix.diff
# fetch http://people.freebsd.org/~gonzo/patches/queue/locore.diff
# fetch http://people.freebsd.org/~gonzo/patches/ehci-bug-detect.diff

それぞれ、kernelが確保するメモリ量の問題、CPUの初期化の問題、イーサドライバの問題を修正します。

これらのpatch を当てて行きます。

# cd /usr/src
# pacth < ~/patch/PR174461-patch
# cd /usr/src/sys
# pacth < ~/patch/arm-autotune-fix.diff
# cd /usr/src/sys/arm/arm
# patch < ~/patch/locore.diff
# cd /usr/src/sys
# pacth < ~/patch/ehci-bug-detect.diff

4.必要なportsを導入しておく

u-bootのコンパイルにGNU sed が必要になるため、これを導入しておきます。

# cd /usr/ports/textproc/gsed
# make install && make clean

5.起動イメージを作成する

いよいよ起動イメージを作成します。

# cd freebsd-beaglebone
# sh beaglebone.sh

この様にスクリプトbeaglebone.sh を実行するだけです。 あとはこのスクリプトが、残る必要なコンパイルと、その結果を用いた起動イメージファイルを 作成してくれます。 この処理には非常に時間がかかります。少なくとも3時間程度は見たほうがいいでしょう。 無事終了したならば、work/FreeBSD-PANDABOARD.img に起動イメージが生成されます。

6.SDカードに焼く

あとは、このイメージをSDカードに焼くだけです。 USBメモリカードリーダにSDカードをつけて母艦に接続し、FreeBSDに認識させたらば、 以下のコマンドを実行して書き込みます。

# dd if=work/FreeBSD-PANDABOARD.img of=/dev/da0 bs=10m

bs引数は10m程度までは指定できるようです。この数値は大きいほうが書き込み時間を短縮出来ます。

7.起動する

カードに焼けたならば、Pandaboard に取り付けて起動しましょう。 このような起動メッセージが得られるはずです。

Texas Instruments X-Loader 1.41 (Sep 29 2011 - 10:43:53)
OMAP4460: 1.2 GHz capable SOM
Starting OS Bootloader from MMC/SD1 ...


U-Boot 2012.07 (Jan 14 2013 - 18:28:46)

CPU  : OMAP4460 ES1.1
Board: OMAP4 Panda
I2C:   ready
DRAM:  1 GiB
MMC:   OMAP SD/MMC: 0
Using default environment

In:    serial
Out:   serial
Err:   serial
Net:   No ethernet found.
Hit any key to stop autoboot:  0
reading ubldr

242850 bytes read
## Starting application at 0x88000054 ...
Consoles: U-Boot console
Compatible API signature found @bfef4258
Number of U-Boot devices: 1

FreeBSD/armv6 U-Boot loader, Revision 1.2
(armdevel@PandaMother-01, Wed Jan 16 23:32:23 JST 2013)
DRAM:    1024MB

Device: disk
-
/boot/kernel/kernel data=0x3da838+0x1f2fc syms=[0x4+0x78f60+0x4+0x63ab6]
Hit [Enter] to boot immediately, or any other key for command prompt.
Booting [/boot/kernel/kernel]...
fdt_start: 0x005B31D0
Kernel entry at 0x80200100...
Kernel args: (null)
KDB: debugger backends: ddb
KDB: current backend: ddb
Copyright (c) 1992-2013 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
        The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 10.0-CURRENT #0 r245505M: Wed Jan 16 23:42:05 JST 2013
    armdevel@PandaMother-01:/home/armdevel/freebsd-beaglebone/work/obj/arm.armv6/usr/src/sys/PANDABOARD arm
CPU: Cortex A9-r2 rev 10 (Cortex-A core)
 Supported features: ARM_ISA THUMB2 JAZELLE THUMBEE ARMv4 Security_Ext
 WB disabled EABT branch prediction enabled
LoUU:2 LoC:1 LoUIS:2
Cache level 1:
 32KB/32B 4-way data cache WB Read-Alloc Write-Alloc
 32KB/32B 4-way instruction cache Read-Alloc
real memory  = 1073741824 (1024 MB)
avail memory = 1043931136 (995 MB)
Texas Instruments OMAP4460 Processor, Revision ES1.1
random device not loaded; using insecure entropy
simplebus0: <Flattened device tree simple bus> on fdtbus0
gic0: <ARM Generic Interrupt Controller> mem 0xe8241000-0xe8241fff,0xe8240100-0xe82401ff on simplebus0
gic0: pn 0x390, arch 0x1, rev 0x2, implementer 0x43b nirqs 160
l2cache0: <PL310 L2 cache controller> mem 0xe8242000-0xe8242fff irq 32 on simplebus0
l2cache0: Part number: 0x3, release: 0x7
l2cache0: L2 Cache: 1024KB/32B 16 ways
mp_tmr0: <ARM Generic MPCore Timers> mem 0xe8240200-0xe82402ff,0xe8240600-0xe82406ff irq 27,29 on simplebus0
Timecounter "ARM MPCore Timecounter" frequency 504000000 Hz quality 1000
Event timer "ARM MPCore Eventtimer" frequency 504000000 Hz quality 1000
uart0: <16750 or compatible> mem 0xe8020000-0xe8020fff irq 106 on simplebus0
uart0: console (115384,n,8,1)
ti_scm0: <TI Control Module> mem 0xd62d9000-0xd62d9fff on simplebus0
setting internal 4 for usbb1_ulpiphy_stp
setting internal 10c for usbb1_ulpiphy_clk
setting internal 10c for usbb1_ulpiphy_dir
setting internal 10c for usbb1_ulpiphy_nxt
setting internal 10c for usbb1_ulpiphy_dat0
setting internal 10c for usbb1_ulpiphy_dat1
setting internal 10c for usbb1_ulpiphy_dat2
setting internal 10c for usbb1_ulpiphy_dat3
setting internal 10c for usbb1_ulpiphy_dat4
setting internal 10c for usbb1_ulpiphy_dat5
setting internal 10c for usbb1_ulpiphy_dat6
setting internal 10c for usbb1_ulpiphy_dat7
omap4_prcm0: <TI OMAP Power, Reset and Clock Management> mem 0xd62da000-0xd62dbfff,0xd62dc000-0xd62dcfff,0xd62dd000-0xd62e4fff on simplebus0
gpio0: <TI General Purpose I/O (GPIO)> mem 0xd62e5000-0xd62e5fff,0xe8055000-0xe8055fff,0xe8057000-0xe8057fff,0xe8059000-0xe8059fff,0xe805b000-0xe805bfff,0xe805d000-0xe805dfff irq 61,62,63,64,65,66 on simplebus0
gpioc0: <GPIO controller> on gpio0
gpiobus0: <GPIO bus> on gpio0
ehci0: <TI OMAP USB 2.0 controller> mem 0xd62e6c00-0xd62e6cff,0xd62e7000-0xd62e76ff,0xd62e8000-0xd62e8fff irq 109 on simplebus0
ehci0: Starting TI EHCI USB Controller
ehci0: UHH revision 0x50700100
ehci0: OMAP_UHH_SYSCONFIG: 0x00000014
ehci0: UHH setup done, uhh_hostconfig=0x8000001c
usbus0: EHCI version 1.0
usbus0 on ehci0
iichb0: <TI I2C Controller> mem 0xe8070000-0xe80700ff irq 88 on simplebus0
iichb0: I2C revision 4.0
iicbus0: <OFW I2C bus> on iichb0
iic0: <I2C generic I/O> on iicbus0
ti_sdma0: <TI sDMA Controller> mem 0xd62e9000-0xd62e9fff irq 44,45,46,47 on simplebus0
ti_sdma0: sDMA revision 00010900
ti_mmchs0: <TI MMC/SD/SDIO High Speed Interface> mem 0xe809c000-0xe809cfff irq 115 on simplebus0
mmc0: <MMC/SD bus> on ti_mmchs0
Timecounters tick every 10.000 msec
usbus0: 480Mbps High Speed USB v2.0
ugen0.1: <Texas Instruments> at usbus0
uhub0: <Texas Instruments EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1> on usbus0
mmcsd0: 7580MB <SDHC SU08G 8.0 SN 447764317 MFG 07/2012 by 3 SD> at mmc0 25.0MHz/4bit/1-block
Root mount waiting for: usbus0
Root mount waiting for: usbus0
uhub0: 3 ports with 3 removable, self powered
Root mount waiting for: usbus0
ugen0.2: <vendor 0x0424> at usbus0
uhub1: <vendor 0x0424 product 0x9514, class 9/0, rev 2.00/2.00, addr 2> on usbus0
uhub1: MTT enabled
Root mount waiting for: usbus0
uhub1: 5 ports with 4 removable, self powered
ugen0.3: <vendor 0x0424> at usbus0
smsc0: <vendor 0x0424 product 0xec00, rev 2.00/2.00, addr 3> on usbus0
Trying to mount root from ufs:/dev/mmcsd0s2 [rw,noatime]...
smsc0: chip 0xec00, rev. 0002
miibus0: <MII bus> on smsc0
ukphy0: <Generic IEEE 802.3u media interface> PHY 1 on miibus0
ukphy0:  none, 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
ue0: <USB Ethernet> on smsc0
ue0: Ethernet address: 0e:60:33:b1:46:01
warning: no time-of-day clock registered, system time will not be set accurately
Setting hostuuid: 3cb350f6-5feb-11e2-8bd9-0e6033b14601.
Setting hostid: 0xcdd5b164.
No suitable dump device was found.
Entropy harvesting: interrupts ethernet point_to_point kickstart.
Starting file system checks:
/dev/mmcsd0s2: FILE SYSTEM CLEAN; SKIPPING CHECKS
/dev/mmcsd0s2: clean, 1796048 free (1512 frags, 224317 blocks, 0.1% fragmentation)
Mounting local file systems:.
Writing entropy file:.
Setting hostname: pandaboard.
smsc0: chip 0xec00, rev. 0002
ue0: link state changed to DOWN
Starting Network: lo0 ue0.
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
        inet 127.0.0.1 netmask 0xff000000
ue0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=80001<RXCSUM,LINKSTATE>
        ether 0e:60:33:b1:46:01
        media: Ethernet autoselect (none)
        status: no carrier
Starting devd.
Waiting 30s for the default route interface: .....(no carrier)
Creating and/or trimming log files.
Starting syslogd.
realpath: /dev/dumpdev: No such file or directory
/etc/rc: WARNING: Dump device does not exist.  Savecore not run.
ELF ldconfig path: /lib /usr/lib /usr/lib/compat
Clearing /tmp (X related).
Updating motd:.
Performing sanity check on sshd configuration.
Starting sshd.
Starting cron.
Starting background file system checks in 60 seconds.

Wed Jan 16 15:32:20 UTC 2013

FreeBSD/arm (pandaboard) (ttyu0)

login:

これで起動しました。あとは独自にカーネルをHackするなり、 portsの導入を試みるなりと、さまざまな物事に挑戦出来ます。 Tear-1なインテルアーキテクチャでしたら、portsのソフトウェアも導入できて 当たり前ですが、arm環境ではそうも行きません。 様々な問題が立ちふさがってくれるでしょう。

ちょっとした情報

イメージの再作成と初回以降の起動イメージ作成時間の短縮

起動イメージを作成する際にいろいろ試していると、カーネルのソースコードだけを 書き換えて再作成することがよくあります。

こうした場合に、いちいちmake buildworldしていると、気が狂いそうになれます。 カーネルだけをいじってるのですから、buildkernelだけにしてほしいものです。

そこで、以下のようにして起動イメージを再作成するとよいでしょう。

# rm work/_.built-kernel
# sh beaglebone.sh

なお、u-bootのコンパイルを除く全てをやり直したい場合は、以下のようにして 実行します。

# rm -rf work/*
# sh beaglebone.sh

workディレクトリの下の掃除をしないと、コンパイルが実行されませんので 注意しましょう。

ここまでのまとめ

Pandaboard 上でFreeBSD-arm を起動させました。 armではソースコードの修正で簡単に動作しなくなります。 一度動作したソース木はバックアップを取るか、 少なくとも動作したrevision番号は記録し、 その際のsvn diffを残しておきましょう。 これを忘れて不用意にsvn up すると、とても悲しいことになります。