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

U-Bootの環境変数

U-Bootの挙動は「環境変数」で制御します。printenv で一覧や個別の値を確認し、setenv で変数を作成・変更・削除(値を省略すると削除)します。変更はそのままでは電源を切ると失われるため、saveenv で不揮発領域(環境ストレージ)に書き戻して永続化します。bootargs(カーネルへ渡す起動引数)、bootcmd(自動起動で実行するコマンド列)、serverip / ipaddr(ネットワーク設定)などが代表的な変数です。変数の中で ${name} の形で他の変数を参照でき、起動手順を部品化できます。

U-Bootの振る舞いは、プログラム本体を書き換えなくても「環境変数(environment variables)」を通じて細かく制御できます。環境変数は「名前 = 値」という形で保持される設定の集まりで、起動時にどのコマンドを実行するか、カーネルへどんな引数を渡すか、ネットワークのIPアドレスをいくつにするか、といった起動にまつわるあらゆる設定がここに格納されます。U-Bootを使った組込み開発の作業の多くは、突き詰めればこの環境変数を読み、書き換え、保存することに集約されます。本体のコードを変えずに挙動だけを調整できるため、同じU-Bootバイナリのまま、開発用と量産用で異なる起動の仕方をさせる、といった使い分けが可能になります。この環境変数の仕組み(boot-envvar)を押さえることが、U-Boot習熟の核心です。

値を確認する printenv

現在の環境変数を確認するコマンドが printenv です。引数なしで printenv とだけ打つと、設定されているすべての変数が「名前=値」の形で一覧表示されます。初めて触るボードでは、まずこの printenv で全体を眺め、どんな変数が定義されているかを把握するのが第一歩です。特定の変数だけ見たいときは、printenv bootcmd のように変数名を続ければ、その変数の値だけが表示されます。環境変数が多いボードでは一覧が長くなるので、目当ての変数が決まっているなら名前を指定したほうが見やすく確実です。なお、printenv は短縮形として pri とだけ打っても動くことが多く、U-Bootの多くのコマンドはこうした短縮入力に対応しています。

値を変更・削除する setenv

環境変数を作成・変更するコマンドが setenv です。書式は setenv 変数名 値 で、たとえば setenv bootdelay 3 とすれば、自動起動までの待ち時間を3秒に設定できます。すでに存在する変数に対して実行すれば値が上書きされ、存在しない名前を指定すれば新しい変数が作られます。値にスペースを含めたいときは、setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk0p2' のように、値全体をシングルクォートで囲みます。そして重要なのが削除の方法です。値を省略して setenv 変数名 とだけ打つと、その変数は削除されます。たとえば setenv myvar と打てば myvar が消える、という具合です。「値を書かない setenv は削除」という挙動は最初は意外に感じますが、覚えておくと不要な変数を整理するのに役立ちます。

変更を永続化する saveenv

ここで必ず理解しておくべき注意点があります。setenv で行った変更は、そのままでは電源を切ると失われるという点です。U-Bootは起動時に不揮発領域から環境変数を読み出し、RAM上に展開して動作します。setenv が書き換えるのはこのRAM上のコピーであって、不揮発領域の元データではありません。したがって変更を恒久的に残したいなら、saveenv コマンドを実行して、RAM上の現在の環境変数を不揮発領域(環境ストレージ。eMMCの特定領域やフラッシュなど)へ書き戻す必要があります。「setenv で変更 → saveenv で保存」が一組の手順だと覚えてください。逆に、一時的に試したいだけなら saveenv をあえて実行しないことで、再起動すれば元の設定に戻せます。これは、危険な変更を試すときの安全策にもなります。

代表的な変数と変数参照

実務でよく触る環境変数には、いくつかの定番があります。bootcmd は、自動起動時に実行されるコマンド列で、起動の心臓部です(次のトピックで詳述)。bootargs は、起動時にカーネルへ渡される引数で、ルートファイルシステムの場所やコンソール設定を指定します。ネットワーク関連では、ボード自身のIPアドレスを表す ipaddr、サーバのIPアドレスを表す serverip があり、TFTP起動(boot-tftp)の際にこれらを設定します。bootdelay は自動起動までの待ち秒数、loadaddr はイメージを読み込むメモリアドレスの既定値です。これらの名前と役割を知っておくと、printenv の出力から起動の仕組みを読み解けるようになります。

環境変数の値がどこに保存されるか、つまり環境ストレージの場所はボードによって異なります。eMMCやSDカードの特定のオフセット領域に置かれることもあれば、専用のSPI NORフラッシュや、NANDフラッシュの一区画が使われることもあります。U-Bootはビルド時の設定で「自分の環境変数をどこに保存するか」を知っており、saveenv はその場所へ書き込みます。ときに、不揮発領域に有効な環境がまだ無い(出荷直後や領域を消した直後)状態では、U-Bootはソースコードに埋め込まれた既定値(デフォルト環境)を使って起動します。「printenv の値を変えて saveenv したのに再起動で戻ってしまう」といった症状が出たら、環境ストレージへの書き込みが正しく行えているか、保存先の設定が実際のハードウェアと合っているかを疑うのが定石です。

U-Bootの環境変数は、値の中で他の変数を参照できる点も強力です。${変数名} という書き方で、別の変数の値を埋め込めます。たとえば setenv bootcmd 'tftpboot ${loadaddr} zImage; bootz ${loadaddr}' のように書けば、loadaddr の値が実行時に展開されます。これを使うと、共通のアドレスやファイル名を一か所の変数にまとめておき、複数のコマンドから参照する、という部品化ができます。アドレスを変えたいときはその変数を一つ書き換えるだけで、参照している全コマンドに反映されます。さらに run というコマンドを使えば、変数に書いておいたコマンド列をその場で実行でき、たとえば setenv netboot 'tftpboot ...; bootz ...' と定義しておいて run netboot と呼び出す、といった「自作コマンド」のような使い方も可能です。printenv・setenv・saveenv という三つの基本操作に、この変数参照を組み合わせることで、起動手順を柔軟かつ再利用しやすい形に組み立てられるようになります。

この項目に出てくる用語

環境変数(U-Boot)かんきょうへんすう
U-Bootの挙動を決める設定値。printenvで確認、setenvで変更、saveenvで永続化。
bootcmdぶーとこまんど
自動起動時にU-Bootが実行するコマンド列を入れた環境変数。

関連コマンド

printenvsetenvsaveenv

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