🐧 Linux 総合学習プラットフォーム
ブートローダ U-Boot ・ 上級

U-Bootとは

U-Boot(Das U-Boot)は、組込みLinuxで広く使われるオープンソースの二次ブートローダです。多数のSoC・ボード・ストレージ・ネットワークに対応し、対話的なコンソールから環境変数の編集やメモリ操作、カーネルの起動までを行えます。シリアルコンソールに表示されるカウントダウン中にキーを押すとU-Bootプロンプト(=> など)に入り、自動起動を止めて手動操作に切り替えられます。開発時はTFTPやNFSと組み合わせてカーネルやルートファイルシステムを差し替え、量産時はストレージからの自動起動に切り替えるのが定石です。

組込みLinuxの二次ブートローダとして、最も広く使われているのがU-Boot(正式名称 Das U-Boot、ドイツ語で「潜水艦」の意)です。オープンソースで開発され、ARM・RISC-V・MIPS・PowerPCなど多様なCPUアーキテクチャに対応し、各SoCメーカーや基板ベンダが自社ボード向けの対応コードを上流に寄せているため、対応ボードの数は膨大です。eMMCやSDカード、NAND/NORフラッシュといったストレージ、さらにEthernet経由のネットワーク起動まで幅広く扱えるのが特徴で、「組込みLinuxを起動するなら、まずU-Bootを介する」というのが事実上の定番になっています。前のトピックで見た多段構成では、U-Bootは二次段(boot-secondstage)に位置し、SPLによってDRAM上へ読み込まれてから本領を発揮します。

対話コンソールに入る

U-Bootの最大の魅力は、シリアルコンソールから対話的に操作できることです。ボードに電源を入れてシリアル端末を開いていると、U-Bootが起動メッセージを表示したあと、「Hit any key to stop autoboot:」のようなメッセージとともに数秒のカウントダウンを始めます。このカウントダウンが終わるまでに何かキーを押すと、自動起動が中断され、=> や u-boot=> といったプロンプトが現れます。これがU-Bootのコマンドプロンプトで、ここから先は人間が一つずつコマンドを打って、ボードを思いどおりに操作できます。逆に、カウントダウン中に何も押さなければ、U-Bootは自動起動の手順(後述の bootcmd)に従ってそのままLinuxの起動へ進みます。この「待ってくれる数秒」が、開発者にとって手動介入の入り口になります。なお、シリアル端末側の通信速度(ボーレート、115200bps などが一般的)がU-Bootの設定と合っていないと、メッセージが文字化けして読めず、キーを押しても反応しないように見えます。コンソールに意味のある文字が出ているかどうかは、ボーレートが正しく合っている何よりの証拠になります。

できることの全体像

プロンプトに入ったあと、U-Bootでは大きく分けて三種類の操作ができます。第一に、環境変数の確認と編集です。printenv で現在の設定を一覧でき、setenv で値を変更します(詳しくは環境変数のトピックで扱います)。第二に、メモリやストレージの直接操作です。md(memory display)で任意のメモリアドレスの中身を16進ダンプで覗いたり、mw(memory write)で値を書き込んだり、フラッシュやeMMCからメモリへデータを読み込んだりできます。第三に、起動そのものの実行です。カーネルとデバイスツリーをメモリへ読み込み、boot や bootm といったコマンドでLinuxを起動します。これらを組み合わせることで、「どのイメージを、どこから、どうやって起動するか」を完全に手元でコントロールできます。

U-Bootには、起動に直接関わらない便利なコマンドも多数あります。たとえば help と打てば使えるコマンドの一覧が出て、help md のように個別コマンドの使い方も確認できます。version でU-Boot自身のバージョンを確認でき、不具合を調べるときに役立ちます。これらは小さなLinuxシェルのような操作感で、初めて触るボードでも help を起点に少しずつ機能を探っていけます。U-Boot自体が一種のミニOSのように、メモリ・ストレージ・ネットワークという基本資源を人間の手で扱える環境を提供している、と捉えると理解しやすいでしょう。

メモリを直接覗ける md コマンドは、地味ながら開発で非常に重宝します。たとえば、ストレージから読み込んだカーネルやデバイスツリーが本当に正しくメモリへ配置されたかを、md でそのアドレスをダンプして先頭の数バイト(イメージごとに決まった識別子=マジックナンバー)を目視で確かめられます。zImage やデバイスツリーには固有の先頭バイト列があるため、それが見えれば「少なくとも読み込みは成功している」と判断できます。逆に、そこが空(全部ゼロやランダムな値)であれば、読み込みコマンドの段階で失敗していると切り分けられます。このように、U-Bootは起動の各段階を人間の目で検証できる「窓」をいくつも備えており、ブラックボックスになりがちな起動処理を一歩ずつ可視化できるのが、現場で頼りにされる理由の一つです。

開発と量産での使い分け

U-Bootの真価は、開発フェーズと量産フェーズで使い方を切り替えられる点にあります。開発中は、カーネルやルートファイルシステムを一日に何度も作り直します。そのたびにストレージへ書き込み直すのは時間の無駄なので、U-BootのTFTP機能(boot-tftp)でネットワーク上のサーバからカーネルを直接メモリへ取り込み、ルートファイルシステムはNFSでネットワーク越しにマウントする、という構成がよく使われます。こうすれば、ビルドしたイメージをサーバに置いてボードを再起動するだけで、最新のカーネルで起動できます。コンソールから手作業でコマンドを打って、起動手順を一つずつ確かめながら詰めていけるのも、この段階ならではの使い方です。

一方、製品として出荷する量産フェーズでは、エンドユーザがシリアルコンソールを操作することはありません。電源を入れたら何もしなくてもLinuxが立ち上がる必要があります。そこで、確定した起動手順を環境変数 bootcmd に書き込み、saveenv で不揮発領域に保存して固定します。さらに、開発時には長く取っていたカウントダウン(bootdelay)を短く、あるいはゼロに設定して、無駄な待ち時間なく自動起動するよう仕上げます。つまり同じU-Bootでありながら、開発時は「対話的に試す道具」、量産時は「黙って確実にカーネルを起動する仕組み」として振る舞わせる——この柔軟さこそが、U-Bootが組込みの現場で長く支持されている理由です。次のトピックでは、この振る舞いを決める環境変数の仕組みを詳しく見ていきます。

この項目に出てくる用語

U-Bootゆーぶーと
組込みLinuxで広く使われるオープンソースの二次ブートローダ。
ブートローダぶーとろーだ
OS本体を起動する前に走り、カーネルを読み込んで制御を渡すプログラム。
環境変数(U-Boot)かんきょうへんすう
U-Bootの挙動を決める設定値。printenvで確認、setenvで変更、saveenvで永続化。

関連コマンド

printenvbootmd

▶ 学習アプリでこの続きを学ぶ・演習する