概要
U-Boot(Das U-Boot:The Universal Bootloader)は、組み込みLinuxシステムで最も広く使われているオープンソースのブートローダーです。ARM・MIPS・PowerPC・RISC-V・x86など多数のアーキテクチャに対応し、Raspberry Pi・BeagleBone・NVIDIA Jetson・産業用SoCなど数千のボードをサポートしています。
U-Bootの役割は、電源投入後にハードウェアを初期化し、ストレージ(eMMC・SDカード・NANDフラッシュ・NORフラッシュ・ネットワーク)からLinuxカーネル・デバイスツリー・initramfsをRAMにロードして実行することです。また、インタラクティブなシェルを持ち、スクリプト実行・ネットワーク経由のファームウェア更新・セキュアブート検証など多様な機能を提供します。
歴史・背景
U-BootはもともとSMon(Diagnostics Monitor)というPowerPC向けのブートモニタから始まりました。1999年頃にWolfgang Dendorfer氏が8xxFADS向けPortを開発し、それが「PPCBoot」として公開されました。2002年にARMやMIPSへの対応が追加され、「U-Boot」にリネームされました。
DENX Software Engineering(ドイツ)がメインの開発・メンテナンスを担い、世界中の組み込みエンジニアがボードポートを貢献しています。Linuxカーネルと同様にGIT管理・メーリングリストベースのパッチレビューで開発が進められています。
2013年頃から、従来のMakefileベース設定に加えてデバイスツリーのサポートが強化されました。2017年以降は、デバイスモデル(Driver Model / DM)へのリファクタリングが進み、ドライバ構造がLinuxカーネルに近い設計になってきています。セキュアブート・fitイメージ署名検証・UEFI準拠なども近年の主要な機能追加です。
技術仕様
サポート起動メディア
U-Bootは多様なメディアからカーネルをロードできます:
| メディア | コマンド例 |
|---|---|
| SDカード / eMMC(FAT) | fatload mmc 0:1 $kernel_addr zImage |
| SDカード / eMMC(ext4) | ext4load mmc 0:2 $kernel_addr /boot/Image |
| NANDフラッシュ | nand read $kernel_addr 0x100000 0x500000 |
| NORフラッシュ | cp.b 0x01000000 $kernel_addr 0x400000 |
| TFTP(ネットワーク) | tftpboot $kernel_addr zImage |
| USB | usb start; fatload usb 0:1 $kernel_addr zImage |
| DHCP + TFTP | dhcp; tftp $kernel_addr zImage |
U-Bootシェルコマンド(主要なもの)
# ヘルプ
help
help mmc # コマンドの詳細ヘルプ
# 環境変数
printenv # 環境変数一覧表示
setenv bootcmd "fatload mmc 0:1 ${kernel_addr_r} Image && booti ..."
saveenv # 環境変数をストレージに保存
# メモリ操作
md 0x80000000 0x10 # メモリダンプ(0x80000000から16ワード)
mm 0x80000100 # メモリ編集
mw 0x80000000 0 0x100 # メモリゼロクリア
# ストレージ操作
mmc list # MMCデバイス一覧
mmc dev 0 # MMCデバイス0を選択
mmc info # デバイス情報
fatls mmc 0:1 # FATパーティションのファイル一覧
ext4ls mmc 0:2 /boot # ext4パーティション内表示
# ネットワーク
dhcp # DHCPでIPアドレス取得
ping 192.168.1.1 # pingテスト
tftpboot 0x80000000 zImage # TFTP転送
# ブート
bootm # 従来のuImageブート
bootz 0x80000000 - 0x83000000 # zImage + DTBでブート(ARMv7)
booti 0x80200000 - 0x87000000 # Image + DTBでブート(ARM64)
# FIT Image(署名付きイメージ)
bootm 0x80000000 # FITイメージをロードして署名検証後にブート
環境変数(bootcmd / bootargs)
U-Bootのブート動作は主に2つの環境変数で制御されます:
# bootargs: Linuxカーネルに渡すコマンドライン引数
setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait rw"
# bootcmd: 自動ブート時に実行するコマンド
setenv bootcmd "fatload mmc 0:1 ${kernel_addr_r} Image; \
fatload mmc 0:1 ${fdt_addr_r} myboard.dtb; \
booti ${kernel_addr_r} - ${fdt_addr_r}"
# saveenvで保存(フラッシュのenv領域に書き込み)
saveenv
FIT Image(Flattened Image Tree)
U-Bootは複数のコンポーネント(カーネル・DTB・initramfs)を1つのファイルにまとめた「FIT Image」をサポートします。署名検証にも対応しており、セキュアブートの実装に使われます:
# image.its(FIT Image Source記述ファイル)
/dts-v1/;
/ {
description = "Kernel+DTB+Initrd Image";
images {
kernel-1 {
description = "Linux kernel";
data = /incbin/("Image");
type = "kernel";
arch = "arm64";
os = "linux";
compression = "none";
load = <0x80080000>;
entry = <0x80080000>;
hash-1 { algo = "sha256"; };
};
fdt-1 {
description = "Device Tree";
data = /incbin/("myboard.dtb");
type = "flat_dt";
arch = "arm64";
compression = "none";
hash-1 { algo = "sha256"; };
};
};
configurations {
default = "conf-1";
conf-1 {
kernel = "kernel-1";
fdt = "fdt-1";
};
};
};
動作原理
SPL(Secondary Program Loader)
SoCのBootROMが読み込めるデータサイズには制限があります(多くのSoCで16KB〜256KB)。そのため、U-Boot本体の前に「SPL(Secondary Program Loader)」と呼ばれる小型のブートコードが動作します:
BootROM → SPL(DDRとU-Boot本体の初期化)→ U-Boot本体
SPLはDDR SDRAMを初期化し、U-Boot本体(数百KBになることも)をDDRにロードして実行を引き継ぎます。
ボード初期化シーケンス(U-Boot内部)
/* U-Boot ボード初期化の主な流れ */
board_init_f() // アーリー初期化(UARTだけ動く状態)
→ relocate // U-Boot自体をRAMの適切な場所にコピー
board_init_r() // フル初期化
→ board_init() // ボード固有初期化
→ mmc_init() // ストレージ初期化
→ net_init() // ネットワーク初期化
→ console_init()// コンソール初期化
→ run_main_loop()
→ autoboot_command() // bootdelay秒後にbootcmdを自動実行
// または bootdelay中にキー入力でインタラクティブシェルへ
デバイスツリーとの連携
U-BootはLinuxカーネルと同じ形式のDTB(Device Tree Blob)を使ってハードウェアを認識します。起動時にfdt_addr環境変数で指定したアドレスにDTBをロードし、カーネルに渡します:
# DTBを指定してブート(ARM64の例)
fatload mmc 0:1 ${fdt_addr_r} raspberrypi/bcm2711-rpi-4-b.dtb
booti ${kernel_addr_r} - ${fdt_addr_r}
用途・ユースケース
組み込みLinux機器全般
Raspberry Pi・NVIDIA Jetson・産業用SBC(BeagleBone・Variscite・PHYTEC等)など、Linuxが動く組み込み機器のほぼ全てでU-Bootが使われています。Yocto Project・BuildrootでビルドされたイメージにもU-Bootが含まれます。
ネットワークブート(PXEブート)
TFTP・DHCP経由でネットワークからカーネルをロードする「PXEブート」に対応しており、量産時のファームウェア書き込みや開発時のデバッグブートに使われます。
ファームウェア更新ツール
量産工程では、JTAGでU-Bootを書き込んだ後、U-BoolのTFTP転送機能で各パーティションにファームウェアを書き込む手順が一般的です。
セキュアブート実装
U-Bootのfit-image署名検証とHAB(High Assurance Boot、NXP)・Secure Boot(Xilinx)などSoC固有のセキュアブート機能を組み合わせて、改ざん防止を実装します。
実装・開発のポイント
ボードポートの作成
新しいボードのU-Bootサポートはboard/<vendor>/<boardname>/ディレクトリに配置します:
board/mycompany/myboard/
├── Kconfig
├── MAINTAINERS
├── Makefile
├── myboard.c # ボード固有初期化
└── myboard.h # ボード定義
include/configs/myboard.h # ボード設定(アドレス・ペリフェラル設定)
configs/myboard_defconfig # デフォルト設定
U-Bootのビルドとデバッグ
# ビルド(Raspberry Pi 4、64bit)
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64
make rpi_4_defconfig
make -j$(nproc)
# 生成物
ls u-boot.bin u-boot.img u-boot-dtb.img
# TFTPを使った開発ブート(U-Bootシェルから)
u-boot> setenv serverip 192.168.1.100
u-boot> tftpboot ${kernel_addr_r} Image
u-boot> tftpboot ${fdt_addr_r} myboard.dtb
u-boot> booti ${kernel_addr_r} - ${fdt_addr_r}
よくある問題と対処法
- DDR初期化失敗: SPLのUARTよりも前に起動が止まる場合はDDR設定(タイミング・容量)を確認
- bootargs不一致:
root=/dev/mmcblk0p2が実際のパーティション番号と合っているか確認 - DTBバージョン不一致: カーネルとDTBのバージョンが合っていないとドライバ初期化に失敗
- 環境変数のsaveenv失敗: フラッシュの
CONFIG_ENV_OFFSETが正しく設定されているか確認
他技術との比較
U-Boot vs Barebox
| 項目 | U-Boot | Barebox |
|---|---|---|
| SoCサポート | 非常に広い(数千ボード) | 主要SoC中心 |
| 設計 | 歴史的な設計(リファクタリング進行中) | よりLinuxライクな現代的設計 |
| デバイスモデル | DM(移行中) | 完全DM採用 |
| ドキュメント | 豊富 | 限定的 |
| 採用例 | 圧倒的多数 | 一部のドイツ系組み込みベンダー |
U-Boot vs UEFI
UEFI(Unified Extensible Firmware Interface)はx86系PCで標準的なブートローダーフレームワークです。U-BootもUEFI準拠のAPIをサポートするようになっており(bootefiコマンド)、ARM64の一部機器ではUEFIをU-Boot上で動かすことができます。