Ubuntuのカーネルパッケージは、Linuxカーネルにいくつもの手を加えUbuntuのさまざまな機能にとって必要なConfigを有効にしたうえで作成しています。今回はそのUbuntuカーネルパッケージを少しだけカスタマイズしてビルドする方法を紹介します。
カーネルパッケージをビルドする理由をひねりだす
第278回の「Ubuntuカーネルとの付き合い方 」でも紹介したように、UbuntuにとってLinuxカーネルはもっとも重要なコンポーネントの1つです。そのためカーネルに対しては、フルタイムで働くCanonical社員も含む専用のメンテナンスチームが次期リリースに向けての開発方針の決定、アップストリームからのパッチの取り込み、サポート期間中のすべてのリリースにおけるセキュリティアップデート対応などを行っています。
そんなカーネルパッケージですから、普通の利用であればUbuntuパッケージをそのまま使用するほうが良いでしょう。もしカスタマイズするとなると、自分でセキュリティアップデートに追随する必要がありますし、コンフィグの変更によって何かのソフトウェアが動かなくなる可能性もあります。よって、よっぽどのことがない限り、独自のカスタマイズはしないことを強くお勧めします。
それを踏まえたうえでカーネルパッケージを自前でビルドする必要があるとすれば、次のような動機が考えられます。
カーネルそのものやドライバーの開発
Linuxカーネルやカーネルドライバーの開発者であれば、当然のことながらカーネルをビルドする必要は出てくるでしょう。ただしこのケースの場合は、Ubuntuのカーネルをベースにすることはほとんどなく、アップストリームの特定のバージョンのカーネルだったり、LSP/BSPなどで提供されるベンダーのコードを利用することになりますし、あえてパッケージングまで行うこともあまりないはずです。もしパッケージングするとなるとMainlineBuilds という形で、Debianパッケージに必要なファイル群のカーネルソースコードへの取り込みから行うことになります。
Ubuntuカーネルの不具合を修正したい
カーネルに起因すると思われる何か不具合に遭遇したときに、デバッグメッセージを仕込んだカーネルを作成して、テストします。すでに他の場所で修正されていることがわかっている場合は、それの修正を取り込んで試してみることもあるでしょう。
特定のデバイスやソフトウェアを動かすためにConfigを変更する必要がある
カーネルの特定の機能と連携するタイプのデバイスやソフトウェア(たとえばsystemdやLXC)を使うとき、Ubuntuの標準設定とは異なるConfigで、カーネルを再構築しなければならないときがあります。
パフォーマンスチューニング
特定の用途向けにLinuxカーネルを使うとき、パフォーマンスをチューニングするために、Linuxカーネルのコードその物に手を加えたり、Configを変更することもあります。パラメーターの変更程度であればカーネルオプションやsysctlでも行えたりしますが、より深く、より細かくとなると、カーネルの再構築も必要になってくるかもしれません。とくにUbuntuのカーネルは、一般的なデスクトップPCやPCサーバー上で動かすことを想定して設定が行われていますので、用途を限定したときに不要となるものも多数存在するでしょう。
知的好奇心・勉強・興味本位
これは言わずもがな、ですね。
今回は例としてOpenBlocks AX3 のカーネルパッケージを作成してみます。OpenBlocks AX3はMarvellのARMADA XP(MV78260)を搭載した国産の小型ARMサーバーです[1] 。12.04まではUbuntuでもARMADA XP用のイメージを配布していたために、そのイメージを使えば比較的簡単にOpenBlocks AX3上にUbuntuをインストールできましたが、Ubuntu 14.04 LTSではARMADA XPのイメージは提供されなくなりました。
幸い、ARMADA XPのソースコードやOpenBlocks AX3のDevice Treeは14.04で採用されている、3.13カーネルには取り込まれています。さらに、14.04のARM向けカーネルはCONFIG_ARCH_MULTIPLATFORMが有効になっているので、genericフレーバーにConfigを追加するだけで、OpenBlocks AX3のカーネルパッケージを作成できそうです。
そこで、ここではConfigを変更したカーネルパッケージの作成方法を紹介しつつ、具体例としてOpenBlocksを取り上げます。上記の動機に照らし合わせると、3つ目の「特定のデバイスやソフトウェアに……」に該当します。あくまで例ですので、作成手順は他のアーキテクチャーやフレーバーにも応用できます。
パッケージにするメリット
カーネルをただビルドして使用するだけでなく、パッケージ化するメリットにはどんなものがあるのでしょうか。
まず複数マシンへのカーネルやモジュール、ソースコードのインストールやアップグレード、ダウングレードが簡単になります。パッケージファイルをコピーしてdpkgコマンドを実行するだけで済むのは魅力的ではないでしょうか。もちろんリポジトリの構築や電子署名も行えば、aptコマンドによるインストールも可能です。
さらにパッケージにしておけば、DKMSによるモジュールの再構築や、Initramfsの生成、GRUBの起動エントリの更新も自動的に行われます。これは/etc/kernelディレクトリ以下のスクリプトがカーネルパッケージのインストールや削除、更新時に実行されるためで、具体的にどんなことをやっているのかは、/etc/kernelディレクトリを参照してください。
実際にビルドしてみる
カーネルパッケージをビルドするには、まず開発環境を準備して、ソースコードを用意し、変更を加えたうえでビルドスクリプトを実行します。詳しいことはUbuntuのドキュメント にまとまっていますが、今回のポイントは次の3つです。
ARMカーネルなのでクロスコンパイル環境も準備する
Ubuntuカーネルのgitリポジトリからソースコードを取得する
変更するのはdebian.master/の下にある設定ファイルだけ
開発環境の構築
Ubuntu上でカーネルビルドに必要なパッケージをインストールします。ターゲットのアーキテクチャはARMですが、クロスコンパイルするため、amd64アーキテクチャ上でも問題ありません。ただし、Ubuntuのバージョン自体は合わせておいたほうが良いでしょう。
Linuxカーネルをビルドするために必要なパッケージはかなりたくさんあります。このためビルド用に隔離された環境を1つ用意して、その上に開発環境を用意するのも1つの手です。もしLXCを使うなら、以下のように実行すると良いでしょう。
$ sudo apt install lxc
$ sudo lxc-create -t ubuntu-cloud -n linuxbuilder -- --auth-key=/home/`id -un`/.ssh/id_rsa.pub
$ sudo lxc-start -n linuxbuilder -d
$ ssh ubuntu@`sudo lxc-info -in linuxbuilder | awk '{print $2}'`
$ sudo update-alternatives --set editor /usr/bin/vim.basic
もちろん、普段の環境や他の仮想マシン上で行う場合は、上記は必要ありません。最後のコマンドは標準のエディターをnanoからvimに変更しているだけです 。
次に必要なパッケージをインストールしましょう。
$ sudo apt install git fakeroot build-essential gcc-arm-linux-gnueabihf \
libncurses5 libncurses5-dev libelf-dev binutils-dev devscripts \
u-boot-tools
$ sudo apt-get build-dep linux
build-depでそのパッケージを構築するために必要なパッケージをインストールできます。ちなみに13.10以前の環境であれば、linuxはlinux-metaから提供されているため、代わりに「linux-image-`uname -r`」を指定してください。
gitはUbuntuカーネルのソースコードをgitリポジトリから取得するために指定しています。必要に応じてgitの設定もしておきましょう。たとえばコミットログに記載する名前やメールアドレスは次のように設定します。
$ git config --global user.name "Mitsuya Shibata"
$ git config --global user.email [email protected]
gcc-arm-linux-gnueabihfは、armhfアーキテクチャ用のクロスコンパイラです。他のアーキテクチャを使う場合は、適宜変更してください。ホストとターゲットが同じCPUアーキテクチャなら、インストールする必要はありません。u-boot-toolsはU-Boot用のイメージファイルを作成する場合に必要になります。
ソースコードのダウンロード
次にカーネルのソースコードをダウンロードします。おもに次の3つのいずれかを実行します。
Ubuntuカーネルのgitリポジトリを使う
公式リポジトリにあるソースパッケージをダウンロードする
リポジトリにないバージョンをダウンロードする
これまでリリースされたUbuntuカーネルのソースコードは、カーネルチームのgitリポジトリ でメンテナンスされています。よって、gitでcloneすれば、特定のリリースのカーネルやその変更履歴が取り出せます。たとえば14.04(コードネームがtrusty)の、実際使っているカーネル(3.13.0-30-generic #55)を取り出すには次のように実行します。
●バージョンの確認
$ uname -a
Linux linuxbuilder 3.13.0-30-generic #55-Ubuntu SMP ...
●ソースコードの取得(時間がかかる)
$ git clone git://kernel.ubuntu.com/ubuntu/ubuntu-trusty.git
$ cd ubuntu-trusty
●上記で確認したバージョンをベースに、新規ブランチを作成
$ git tag -l Ubuntu-3.13.0-30*
Ubuntu-3.13.0-30.54
Ubuntu-3.13.0-30.55
$ git checkout -b openblocks Ubuntu-3.13.0-30.55
gitで取得しておけば、次のカーネルアップデート時も、openblocksブランチをrebaseするだけで、アップデートに追随できるのでお勧めです。ただしgitのcloneには時間がかかるので注意してください。
バージョン管理をしなくても良いのであれば、直接ソースパッケージをダウンロードしても良いでしょう。13.10以前の場合は、「 linux」を「linux-image-`uname -r`」に変更してください。
●最新版をダウンロードする
$ apt-get source linux
●バージョンを指定したい場合
$ apt-get source linux:3.13.0-30.55
この方法でダウンロードできるのは、リポジトリに存在するパッケージだけです。他のリリースのソースコードをダウンロードしたい場合は、ubuntu packages からパッケージを検索したうえで、ソースパッケージをdgetします。たとえば12.04のカーネルパッケージ であれば、ページ下部にあるlinux_3.2.0-65.99.dscファイルを使って、次のように実行します。
$ dget -x http://archive.ubuntu.com/ubuntu/pool/main/l/linux/linux_3.2.0-65.99.dsc
パッケージのビルド
カーネルのソースコードをダウンロードできましたので、まずは何も変更を加えずにパッケージのビルドを試してみましょう。
●クロスコンパイル用の設定
$ export $(dpkg-architecture -aarmhf); export CROSS_COMPILE=arm-linux-gnueabihf-
●debian/controlやビルドディレクトリのセットアップ
$ fakeroot debian/rules clean
●アーキテクチャに依存するパッケージのビルド
$ fakeroot debian/rules binary-generic
●アーキテクチャに依存しないパッケージのビルド
$ fakeroot debian/rules binary-indep
最初の「クロスコンパイル用の設定」は、ホストとターゲットのアーキテクチャが同じなら(amd64上でamd64パッケージをビルドするなら)必要ありません。
3つ目のbinary-genericターゲットは、指定したアーキテクチャに対するgenericフレーバー用のパッケージを作成します[2] 。別フレーバーをビルドする場合は「generic」の部分をそのフレーバー名に変更し、そのアーキテクチャーでサポートしているすべてのフレーバーをビルドするなど、「 binary-generic」の代わりに「binary-debs」ターゲットを指定します。
ちなみにbinary-genericは、Intel Core i5-3317U/4GBメモリー/SSDという環境で、だいたい2時間20分ぐらいかかりました[3] 。
パッケージは親ディレクトリに作成されます。
$ ls ../*.deb
linux-cloud-tools-common_3.13.0-32.56_all.deb
linux-doc_3.13.0-32.56_all.deb
linux-headers-3.13.0-32-generic_3.13.0-32.56_armhf.deb
linux-headers-3.13.0-32_3.13.0-32.56_all.deb
linux-image-3.13.0-32-generic_3.13.0-32.56_armhf.deb
linux-source-3.13.0_3.13.0-32.56_all.deb
linux-tools-common_3.13.0-32.56_all.deb
ubuntu-trusty
linux-cloud-tools-commonは、Hyper-V上でUbuntuを動かす場合に使うデーモンです。linux-docはドキュメント類のパッケージで。linux-headerdsはともにヘッダーファイルなどが入っているパッケージで、カーネルモジュールのビルドやDKMSを利用する場合にどちらも必要になります。linux-imageがカーネルイメージやモジュール類を提供するカーネルパッケージの本体になります。linux-sourceはカーネルソースコードをシステムにインストールするためのパッケージになります。最後のlinux-tools-commonは、カーネルソースのtoolsディレクトリをビルドしたソフトウェアが入っています。
カーネルイメージとモジュール類だけで良いのであれば、linux-imageパッケージをビルドするbinary-genericターゲットのみを実行すれば十分です。
パッケージのカスタマイズ
ちゃんとビルドできることを確認したところで、次は実際にパッケージをカスタマイズしてみましょう。
Configファイルの構成
カーネルのカスタマイズの基本は、カーネルコンフィグの変更です。「 make defconfig」や「make menuconfig」で.configファイルを生成・編集するという手順を知っている方も多いでしょう。
Ubuntuのカーネルパッケージの場合、.configの作成はパッケージのスクリプト側で対応します。binary-genericやbinary-debsターゲットを実行したときに、自動的にアーキテクチャやフレーバーごとに.configを生成して、カーネルビルドを行うのです。そのため、Configファイルはアーキテクチャ・フレーバーごとに別途管理されています。
そこでまずはパッケージビルドの大まかな流れを把握したうえで、どんな風にConfigファイルが生成されているのか確認してみましょう。以下のファイルリストは、カーネルのソースパッケージ含まれるファイルの一部を抽出したものです。
debian/
debian.env
rules
rules.d/
scripts/
debian.master/
abi/
changelog
config/
amd64/
armhf/
config.common.armhf
config.flavour.generic
config.flavour.generic-lpae
config.common.ubuntu
enforce
rules.d/
amd64.mk
armhf.mk
debian/rulesがビルドスクリプトの本体となります。armhfアーキテクチャに対してdebian/rulesのbinary-genericターゲットを実行すると、おもに次のような処理が行われます。
debian.envが読み出されサブのdebianディレクトリ(debian.master)を決定する。
debian/rules.dとdebian.master/rules.d/armhf.mkを読み込む。debian.master/rules.d/には、アーキテクチャ固有の設定が記述されている。
ビルドするアーキテクチャとフレーバーに合わせて、debian/rules.d/2-binary-arch.mkの"stamp-prepare-tree"ターゲットで、debian.master/config以下にあるConfigファイルを連結し、ビルドディレクトリ(debian/build/build-generic/)に.configとして保存する。
生成されたConfigのうち、必須オプション(debian.master/config/enforce)が有効になっているかどうかを、debian/scripts/config-checkで確認する。
debian.master/rules.d/armhf.mkのbuild_imageをビルドする。
debian/scripts/module-checkとdebian/scripts/abi-checkを使って、debian.master/abi/以下に保存されている前回リリースしたバージョンのシンボルやモジュールリストと比較を行う。
ビルドしたファイル群をDebianパッケージとしてまとめる。
.configを生成しているのは3.の部分なのですが、ここで使っているのはcatコマンドとmake silentoldconfgです。とどのつまり、次のようなコマンドを実行しているだけです。
$ cat config.common.ubuntu armhf/config.common.armhf armhf/config.flavour.generic > build/build-generic/.config
$ cd build/build-generic; make silentoldconfig
よって、カーネルコンフィグを変更するときは、debian.master/config/以下のファイルを編集します。config.common.ubuntuがフレーバー、アーキテクチャ共通の設定、config.common.armhfがarmhfアーキテクチャ固有の設定、config.flavour.genericがarmhfアーキテクチャのgenericフレーバー固有の設定になります。
フレーバーの追加
Configを大きく変更する場合は、既存のフレーバーを上書きするのではなく、新規にフレーバーを追加することも考えたほうが良いでしょう。おもな編集ポイントは次のとおりです。
「debian.master/rules.d/$(ARCH).mk」のflavours行に、新しいフレーバー名を追加する
「debian.master/config/$(ARCH)/config.flavour.フレーバー名」を作成する
ビルド時は「debian/rules binary-フレーバー名」を実行する
今回はMultiPlatform対応のgenericカーネルに、OpenBlocks AX3のConfigを追加するだけなので、新規フレーバーは作成しません。
OpenBlocks AX3の場合
編集すべきところがわかったところで、OpenBlocks AX3に必要な設定を有効にしていきましょう。
OpenBlocks AX3のdefconfigはarch/arm/configs/mvebu_defconfigのようです。このファイルをそのままdebian.master/config/config.common.ubuntuに追加しても良いのですが、既存の設定と重複しているところが多々あります。そこで一度内容を確認してみます。まず、次のようなスクリプトをcheck_config.shという名前で作成してください。
check_config.sh
#!/bin/bash
cat $1 | while read line
do
[ -z "$line" ] && continue
if echo $line | grep -q "^#" ; then
# "# CONFIG_ABC is not set" to "CONFIG_ABC"
conf=`echo $line | sed "s/^# \(.*\) is not set/\1/"`
else
# "CONFIG_ABC=y" to "CONFIG_ABC"
conf=${line%=*}
fi
orig=`grep "$conf[= ]" $2`
if [ -z "$orig" ]; then
echo "Added : $line"
elif [ "$line" = "$orig" ]; then
echo "Duplicate: $line"
elif [ "# $conf is not set" = "$orig" ]; then
echo "Uncomment: $line"
elif echo $line | grep -q "^# " ; then
echo "Commented: $conf (Ubuntu is $orig)"
else
echo "Changed : $orig => ${line#*}"
fi
done
そして既存のConfigをubuntu_configsという名前のファイルに保存し、比較を行ってみます。
$ cd ubuntu-trusty
$ cat debian.master/config/config.common.ubuntu > ../ubuntu_configs
$ cat debian.master/config/config.common.ports >> ../ubuntu_configs
$ cat debian.master/config/armhf/config.common.armhf >> ../ubuntu_configs
$ cat debian.master/config/armhf/config.flavour.generic >> ../ubuntu_configs
$ chmod u+x ../check_config.sh
$ ../check_config.sh arch/arm/configs/mvebu_defconfig ../ubuntu_configs | sort
Added : # CONFIG_EXT3_FS_XATTR is not set
Added : CONFIG_ARMADA_THERMAL=y
Added : CONFIG_EXPERIMENTAL=y
Added : CONFIG_I2C_MV64XXX=y
Added : CONFIG_MACH_ARMADA_370=y
Added : CONFIG_MACH_ARMADA_XP=y
Added : CONFIG_MMC_MVSDIO=y
(中略)
Changed : CONFIG_BT=m -> y
Changed : CONFIG_BT_MRVL=m -> y
(中略)
Commented: CONFIG_CACHE_L2X0 (Ubuntu is CONFIG_CACHE_L2X0=y)
Commented: CONFIG_DEBUG_BUGVERBOSE (Ubuntu is CONFIG_DEBUG_BUGVERBOSE=y)
Commented: CONFIG_IOMMU_SUPPORT (Ubuntu is CONFIG_IOMMU_SUPPORT=y)
Commented: CONFIG_SCHED_DEBUG (Ubuntu is CONFIG_SCHED_DEBUG=y)
Commented: CONFIG_SWP_EMULATE (Ubuntu is CONFIG_SWP_EMULATE=y)
Duplicate: # CONFIG_COMPACTION is not set
Duplicate: CONFIG_AEABI=y
Duplicate: CONFIG_ARCH_MVEBU=y
(中略)
Uncomment: CONFIG_DEBUG_USER=y
Uncomment: CONFIG_EXT2_FS=y
Uncomment: CONFIG_EXT3_FS=y
Uncomment: CONFIG_GPIO_SYSFS=y
(後略)
Addedがubuntu_configsでは設定されていない項目、ChangedがUbuntuからMVEBUで値が変更された項目、CommentedがMVEBUで「is not set」にされた項目、Duplicateが値が同じ項目、Uncommentが「is not set」から変更された項目です。
Addedは原則としてそのまま追加し、Duplicateは他のところで設定されているために追加する必要はありません。ChangedとConfig、Uncommentは内容によって判断することになります。変更する箇所は、debian.master/config以下のどこにもないものはconfig.flavour.genericに、それ以外については記載のある場所を変更するか、config.flavour.genericを変更するかは随時判断することになるでしょう。今後、カーネルパッケージをアップデートするときに、Ubuntuの変更点を取り込みやすいほうを選びましょう。
編集したら、一度Configを再生成してみます。
$ debian/rules updateconfigs
これによりsilentoldconfigを行うため、未設定の項目についてはプロンプトが表示されます。ビルドの自動化まで考えているのであれば、ここの項目を参考に、さらにdebian.master/configを設定してください。さらにupdateconfigsでは、すべてのアーキテクチャとフレーバーで矛盾がなくなるように、debian.master/config以下を再構築します。このため、config.common.ubuntuに設定されていたものが、armhf/config.flavour.genericと矛盾するために、各アーキテクチャのconfig.flavour.に分散設定されるようになる、ということも起こります。具体的にどこが変更されたかは、“ git diff” などで確認してください。
DTBファイルのインストール
ハードウェアのプロパティについて記述するDevice Tree に対応したアーキテクチャであれば、DTBファイルをパッケージに含めることができます。OpenBlocks AX3用のDvice Treeがカーネルのソースコードに含まれていますので、これもパッケージに含めてしまいましょう。
$ echo -e 'dtb_files_generic\t+= armada-xp-openblocks-ax3-4.dtb' >> debian.master/rules.d/armhf.mk
armhf.mkの中に、「 dtb_files_フレーバー名 += DTVファイル名」と書いておくと、そのフレーバーのバイナリパッケージの「/lib/firmware/カーネルバージョン/device-tree/」以下にDTBファイルが保存されます。Debice Treeのソースコードは「arch/arm/boot/」以下に存在しますので、そこから必要になるファイル名を探してください。
debian.master/changelogの編集
最後にdebian.master/changelogを編集します。このときのバージョン名がCONFIG_VERSION_SIGNATUREなどに使われます。よくわからなければ、下記コマンドのように1つ前のエントリのバージョンに「+ラベル」というバージョンにしておきましょう。
$ dch -v "$(dpkg-parsechangelog -SVersion -ldebian.master/changelog)+obs1" \
-c debian.master/changelog "Support OpenBlocks AX3"
Linux (3.13.0-30.55+obs1) trusty; urgency=low
(変更点をここに記述)
Linux (3.13.0-30.55) trusty; urgency=low
(3.13.0-30.55リリース時の変更点)
Linux (3.13.0-30.54) trusty; urgency=low
ただし、この場合binary-genericターゲットのmodule-check/abi-checkはchangelog上の1つ前のエントリ(3.13.0-30.55)に対して実行しようとします。しかしながら、debian.master/abi/以下には2つ前のエントリ(3.13.0-30.54)の情報しかないため、チェックに失敗してしまいます。本来はメンテナースクリプトを使って前のバージョンのABI情報を生成するのですが、面倒であればチェックそのものをスキップしてしまいましょう。
$ skipmodule=true skipabi=true fakeroot debian/rules binary-generic
上記のようにskipmodule/skipabiにtrueを設定しておけば、module-check/abi-checkは何も行いません。恒常的に設定を変更したい場合は、debian/rules.d/0-common-vars.mkのAUTOBUILDに1を設定してください。
あとは「パッケージのビルド」に従ってビルドすれば、変更が適用されたパッケージが作成されます。debファイルはlessコマンドで中身を表示できますので、新規に指定したモジュールやDTBファイルがlinux-imageパッケージに含まれるか確認してください。
そして次のステップへ
新規に作成したカーネルパッケージは、そのままdpkgコマンドでインストールできます。GRUBがインストールされた環境であれば、/etc/kernel/postinst.d/zz-update-grubによって、GRUBの起動エントリも自動的に更新されているはずです。インストール後再起動し、unameコマンドで新しいカーネルになっていることを確認してください。
今回の例ではパッケージ名が公式リポジトリのそれと同じになるので、Pinで固定しないと 公式リポジトリのカーネルパッケージがアップデートされたときに、別のカーネルに差し変わってしまうでしょう。
ARMデバイスのように、ブートローダーがU-Bootの場合はもう一手間以上必要になります。UbuntuのカーネルパッケージにはU-Boot用のイメージファイルは含まれていないため、既存のカーネルイメージやInitramfsをu-boot-toolsパッケージのmkimageコマンドで変換し、場合によってはU-Bootの環境変数やboot.scrを変更しなくてはいけないからです[4] 。
Initramfs(通常は/boot/initrd.img-3.13.0-30-genericといった名前になります)は、カーネルパッケージには存在しません。パッケージインストール時に、initramfs-toolsパッケージのコマンドで自動生成やアップデートを行うためです。
カーネルそのものはMultiPlatformに対応しているARMデバイスすべてで共通になるのですが、U-Boot対応のカーネルイメージはボードによって異なります。よって、UbuntuのNetbootインストール用のカーネルイメージ はボード毎にDTBデータを埋め込んだ状態で用意されています。Netbootでインストールしたい場合は、同じようにカーネルイメージを作成したうえで、Initramfsイメージ(uInitrd)に今回作ったlinux-imageのカーネルモジュールをインストールしておく必要があるでしょう。なおこのuInitrdもU-Bootのヘッダー部分(先頭64バイト)がデバイス毎に異なりますので、そのまま他のデバイスに流用することはできません。
別にインストーラーは必要ないということであれば、開発マシン上でUbuntu Coreを外付けディスクなりSDカードなりに展開 したうえで、chrootしてdpkgコマンドで作成したカーネルパッケージをインストールしてしまえば、ルートファイルシステムの完成です。この方法ならInitramfsも手に入れられるので一石二鳥になります。
このようにデバイスによっては、パッケージを作成した後もいろいろとやらなければいけないことが出てくるものの、一度「Ubuntuのやり方」を把握しさえすれば、あとは他の対応デバイスと同じことが実現できます。最近はHummingBoard などおもしろそうなARMデバイスもちょこちょこ増えていますので、夏休みの課題に特定ボード向けのカーネルパッケージを作ってみるのはいかがでしょうか。
[4] このへんはflash-kernelパッケージによってある程度自動化できます。ただしUbuntu 14.04 LTSのflash-kernelはDebianのそれに比べて古いバージョンをベースにしており、OpenBlocks AX3のサポートが入っていないため、OpenBlocks AX3上で動かすためにはカスタマイズが必要です。