OS・実行環境

U-Boot

組み込みLinuxで定番のブートローダー。

概要

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
USBusb start; fatload usb 0:1 $kernel_addr zImage
DHCP + TFTPdhcp; 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 ProjectBuildrootでビルドされたイメージにも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}

よくある問題と対処法

  1. DDR初期化失敗: SPLのUARTよりも前に起動が止まる場合はDDR設定(タイミング・容量)を確認
  2. bootargs不一致: root=/dev/mmcblk0p2が実際のパーティション番号と合っているか確認
  3. DTBバージョン不一致: カーネルとDTBのバージョンが合っていないとドライバ初期化に失敗
  4. 環境変数のsaveenv失敗: フラッシュのCONFIG_ENV_OFFSETが正しく設定されているか確認

他技術との比較

U-Boot vs Barebox

項目U-BootBarebox
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上で動かすことができます。

関連用語

参考リンク