組み込みLinuxのブートシーケンス

組み込みLinuxの起動シーケンスの図。電源を入れると、SDカード、eMMC、ネットワークのいずれかから起動し、SoCのハードウェア初期化とU-Bootのロードがおこなわれる。次にLinuxカーネルが、CPUやMMUなどのハードウェアを制御する。最後にRootfsをマウントし、ユーザ空間の処理が始まる。

組み込みLinux開発では、システムの電源を入れてからOSが起動するまでの「ブートシーケンス」を正確に理解することが求められます。

本記事では、ブートローダである「U-Boot」からカーネル、そしてrootfsがマウントされるまでの流れを解説します。実際のコマンドやYocto Projectを用いた実践的な運用方法も紹介するので、実務での開発やトラブルシューティングにお役立てください。

U-Bootのブートの流れとは|組み込みLinux起動シーケンスの全体像

システムの起動は、ハードウェアの初期化からOSの呼び出しへと順に制御を引き継ぐリレー形式でおこなわれます。ここではその全体像を解説します。

組み込みシステムでのU-Bootの役割とGRUBとの違い

SoCやボードの構成によっては、ブートROMが軽量なSPLを起動します。SPLはオンチップSRAMなどで動作し、DRAMを初期化した後、ストレージからU-Boot properをDRAMへロードして制御を引き渡します。

SPL(Secondary Program Loader)からU-Boot本体への移行

組み込み機器の起動は「多段階」でおこなわれます。電源投入直後のシステムは、SoC(System on Chip)内蔵の小容量なSRAM(Static RAM)など、限られた領域しか使えません。U-Boot本体(U-Boot proper)はこの狭い領域には入りきらないため、まずは軽量なSPLが起動します。

SPLはオンチップSRAM等の限られた領域で動作し、外部の大容量メモリであるDRAM(Dynamic RAM)のコントローラを初期化したうえで、ストレージからU-Boot本体をDRAMにロードして制御を渡すことで、高度なブート処理へ移行できる仕組みです。

Linuxカーネルの起動とrootfs/initramfsの扱い

initramfsを使用する構成では、カーネルはinitramfsアーカイブをメモリ上のrootfsへ展開し、内部の /init を実行します。/init は必要なドライバの準備や本来のrootfsのマウントをおこなった後、switch_root などを用いて実rootファイルシステム上のinitへ処理を引き継ぎます。その後のファイルシステム(rootfs)のマウント方法は、システム構成によって異なります。

構成によっては、eMMCなどの永続ストレージ上にあるrootfsを直接マウントします。

一方、別の構成として、本番ストレージを読み込むためのドライバをロードする目的で、カーネルはまずメモリ上に展開される軽量な初期ファイルシステム(initramfs)をマウントします。その後、必要な準備を終えた段階でswitch_rootコマンドなどを用いて最終的なrootfsへとルートを切り換え、システムの起動を完了します。

U-Bootのブートの流れを制御する主要コマンドと環境変数

実務では、U-Bootのコマンドや変数を操作して起動プロセスを制御します。

実際の開発現場で必要となるU-Bootコマンド一覧

開発現場のデバッグや設定変更で頻出する主要コマンドは以下のとおりです。

  • printenv:現在の環境変数を確認する
  • setenv:環境変数を設定(変更)する
  • saveenv:設定した環境変数を不揮発性メモリに保存する
  • bootz:メモリに配置したzImage形式のカーネルイメージを起動する

ブートプロセスをカスタマイズする環境変数の設定

U-Bootの起動時の挙動は、ビルド時の設定、デバイスツリー、環境変数、およびブートスクリプトや標準ブート設定などによって決まります。特に重要なのが、自動実行されるコマンドラインを定義するbootcmdと、カーネルに渡す起動オプションを指定するbootargsです。

bootargsでは、ログを出力するコンソールやrootfsの場所を指定し、システム構成にあわせてカスタマイズします。

ブートスクリプト(boot.scr)を用いた起動処理の自動化

実務では、毎回手動でコマンドを入力するわけではありません。テキストファイルに記述した起動用コマンド群をmkimageでU-Boot用のスクリプトイメージへ変換し、boot.scrとして配置します。boot.scrは、U-Bootの起動コマンドを自動実行するために利用できる方式の一つです。ボードやU-Bootの設定によっては、extlinux.conf、FITイメージ、標準ブート機構などを使用する場合もあります。

実機で確認するU-Bootのブートの流れとカーネル展開手順

OSイメージを実機に書き込み、起動を確認する流れとセオリーを解説します。

ストレージ(SDカード・eMMC)からの起動ファイル読み込みの仕組み

起動メディアは適切にパーティション分割されている必要があります。一例として、FAT形式のブート用パーティションにカーネル、DTB、起動設定を配置し、ext4形式の別パーティションにrootfsを配置する構成があります。U-Boot本体の配置場所は、SoCのブートROM仕様により、eMMCのブートパーティション、未パーティション領域、SPIフラッシュなどで異なります。

シングルボードコンピュータを用いたU-Bootからカーネル・initramfsのブート手順

SoCによっては、CPUコアの実行前にブートROM、補助プロセッサ用ファームウェア、またはSPI EEPROM上のブートローダが初期化を担当する構成があります。実際の起動順序、読み込むファイル名、U-Bootの配置方法は、使用するSoCおよびボードの公式ブート仕様で確認してください。

このような構成におけるシングルボードコンピュータの起動の流れはやや特殊で、最初にCPUではなくGPUのファームウェアが動作します。GPUがハードウェアを初期化した後、u-boot.binが読み込まれ、そこからカーネルイメージ(zImageなど)やinitramfsを呼び出すという手順を踏みます。なお一部の最新のシングルボードコンピュータでは、EEPROM(Electrically Erasable Programmable Read-Only Memory)のブートローダがこの役割を担います。

評価ボードのブートシーケンスと実機確認

シリアルコンソールでは、多くのU-Boot構成でバージョン情報や自動起動までの待機メッセージを確認できます。ただし、表示内容や待機時間、キー入力による停止可否は、U-Bootの設定および環境変数によって異なります。電源を入れると、まずU-Bootのバージョン情報が流れ、「Hit any key to stop autoboot:」というカウントダウンが表示されます。ここでキーを押さずに待つと、自動的にカーネルがメモリに展開され、「Starting kernel ...」というログとともにLinux側へ制御を引き渡します。起動しない場合は、mdコマンドでメモリ上の内容やロード先アドレスを確認します。あわせて、ロードコマンドの戻り値、ファイルサイズ、チェックサム、DTBおよびinitramfsのアドレス範囲、U-Bootとカーネルのログを確認します。

Yocto Projectを活用したU-Bootのブートの流れと実装手順

現在主流のYocto Projectを使った開発環境でのU-Bootの扱い方を解説します。

Yocto Projectを利用したU-Bootのビルドと組み込み

Yocto Projectでは、BSPレイヤおよびマシン設定でU-Bootを採用している場合、BitBakeレシピによりU-Bootを取得・クロスコンパイルできます。生成物をどのメディアのどの領域へ配置するかは、BSP、WKS_FILEなどのWic設定、イメージレシピ、およびSoCのブート仕様に依存します。

Yocto環境でのブートスクリプトの実務的な運用

ターゲットボードごとの起動設定は、BSPレイヤ、マシン設定、U-Boot設定、カーネルコマンドライン、Wic設定、起動スクリプトなどで管理します。boot.scrを利用する構成では、レシピでボードごとのスクリプトを生成・配置する方法もあります。

開発プロセスのU-Boot起動時のトラブルシューティング

ブート時の代表的なエラーがVFS: Unable to mount root fs on unknown-block(X,X) のようなカーネルパニックです(前後のログはカーネルバージョンや設定によって異なる)。このエラーは、カーネルが指定されたrootファイルシステムをマウントできない状態を示します。主な原因には、root= で指定したブロックデバイスまたはUUIDの誤り、パーティション構成の不一致、ストレージ・ファイルシステムドライバがカーネルに組み込まれていないこと、デバイスの初期化待ち不足、デバイスツリー設定の不備などがあります。

また、実務の開発フェーズでは、毎回SDカードを書き換えるのは非効率です。そのため、U-Bootのネットワーク機能を利用し、TFTP(Trivial File Transfer Protocol)サーバからカーネルをダウンロードし、NFS(Network File System)経由でホストPC上のrootfsをマウントする「ネットワークブート」を構築することで、開発スピードの向上が期待できます。

組み込みソフトの世界 トップへ戻る