DE1-SOCで、yocto版linuxを動かす。

　DE1-SOCの[リソースサイト(http://cd-de1-soc.terasic.com)](http://cd-de1-soc.terasic.com)にも、linuxのインストールイメージは、ちゃんとあります。
　まぁ、普通に使うだけなら、これを利用するのが一番手っ取り早いんだけど･･･バージョンが少し古め。コンソール版のカーネルは、3.12で、デスクトップだと、4.5となります。
　どうも、いろいろな資料を見ていると、このベースは、yoctoプロジェクトを利用して作られているようです。というわけで、自分でも、やってみたくなり、試行錯誤した結果のメモです。
　ただ、このyoctoプロジェクト。いろいろと組み合わせて自由自在なディストリビューションを作れるのは良いのですが、モジュール間の相互作用で動かないなんてパターンも結構あるようです。現時点(2019年4月)の一事例ということで、ご容赦ください。

　さて、yoctoプロジェクトとは、linuxのコンパイルから始め、環境を構築するための一連のツールと、インストールする各種モジュールの一連の設定ファイル例をひとまとめにして、自由に組み合わせてシステムを構築できるようにしたシステムのようです。
 本家本元は、[こちら(https://www.yoctoproject.org/)](https://www.yoctoproject.org/)になります。

　そもそも、DE1-SOCで、デスクトップを使い･･･というのもあまり考えられません。ここに乗せるOSというのは、もっともっと簡単な物で良い。カラフルなユーザーインターフェースに資源を使うくらいなら、その資源は別の事に使った方が有意義なように思います。
　という発想で、とにかく最小限のシステムが欲しいというのを目標にします。
　あまり深入りすると･･･そうとう深入りもできそうな気配がありますが、その入り口のみです。

　手順の最初は、とにかく、yoctoのシステムを落としてこなくてはいけないわけですが･･･このシステムは、linuxでのみサポートされています。悲しいかな、windows上では動きません。てわけで、母艦となるlinuxの動くPCの用意が必要となります。幸い、linux仮想環境を比較的簡単に作れる世の中になりましたので、それで行くことにします。私は、OracleのVirtualBoxに、ubuntu18.10を乗せて、これを母艦とすることにしました。この環境構築に関しては、ここで書くより分かりやすい記事が山ほどあるので、ぐっぐってくださいで終わらせることにします。

　yoctoプロジェクトのトップページから、Get Started Hereの下のリンクをたどると、システムの概要を読むことができます。（ちなみに英文です･･･読む人は頑張ってください。）この文書の最後の方に、「Development Environment - Host Setup」という項があります。その最初のリンク、 Yocto Project Quick Build. をクリックすると、そのページに、「Yocto Project Quick Build 2.6.1 」という比較的大きなリンクがあります。この文書が、私がスタートラインにした手順書になります。
　ここから、逸脱する、DE1-SOCに関連する話題を中心に、進めます。

　まずは、これからの作業に必要となる最低50Gバイトのハードディスク領域をubuntu上に確保してください。できれば、100G程度あると幸せになれるでしょう。
　プロジェクトに利用するディレクトリを適当な名前で作成します。（私は、もう素直に、yoctoというディレクトリを作成しました。今後の説明は、このディレクトリを基準点とします。）
　次に、必要なライブラリー・ツール群のインストールです。開発環境では、良く使われるもの達なので、もう入っているかもしれませんね。
```
$ sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib \
  build-essential chrpath socat cpio python python3 python3-pip python3-pexpect \
  xz-utils debianutils iputils-ping libsdl1.2-dev xterm
```
　をインストールせよとあります。

　次は、yocto本体のインストールですが、これは、gitでクローンをするだけ。先に作ったyoctoディレクトリの下で
```
$ git clone git://git.yoctoproject.org/poky
```
とすると、完了です。ただし、結構大きな代物で、下手すると時間単位かかるかもしれません。終了すると、pokyというディレクトリができます。
　このディレトクリに行くと、「oe-init-build-env」というファイルがあります。これを実行すると、これからの作業に必要な環境を全て自動で作ってくれます。
```
$ source ./oe-init-build-env
```
実行すると、buildというディレクトリが作られ、カレントディレクトリもそこになります。今後、作業を中断して再開する時には、このスクリプトをまず実行する必要があります。

次に、cyclone5に必要なファイル群をダウンロードします。とりあえず、yocto/pokyに移動し直してください。
```
$ cd ~/poky
$ git clone https://github.com/kraj/meta-altera.git
```
で、必要なファイル群が落とせます。
さらに、
```
$ git clone git://git.openembedded.org/meta-openembedded
```
も落としておきます。これは、ntdを作成するのに必要なので入れました。ただ、ここには、相当なユーティリティー達のファイルが存在します。インデックスが、[https://layers.openembedded.org/layerindex/branch/master/layers/](https://layers.openembedded.org/layerindex/branch/master/layers/)にあります。ここを眺めて、必要そうなものがあれば、足してみるのも良いかもしれません。

　さて、カレントディレクトリをbuildに戻しましょう。ここに、「conf」というディレクトリが作られています。この中に、「bblayers.conf  local.conf」という二つのファイルがあります。bblayers.confは、作成するlinuxシステムの骨組みを指定するファイルです。yoctoでは、layerという単位で、ある程度のモジュールとその設定の塊が定義されます。このlayerを重ねていくことで（また、自分で作成する）ことで、システムを構築します。
　今回、作成した、bblayers.conの中身は、次の通り。

```bblayers.conf
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
  /home/mito/de1soc/yocto/poky/meta \
  /home/mito/de1soc/yocto/poky/meta-poky \
  /home/mito/de1soc/yocto/poky/meta-yocto-bsp \
  /home/mito/de1soc/yocto/poky/meta-openembedded/meta-oe \
  /home/mito/de1soc/yocto/poky/meta-openembedded/meta-perl \
  /home/mito/de1soc/yocto/poky/meta-openembedded/meta-networking \
  /home/mito/de1soc/yocto/poky/meta-openembedded/meta-python \
  /home/mito/de1soc/yocto/poky/meta-altera \
  "
```
最初の段階で、meta-yocto-bspまでの行が定義されています。その後ろは、私が付け加えた物です。
　meta-alteraの行は、cylone5の為の設定等が含まれます。必須です。
　meta-openembeddedの含まれる四行は、ntpの為に追加しました。本当に欲しかったのは、meta-networkingです。残りは、依存関係を満たすためにあります。

　次に、local.confの設定が必要です。これは、作成するシステムの詳細と環境の設定を行います。が･･･結構長い。長い理由の大半は、デフォルトでつくコメントにあります。ばっさり、コメントを抹殺した内容を掲載します。

``` local.conf
MACHINE ??= "cyclone5"
DL_DIR ?= "/home/****/yocto/download"

SSTATE_DIR ?= "${TOPDIR}/sstate-cache"

DISTRO ?= "poky"

PACKAGE_CLASSES ?= "package_rpm"

USER_CLASSES ?= "buildstats image-mklibs image-prelink"

PATCHRESOLVE = "noop"

BB_DISKMON_DIRS ??= "\
    STOPTASKS,${TMPDIR},1G,100K \
    STOPTASKS,${DL_DIR},1G,100K \
    STOPTASKS,${SSTATE_DIR},1G,100K \
    STOPTASKS,/tmp,100M,100K \
    ABORT,${TMPDIR},100M,1K \
    ABORT,${DL_DIR},100M,1K \
    ABORT,${SSTATE_DIR},100M,1K \
    ABORT,/tmp,10M,1K"

/2.5/PATH;downloadfilename=PATH"

PACKAGECONFIG_append_pn-qemu-system-native = " sdl"
PACKAGECONFIG_append_pn-nativesdk-qemu = " sdl"

CONF_VERSION = "1"

BB_NUMBER_THREADS = "4"
PARALLEL_MAKE = "-j 4"

IMAGE_INSTALL_append = " avahi-daemon"
IMAGE_INSTALL_append = " git "
IMAGE_INSTALL_append = " libstdc++"
IMAGE_INSTALL_append = " ntp"

TOOLCHAIN_TARGET_TASK_append = " kernel-devsrc"

IMAGE_INSTALL_append = " tzdata"
DEFAULT_TIMEZONE = "Asia/Tokyo"

INHERIT_append = " extrausers"
EXTRA_USERS_PARAMS = " \
            useradd -p '' user; \
            groupadd sinkigroup; \
            usermod -s /bin/bash user;"

hostname_pn-base-files = "de1soc"

#use systemd
DISTRO_FEATURES_append = " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_initscripts = ""
IMX_DEFAULT_DISTRO_FEATURES_append = " systemd"
```
　それでも、長いのですが=^･･;=。デフォルトからの変更・追加は、次の通り。

* MACHINE ??= "cyclone5"
　この行は、対象となるシステムを指定します。DE1-SOCの場合、システムのチップは、cyclone5となりますので、これを指定します。

* DL_DIR ?= "/home/\*\*\*\*/yocto/download"
　自分のディレクリ構成に合わせてください。ここはフルパスでの設定が必要です。"~/****"の略記法は使えないので注意してください。このディレクトリは、この後、システム作成でダウンロードしてくる大量のファイルの保存先です。デフォルトのままでも良いのですが、あえてpoky配下から外しておくと、次にやり直す時に、ダウンロードの時間が数時間単位で節約できます。（gitの扱いをしくじってにっちもさっちもいかなくなり、poky以下をばっさり削除してやり直した時は、本当に有り難みを感じました（笑））

* IMAGE_INSTALL_appendの一群
　追加でインストールするモジュールが指定されています。私は、この程度を指定しました。何を入れているかは、名前を見ればわかりますよね。

* TOOLCHAIN_TARGET_TASK_append = " kernel-devsrc"
　この行をつけておくと、この後作成する、母艦のクロスコンパイル用環境にlinuxソースが入ります。デバイスドライバを作成するなら、あると便利です。（無くても、生成物の中にlinuxソースがあるので、そちらを使うという手もあるのですが、やたらと深い階層に密かに隠れているのと別途システムコンパイルの手間が必要で、使うのが面倒です。）
 
* IMAGE_INSTALL_append = " tzdata"
　これと、次の行で、作成するシステムのtzdataが設定をしています。ちなみに、これが無いと、日本時間の表示ができなくなります。

* INHERIT_append = " extrausers"のブロック
　デフォルトで作成しておきたいユーザー・グループがあれば、ここで作れます。必要なければ、ブロックごと消しても問題ありません。

* hostname_pn-base-files = "de1soc"
　この行は、システムのホスト名を指定しています。デフォルトの名前だと、avahiを使うのに支障があるので、変えました。お好きな名前をどうぞ。

* \#use systemd以降
　デフォルトでは、サービスの構成がinit.dで作成されます。これを今時のsystemdに切り換えるための一連の設定です。init.dで運用するなら不要です。

 さて、設定は終わりました。
```
$ bitbake-layers show-recipes | grep image-
```
　としますと、今の設定で作成できるシステムのイメージの名前が一覧できます。今回は、core-image-full-cmdlineを指定しました。
　生成は、次のコマンドです。
```
$ bitbake core-image-full-cmdline
```
　この実行には、大変大変時間がかかります。寝る前に実行して朝結果を見るくらいで大丈夫です。というくらいかかりますので、覚悟して実行しましょう。（特に、初回は、ダウンロードに大量の時間を消費します。）
```
$ bitbake core-image-full-cmdline -c populate_sdk
```
　を実行すると、母艦でのクロスコンパイル環境を作成してくれます。
　
　やっと、システムをインストールできる状態が整いました。
　実は、起動に必要なuboot関係もこれまでの作業で作成されています。SDカードのイメージもあります。でも、altera公式では、これを使うのは非推奨となっています。で、これをまっとうに作るのは結構骨が折れそうだったので、手を抜きました。
　ボードのサポートパッケージの中から、適当なlinuxイメージをSDカードにコピーすれば、必要なuboot環境は当然入っています。これを流用することにして、今回のシステムに必要な部分を書き換えます。（目一杯手抜きで、最大の難点は、自分で作った回路のデバイスツリーデータが反映されないことです。これも、自分でdtbファイルを作れば良いのですが、これが一筋縄ではいかない･･･。）

　サポートパッケージのSDを作ると、中に３つのパーティーションがあります。一つは、FATシステムの800M程度の領域。もう一つは、unknownなファイルシステム。もう一つがEXT4形式の領域です。
　FATシステムの中に、linuxのシステムイメージファイル(zImage)があります。また、FPGAのコンフィギュレーションファイルもここにあります。
　unknownな領域には、一番最初に起動されるローダーが入っています。これの内容は、干渉する必要は無いでしょう。(preloaderと言うようです。)
　EXT4の領域は、ご想像の通り、rootファイルシステムです。
　ぶっちゃけ、zImageと、rootファイルシステムを書き換えてしまえば、作業は終わりです。
　linux仮想環境に、sdカードを認識させられるなら、作業も簡単です。

 まず、今までの作業の成果物ですが、yocto/poky/build/tmp/deploy/images/cyclone5にあります。
　ここを、ls \*rootfs\*、で見てみると、tar.gzファイルが一つ出てきます。（正確な名前は、環境に左右されると想像されます。うちでは、「core-image-full-cmdline-cyclone5-20190403141415.rootfs.tar.gz」となりました。）これが、ルートファイルシステムです。SDカードのEXT4形式の領域を全部消してしまって、このファイルを展開すれば、ルートファイルシステムのインストールは終わりです。
　FAT領域に、同じディレクトリにある、zImageを上書きコピーします。

　これで、超手抜き版インストールは終わりです。
　何にも入ってないので、本当に小さなシステムが出来上がります。
　起動して確認してみましょう。

　最後に、クロス開発環境のインストールと使い方。

* yocto/poky/build/tmp/deploy/sdkに、生成されたクロス開発環境が入ってます。
* この中に長い名前の.shファイルが一つあります。正確な名前は、母艦の環境などにも左右されると思うのですが、私の時は、poky-glibc-x86_64-core-image-full-cmdline-armv7at2hf-neon-cyclone5-toolchain-2.6+snapshot.shとなりました。これを実行すると、インストール先のディレクトリを聞いてくるので指定してあげれば、インストール完了です。
* インストール先のディレクトリを見ると、environment-setupで始まるスクリプトがあります。これを
```
$ source environment-setup-armv7at2hf-neon-poky-linux-gnueabi
```
　で実行すると、クロスコンパイルに必要な環境変数一式が設定されるので、この状態で、開発を行うことになります。詳細な内容は、スクリプトを確認してください。余りにファイル名が長いので、シンボリックリンクを適当な場所に作るとよいかもしれません。

　例えば、
```
$ $CC hello.c
```
で、簡単なコンパイルなら実行可能です。
Makefileで指定するような大概の変数は、ここで定義されているので、普通に書けば、ターゲット用の実行ファイルが作成されると思います。

今回は、ここまで。
メモ書きなので、読みにくいところも多々あると思いますが、ご容赦ください。