SH4ターゲット(SolutionEngine MS7750SSE01)のためのクロス開発環境の構築

2004/04/12 阿部 昌裕 <m-abe at aandd.co.jp>
(C) 2001-2004 A&D Co., Ltd. <http://www.aandd.co.jp/>
[English]

目次

1. はじめに
2. 前提
2.1 ホスト環境
2.2 ターゲット環境
3. 準備
3.1 ディレクトリの用意
3.2 必要なファイルの入手
3.3 追加パッチの入手
4. ツールのインストール
5. Linux Kernelの構築
6. ipl, liloの用意
6.1 iplの用意
6.2 liloの用意
6.3 iplをターゲットにインストール
7. ブートできることを確認
7.1 CompactFlashの内容の準備
7.2 ターゲットのブート
8. ターゲット用CFの内容の整備
8.1 ターゲットCF作成用ファイルの取得
8.2 ライブラリrpmファイルの用意
8.3 ncursesの構築
8.4 busyboxの構築
8.5 tinyloginの構築
8.6 追加rpmファイルの展開
8.7 基本スクリプトファイルのコピー
8.8 ファイルをCFにコピーして途中経過の確認
8.9 tcp_wrappersの構築
8.10 netkit-ftpの構築
8.11 netkit-telnetの構築
8.12 linux-ftpdの構築
8.13 ファイルをCFにコピーして最終確認


1. はじめに

この書類では、日立SH4プロセッサの評価ボードであるSolutionEngine MS7750SSE01をターゲットとする、x86ホストでのクロス開発環境の構築手順を記す。

この書類は、すべてのケースを想定したHOWTO書類ではない。特定の環境における成功例のケーススタディと捉えて欲しい。異なるケースに適用するには、 各自の創意工夫を期待したい。

この場を借りて、SH3/4プロセッサへのLinux Kernel及びGNU Toolchainの移植作業に携わるすべての方々に、これまでの努力に対して敬意と感謝の念を評する。

なお、文中に出てくる固有名詞には商標や登録商標に当たるものもあるが、特にそれぞれについて言及はしないので注意して欲しい。

なお、この書類に記されている内容、及び同時に公開されるパッチファイルについては全くの無保証であり、著者はその内容に関して一切の責任を負わない。こ の書類については、どんな用途であれ内容の開示や複製を行うことができる。


2. 前提

2.1 ホスト環境

当方では、以下のようなホスト環境で作業を行った。
以下の文中の作業は、全てrootでログインして行うことを想定している。

2.2 ターゲット環境

ターゲットは、以下のような条件で使用することにした。

3. 準備

3.1 ディレクトリの用意

下記のようにディレクトリを作成する。
/root/sh/               作業用ディレクトリ
        basket/         圧縮ファイルを入れておくためのディレクトリ
                        {target host}ディレクトリを中に用意
        dest/           ターゲットのファイルシステムを模擬するディレクトリ
                        {boot}ディレクトリを中に用意
        temp/           テストプログラム構築ディレクトリ
/root/cvsroot/m17n      sh-ipl+g,sh-lilo取得ディレクトリ
/mnt/target/            ターゲットのファイルシステム(CF上)のマウント先

3.2 必要なファイルの入手

Linux Kernelについては、kernel.orgの2.4.18 vanila カーネルを使う。"linux-2.4.18.tar.bz2"ファイルを取得し、/root/sh/basketに入れる。

クロスコンパイラなどのツールは、<http://www.sh-linux.org/> から取得する。

rpm-2003/RPMS/noarch/host/:             --> /root/sh/basket/host/に取得
rpm-2003/RPMS/i386/:                    --> /root/sh/basket/host/に取得
rpm-2003/RPMS/sh4/:                     --> /root/sh/basket/target/に取得
ipl、liloについては、m17n.orgのCVSから以下のようにして取得する。

# mkdir -p /root/cvsroot/m17n
# cd /root/cvsroot/m17n
# cvs -d:pserver:anonymous@cvs.m17n.org:/cvs/superh login
CVS Password:<そのままreturn>
# cvs -d:pserver:anonymous@cvs.m17n.org:/cvs/superh co ipl+g
# cvs -d:pserver:anonymous@cvs.m17n.org:/cvs/superh co lilo


こうすることで、/root/cvsroot/m17n/の下にipl+gおよびliloディレクトリができて、その中に必要なファイルが取得される。

busyboxは、<http://www.busybox.net> またはミラーサイトから/root/sh/basket/target/に取得する。現時点での最新版は1.00-pre8なので、それを使う。

tinyloginは、<http://tinylogin.busybox.net> またはミラーサイトから/root/sh/basket/target/に取得する。現時点での最新版は1.4なので、それを使う。

3.3 追加パッチの入手

上記のKernel、Toolchainに対して追加で適用するパッチを取得する。このドキュメントと同じ場所に置かれている以下のファイルである。/root/sh/basketに取得する。

4. ツールのインストール

まずは、クロスコンパイルするためのツールをホストPCにインストールする。

# cd ~/sh/basket/host
# rpm -Uvh binutils-sh-linux-xxx.i386.rpm
# rpm -Uvh glibc-sh-linux-xxx.i386.rpm
# rpm -Uvh glibc-sh4-linux-xxx.i386.rpm
# rpm -Uvh zlib-sh-linux-xxx.i386.rpm
# rpm -Uvh zlib-sh4-linux-xxx.i386.rpm
# rpm -Uvh gcc-sh-linux-xxx.i386.rpm

5. Linux Kernelの構築

ここまでで、kernel構築に必要なツールが用意されたので、kernelを構築してみる。

まず、カーネルソースを用意する。

# cd ~/sh/basket
# tar xjf linux-2.4.18.tar.bz2
# cd linux
# bzcat ../patch-2.4.18-sh-xxx.diff.bz2 | patch -p1
# cd ..
# mv linux /usr/src/linux-sh-2.4.18
# cd /usr/src
# ln -s linux-sh-2.4.18 linux-sh-2.4
# cd /usr/src/linux-sh-2.4.18

以上の手順で、ビルドするためのカーネルのソースが/usr/src/linux-sh-2.4.18として用意される。また、そこへのリンクとして /usr/src/linux-sh-2.4ができる。クロスコンパイラは、/usr/src/linux-sh-2.4にカーネルソースがあるものとし て動作するので、このリンクファイルが必要なのである。

次に、カーネルのコンフィグレーションを行う。SolutionEngine MS7750SSE01用にデフォルトのconfigファイルを用意したので、それを元に行う。

# cp arch/sh/configs/defconfig-se7750 .config
# make ARCH=sh CROSS_COMPILE=sh4-linux- menuconfig
[お好みで設定、保存して終了]


カーネルをビルドする。

# make ARCH=sh CROSS_COMPILE=sh4-linux- INSTALL_MOD_PATH=/root/sh/dest clean dep zImage modules modules_install
# cp arch/sh/boot/zImage /root/sh/dest/boot/


以上の作業で、~/sh/destの下の適切なディレクトリの中にカーネルとモジュールがインストールされる。

最後に、アプリケーション構築のために必要となるインクルードファイルのディレクトリの設定を行う。

# cd /usr/sh-linux/include
# ln -s /usr/src/linux-sh-2.4/include/asm asm
# ln -s /usr/src/linux-sh-2.4/include/linux linux

6. ipl, liloの用意

カーネルをブートさせるために必要な、ipl(Initial Program Loader)とlilo(LInux LOader)を構築し、iplをターゲットにインストールする。

6.1 iplの用意

cvs.m17n.orgにあるソースは、現時点でバグを一つ含んでいるので、以下のパッチを適用する。

Index: ide.c
===================================================================
RCS file: /cvs/superh/ipl+g/ide.c,v
retrieving revision 1.16
diff -u -r1.16 ide.c
--- ide.c    26 Jun 2001 07:34:55 -0000    1.16
+++ ide.c    5 Apr 2004 05:23:20 -0000
@@ -302,8 +302,10 @@
 
   if (i == TIMEOUT)
     return -1;
-  else if (ide_inb (IDE_ERROR) != 1)
-    return -1;
+  else if (status & IDE_ERR){
+    if (ide_inb (IDE_ERROR) != 1)
+      return -1;
+  }
   return 0;
 }
 


適用したら、iplを構築する。

# cd /root/cvsroot/m17n/ipl+g
# ln -s config/config.mk-sesh4-pcmcia config.mk
# ln -s config/config.h-sesh4-pcmcia config.h
# make CROSS_COMPILE=sh4-linux-

6.2 liloの用意

cvs.m17n.orgにあるソースに、以下のパッチを適用する。

Index: first.S
===================================================================
RCS file: /cvs/superh/lilo/first.S,v
retrieving revision 1.17
diff -u -r1.17 first.S
--- first.S    25 Dec 2000 04:58:51 -0000    1.17
+++ first.S    7 Apr 2004 04:15:57 -0000
@@ -44,7 +44,7 @@
     !
     .ascii    "LILO"
     .word    1
-#if 1
+#if 0
     /* EDIT HERE ! */
             ! Depends LILO's version
     .word    20
Index: partition.c
===================================================================
RCS file: /cvs/superh/lilo/partition.c,v
retrieving revision 1.1
diff -u -r1.1 partition.c
--- partition.c    25 Dec 2000 04:58:51 -0000    1.1
+++ partition.c    7 Apr 2004 04:15:57 -0000
@@ -23,7 +23,7 @@
 
 
 /* For older kernels ... */
-
+#if 0
 #ifndef DOS_EXTENDED_PARTITION
 #define DOS_EXTENDED_PARTITION EXTENDED_PARTITION
 #endif
@@ -31,7 +31,7 @@
 #ifndef LINUX_EXTENDED_PARTITION
 #define LINUX_EXTENDED_PARTITION EXTENDED_PARTITION
 #endif
-
+#endif
 
 void part_verify(int dev_nr,int type)
 {

liloを構築する。

# cd /root/cvsroot/m17n/lilo
# make CROSS_COMPILE=sh4-linux-
# cp boot.b ~/sh/dest/boot/

6.3 iplをターゲットにインストール

/root/cvsroot/m17n/ipl+g/READMEを参考に、sh-stub.srecファイルをターゲットマシンのFlashROMに焼 き込む。

私は以下のようにして、Windowsマシンから焼き込んだ。
  1. ターゲットのボーレートを115200に設定
  2. ftp/samba等で、sh-stub.srecファイルをWindowsマシンに転送
  3. Windowsマシンとターゲットをシリアルのクロスケーブルで接続
  4. HyperTerminalでターゲットに接続、ターゲットのSW4-3をonにする
  5. ターゲットに通電
  6. ROM Monitorが動くことを確認(Hyperterminalに出力がある)
  7. Ready>プロンプトに"fl 80000000"と入力してReturnキーを押す
  8. 転送メニューの"テキストファイルの送信"を選び、sh-stub.srecファイルを指定
  9. 転送が終了したら、ターゲットの電源を落とす
  10. ターゲットのSW4-3をoffにする
  11. ターゲットに通電
  12. Hyperterminalにsh-ipl+gのバナーメッセージが出たら成功
  13. ターゲットの電源を落とし、Hyperterminalを閉じる

7. ブートできることを確認

CFにカーネルとliloをインストールし、ターゲットでブートさせてみる。

私の環境では、USB接続のCompactFlash Reader/Writerは/dev/sdaとして認識されるようになっている。その仮定で以下の手順を説明する。設定が異なる場合には、適宜読み変え て欲しい。

7.1 CompactFlashの内容の準備

/root/sh/destの下に必要なディレクトリやファイルを作成する。

# cd /root/sh/dest
# mkdir -p bin boot dev etc home lib proc root sbin tmp usr var dev/pts usr/bin usr/lib usr/sbin lib/modules var/log
# cd /dev
# cp -a console hda hda? kmem mem null rtc sda sda? tty tty? urandom ptyp? ttyp?
/root/sh/dest/dev/
# cd /root/sh/dest/dev
# ln -s ../proc/self/fd/0 ./stdin
# ln -s ../proc/self/fd/1 ./stdout
# ln -s ../proc/self/fd/2 ./stderr
# mknod ttySC0 c 204 8
# mknod ttySC1 c 204 9

/root/cvsroot/m17n/lilo/READMEに書かれているような内容で/root/sh/dest/etc/lilo- se.confファイルを作成する。私の場合には、CFは/dev/sdaなので、以下のようになった。

linear
boot=/dev/sda
disk=/dev/sda
        bios=0x80
vga=normal
delay=30
image=/boot/zImage
        label=linux
        root=/dev/hda1
        append="mem=64M sh_mv=SolutionEngine console=ttySC1,115200"
        read-only

CF R/WをホストのUSBコネクタに接続してから、CompactFlashをCF R/Wに装着する。

次のコマンドで、CompactFlashを初期化する。

# modprobe usb-storage
# fdisk /dev/sda
[単一パーティションを一つ作成]
# mke2fs -j /dev/sda1
# mount /dev/sda1 /mnt/target


以上で、CompactFlashのパーティションが/mnt/targetにマウントされる。

続けて次のようにコマンドを打つ。

# cd /root/sh/dest
# cp -auf * /mnt/target/
# lilo -r /mnt/target -C /etc/lilo-se.conf


"Added linux *"と出れば成功である。

最後のコマンドを打ったときに、ホストの構成によっては"バージョンが合わない"というエラーが出ることがある。この場合、そのメッセージの中でどういう バージョンを要求しているかを読み取り、それに合わせて/root/cvsroot/m17n/lilo/first.Sの中の以下の部分を修正する。

                      /* v--- Major Version */
        .word   4*256 + 21
        !    /* ^--- Minor Version*/    


"21.3"が要求されていたら、"3*256 + 21"と修正するわけである。修正後、liloをmakeし、出来たboot.bを/root/sh/dest/boot/と /mnt/target/boot/にコピーしてから、先の最後のコマンドを発行する。

CFをumountして、Linuxホストから取り外す。

# umount /mnt/target
# modprobe -r usb-storage

7.2 ターゲットのブート

CFをターゲットに装着し、ターゲットとLinuxホストをシリアルクロスケーブルで接続する。

# cu -l /dev/ttyS0 -s 115200

と打つと、"connected."と出る。ここでターゲットに通電すると、sh-ipl+gのバナーメッセージが表示される。プロンプトに対して"b" と打つと、カーネルのブートが始まり、"Kernel Panic"で止まるはずである。

ここまで来れば、これまでの作業が正しく行われたことが確認できる。


8. ターゲット用CFの内容の整備

ターゲット上で動作するLinuxディストリビューションを、CompactFlash上に整備する。

8.1 ターゲットCF作成用ファイルの取得

先にダウンロードした、ターゲット向けディストリビューション作成用ファイルを解凍する。

# cd /root/sh/basket/target
# tar xjf ../make_rootfs-xxx.tar.bz2


これで、/root/sh/basket/target/make_rootfsディレクトリができる。

8.2 ライブラリrpmファイルの用意

先にダウンロードしたターゲット向けライブラリrpmファイルを/root/sh/dest以下に展開する。

まず、rpmを展開するために必要な処理を行う。

# mkdir -p /root/sh/dest/var/lib/rpm
# rpm --root /root/sh/dest --initdb


ライブラリrpmファイルを/root/sh/destに展開する。

# cd /root/sh/basket/target
# rpm --root /root/sh/dest -ivh --ignorearch --noscripts --nodeps glibc-xxxxx.sh4.rpm
# rpm --root /root/sh/dest -ivh --ignorearch --noscripts --nodeps libstdc++-xxxxx.sh4.rpm
# rpm --root /root/sh/dest -ivh --ignorearch --noscripts --nodeps libtermcap-xxxxx.sh4.rpm

8.3 ncursesの構築

以下のコマンドで構築する。

# cd /root/sh/target/make_rootfs/ncurses
# tar xzf ncurses-5.2.tar.gz
# cd ncurses-5.2
# cat ../ncurses-sh-5.2-20010724.diff | patch -p1
# cd ..
# mkdir sh4-ncurses
# cd sh4-ncurses
# BUILD_CC=gcc BUILD_CFLAGS="-O2 -Wall" CC=sh4-linux-gcc CFLAGS="-O2 -Wall" LD=sh4-linux-ld AR=sh4-linux-ar RANLIB=sh4-linux-ranlib ../ncurses-5.2/configure --prefix=/usr --host=sh4-linux --build=`arch`-linux --with-install-prefix=`pwd`/_install --with-shared --without-debug --disable-profile --without-cxx --without-ada
# make
# make install


以下のコマンドで、ホスト上にライブラリとヘッダをインストールする。

# cd _install/usr
# cp include/ /usr/sh-linux/include/ncurses -a
# cp lib/* /usr/sh-linux/lib/ -a
# cd /usr/sh-linux/include
# ln -s ncurses/curses.h ./
# ln -s ncurses/eti.h ./
# ln -s ncurses/form.h ./
# ln -s ncurses/menu.h ./
# ln -s ncurses/ncurses.h ./
# ln -s ncurses/panel.h ./
# ln -s ncurses/term.h ./
# ln -s ncurses/termcap.h ./
# ln -s ncurses/unctrl.h ./


以下のコマンドで、/root/sh/destにライブラリをインストールする。

# cd /root/sh/basket/target/make_rootfs/ncurses/sh4-ncurses/_install/usr
# cp -a lib/*.so* /root/sh/dest/usr/lib/


ライブラリの依存関係を解決する。

# ldconfig -vr /root/sh/dest

8.4 busyboxの構築

先に取得した圧縮ファイルを解凍し、ファイルを用意する。

# cd /root/sh/basket/target/make_rootfs/busybox/
# tar xjf ../../busybox-1.00-pre8.tar.bz2
# cd busybox-1.00-pre8
# cp ../defconfig .config


構築する。

# make menuconfig
[必要であればオプションを変更する]
# make
# make install


構築されたファイルを/root/sh/destにコピーする。

# cp -a _install/* /root/sh/dest/

8.5 tinyloginの構築

先に取得した圧縮ファイルを解凍し、ファイルを用意する。

# cd /root/sh/basket/target/make_rootfs/tinylogin/
# tar xjf ../../tinylogin-1.4.tar.bz2
# cd tinylogin-1.4


構築する。

# make CROSS=sh4-linux-
# make CROSS=sh4-linux- install


tinyloginの権限を変更する。

# chmod +s _install/bin/tinylogin

構築されたファイルを/root/sh/destにコピーする。

# cp -af _install/* /root/sh/dest/

8.6 追加rpmファイルの展開

rpmで用意されたいくつかのアプリケーションを展開する。

# cd /root/sh/basket/target
# rpm --root /root/sh/dest -ivh --ignorearch --noscripts --nodeps e2fsprogs-xxxxx.sh4.rpm
# rpm --root /root/sh/dest -ivh --ignorearch --noscripts --nodeps bash-xxxxx.sh4.rpm

# rpm --root /root/sh/dest -ivh --ignorearch --noscripts --nodeps modutils-xxxxx.sh4.rpm

8.7 基本スクリプトファイルのコピー

/root/sh/basket/target/make_rootfs/scripts の中のファイルをすべて /root/sh/destの中にコピーする。

# cp -af /root/sh/basket/target/make_rootfs/scripts/* /root/sh/dest/

8.8 ファイルをCFにコピーして途中経過の確認

以上の処理で、基本的なディストリビューションのファイルが用意されたので、CFにコピーして起動してみる。

CFをUSB-CFRWに装着してから、次のコマンドを実行する。

# modprobe usb-storage
# mount /dev/sda1 /mnt/target
# cd /root/sh/dest
# cp -auf * /mnt/target/
# lilo -r /mnt/target -C /etc/lilo-se.conf
# umount /mnt/target
# modprobe -r usb-storage


CFをホストから外し、ターゲットに装着する。コンソールでつないでから、ターゲットの電源を入れる。ユーザ名"root"、パスワード"pass"と入 れてEnterキーを押すとログインできる。

まず、モジュールの依存関係を解決する。

# depmod -a

その後、コマンドをいくつか打ってみて、動いていることを確認する。

動作を確認したら、"halt"コマンドでターゲットを終了し、電源を落とす。

8.9 tcp_wrappersの構築

以下のコマンドで構築する。

# cd /root/sh/basket/target/make_rootfs/tcp_wrappers
# tar xzf tcp_wrappers_7.6.tar.gz
# cd tcp_wrappers_7.6
# cat ../tcpw7.2-config.patch | patch -p1
# cat ../tcpw7.2-setenv.patch | patch -p1
# cat ../tcpw7.6-netgroup.patch | patch -p1
# cat ../tcpw-barterly-yp.patch | patch -p1
# cat ../tcp_wrappers-sh-linux.patch | patch -p1
# make linux CC=sh4-linux-gcc AR=sh4-linux-ar RANLIB=sh4-linux-ranlib


以下のコマンドで、ホスト上にライブラリとヘッダをインストールする。

# cp tcpd.h /usr/sh-linux/include/
# cp libwrap.a /usr/sh-linux/lib/


構築されたファイルを/root/sh/destにコピーする。

# cp tcpd /root/sh/dest/usr/sbin/

8.10 netkit-ftpの構築

以下のコマンドで構築する。

# cd /root/sh/basket/target/make_rootfs/netkit-ftp
# tar xzf netkit-ftp-0.17.tar.gz
# cd netkit-ftp-0.17
# cat ../netkit-ftp-sh-linux.patch | patch -p1
# CC=sh4-linux-gcc ./configure
# make


構築されたファイルを/root/sh/destにコピーする。

# cp ftp/ftp /root/sh/dest/usr/bin/

8.11 netkit-telnetの構築

以下のコマンドで構築する。

# cd /root/sh/basket/target/make_rootfs/netkit-telnet
# tar xzf netkit-telnet-0.17.tar.gz
# cd netkit-telnet-0.17
# cat ../netkit-telnet-sh-linux.patch | patch -p1
# CC=sh4-linux-gcc CXX=sh4-linux-g++ ./configure
# make -C telnetd


構築されたファイルを/root/sh/destにコピーする。

# cp telnetd/telnetd /root/sh/dest/usr/sbin/in.telnetd

8.12 linux-ftpdの構築

以下のコマンドで構築する。

# cd /root/sh/basket/target/make_rootfs/linux-ftpd
# tar xzf linux-ftpd-0.17.tar.gz
# cd linux-ftpd-0.17
# cat ../linux-ftpd-sh-linux.patch | patch -p1
# CC=sh4-linux-gcc ./configure
# make


構築されたファイルを/root/sh/destにコピーする。

# cp ftpd/ftpd /root/sh/dest/usr/sbin/in.ftpd

8.13 ファイルをCFにコピーして最終確認

以上の処理で、ディストリビューションのファイルが用意された。CFにコピーして起動してみる。

CFをUSB-CFRWに装着してから、次のコマンドを実行する。

# modprobe usb-storage
# mount /dev/sda1 /mnt/target
# cd /root/sh/dest
# cp -auf * /mnt/target
# lilo -r /mnt/target -C /etc/lilo-se.conf
# umount /mnt/target
# modprobe -r usb-storage


CFをホストから外し、ターゲットに装着する。コンソールでつないでから、ターゲットの電源を入れる。ユーザ名"root"、パスワード"pass"と入 れてEnterキーを押すとログインできる。

linuxホストマシンから、ターゲットに対して、ftpやtelnetで接続してみる。ユーザ名"shuser"・パスワード"pass"でログオンで きるはずである。

動作を確認したら、"halt"コマンドでターゲットを終了し、電源を落とす。