概要
ブートローダー(Bootloader)は、組み込み機器・PCなどのコンピュータシステムで、電源投入後に最初に実行されるプログラムです。ハードウェアの基本的な初期化を行い、OSやメインプログラムをメモリにロードして実行を開始させる役割を担います。
組み込みLinuxシステムでは、BootROM(SoC内蔵の変更不可なROM)→一次ブートローダー(SPL/ATF)→U-Boot→Linuxカーネルというように、複数段階で起動処理が進みます。マイコン向けのベアメタル・RTOSシステムでも、最小限のブートローダー(スタートアップコード)が必ず存在します。
ブートローダーはシステムの「信頼の起点(Root of Trust)」であり、セキュアブートの実装やOTA(Over-The-Air)更新処理でも中心的な役割を果たします。
歴史・背景
PC向けブートローダーの歴史は1980年代のBIOS(Basic Input/Output System)から始まります。BIOSは電源投入時にCPUが実行するファームウェアで、デバイス初期化とOSブートを担いました。2000年代にはより高機能なUEFI(Unified Extensible Firmware Interface)に移行しています。
組み込みLinux向けのブートローダーとして最も普及したのはU-Boot(Das U-Boot)で、2000年代初頭から多くのSBC・組み込みSoCで採用されました。
マイコン向けでは、NordicのnRFシリーズのBootloader、STM32のシステムブートローダー(製造時フラッシュ書き込み用)など、各メーカーがマイコン固有のブートローダーを提供しています。DFU(Device Firmware Upgrade)やBluetooth OTAブートローダーは組み込みIoT機器で広く使われています。
ARMv8-A以降では、ARM Trusted Firmware(ATF / TF-A)が信頼境界を管理するEL3(Exception Level 3)のブートコードとして標準化され、セキュリティ強化されたブート手順が整備されています。
技術仕様
組み込みLinuxの多段ブートシーケンス
現代のARMベース組み込みLinuxでは、以下の多段構成が一般的です:
電源投入(Power-On Reset)
↓
【Stage 0】BootROM(SoC内蔵・変更不可)
- CPUコアの最低限初期化
- 起動デバイスの選択(SD/eMMC/NAND/NOR/USB等)
- 次段ブートローダーの読み込み・実行
↓
【Stage 1】一次ブートローダー(SPL / TF-A BL2)
- DDR SDRAM初期化(最重要:メインRAMの初期化)
- 次段ブートローダーをRAMへロード
↓
【Stage 2】U-Boot / TF-A BL31
- 全ペリフェラル初期化
- コンソール・ネットワーク初期化
- Linuxカーネル・DTBをRAMへロード
- セキュアブート(署名検証)
↓
【Stage 3】Linuxカーネル(+initramfs)
- カーネル本体の展開・実行
- デバイスドライバ初期化
↓
【Stage 4】ユーザースペース init(systemd等)
MCUブートシーケンス(Cortex-M)
マイコン(ARM Cortex-M)では起動がシンプルです:
電源投入
↓
Cortex-Mコア:フラッシュ先頭(0x08000000)を読む
↓
ベクタテーブル[0]:スタックポインタを設定
ベクタテーブル[1]:Reset_Handlerアドレスへジャンプ
↓
Reset_Handler(スタートアップコード)
- .data セクション初期化(ROM→RAM コピー)
- .bss セクション ゼロクリア
- SystemInit()
↓
main()
MCU向け応用ブートローダー(DFU・OTA対応)
組み込みIoT機器では、フィールドでのファームウェア更新のため専用ブートローダーを実装します:
【フラッシュレイアウト例(STM32F4)】
0x08000000 - 0x0800FFFF: Bootloader(64KB)
0x08010000 - 0x0807FFFF: Application(448KB)
0x08080000 - 0x080FFFFF: Update slot(512KB)
【起動フロー】
1. ブートローダー起動
2. 更新フラグを確認
3. フラグあり:Updateスロットの署名を検証
4. 検証OK:ApplicationスロットへUpdateスロットをコピー
5. Applicationを起動
ブートローダーの選択
| ブートローダー | 対象 | 用途 |
|---|---|---|
| U-Boot | ARM/MIPS等の組み込みSoC | 組み込みLinuxのデファクトスタンダード |
| Barebox | ARMなど | U-Bootより近代的な設計 |
| GRUB | x86系PC | デスクトップLinux・サーバー |
| UEFI | x86 / ARM64 | 高性能機器・UEFI準拠 |
| MCUboot | ARM Cortex-M | IoT MCU向け安全ブートローダー |
| nRF Bootloader | nRFシリーズ | Nordic BLE OTA専用 |
| STM32 Bootloader | STM32 | ST製マイコン組み込み版 |
動作原理
DDR初期化の重要性
組み込みLinux向けブートローダーの最重要処理の1つはDDR SDRAM(メインRAM)の初期化です。SoCのBootROM実行時点では外付けDDRが使えず、SoC内部のSRAM(数十〜数百KB)しか使えません。SPLがDDRコントローラを初期化することで、初めてLinuxカーネルをメモリにロードできます:
/* U-Boot SPL のDDR初期化(擬似コード) */
void board_init_f(ulong dummy) {
/* UART初期化 */
preloader_console_init();
/* DDR初期化 */
ddr_init(); /* SPDロード・タイミング設定・キャリブレーション */
/* DDRが使えるようになったのでU-Boot本体をロード */
board_init_r(NULL, CONFIG_SYS_TEXT_BASE);
}
セキュアブートの仕組み
セキュアブートでは、各ステージのブートローダーが次のステージの署名を検証します:
BootROM(ハード焼き付けの公開鍵でSPLを検証)
↓ 署名検証OK
SPL(ATF BL1で検証、またはBootROMから委譲)
↓ 署名検証OK
U-Boot(BL2/BL3で検証)
↓ 署名検証OK
Linuxカーネル(U-Bootのfitイメージ署名検証)
A/Bパーティション(アップデートレジリエンス)
OTA更新の信頼性を高めるため、A/Bパーティション方式が使われます:
パーティション構成:
Boot A | Boot B | System A | System B
更新フロー:
1. 現在Aで動作中
2. OTAでBに新バージョンを書き込み
3. ブートローダーのスロット設定をBに変更
4. 再起動→Bで起動
5. 起動成功確認後、Bをアクティブスロットとして確定
6. 次回OTA更新はAスロットに上書き
用途・ユースケース
組み込みLinux機器
産業用ゲートウェイ・スマートホームハブ・カーナビなど、Linuxが動く組み込み機器では必ずブートローダーが存在します。U-Bootが最もよく使われ、デバイスツリーのロードと検証を担います。
IoT機器のOTA更新
スマートスピーカー・工業センサー・スマートメーターなどのIoT機器では、フィールドでのファームウェア更新が不可欠です。MCUbootや独自ブートローダーがOTAの信頼性・セキュリティを担保します。
セキュア製品
医療機器・決済端末・産業制御機器では、改ざんを防ぐためのセキュアブートが法規制や認証で要求されます。ブートローダーが署名検証の起点として機能します。
工場でのファームウェア書き込み
量産工程では、JTAGまたはUART経由でブートローダーを使ってファームウェアを書き込みます。ST製マイコンの内蔵ROMブートローダー(UART/USB DFU対応)はよく利用されます。
実装・開発のポイント
U-Bootのビルド(Raspberry Pi 4例)
# クロスコンパイル環境
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64
# ビルド
git clone https://source.denx.de/u-boot/u-boot.git
cd u-boot
make rpi_4_defconfig
make -j$(nproc)
# 生成物
# u-boot.bin → SDカードのbootパーティションへ配置
MCUbootによるMCU向けセキュアブート
/* MCUboot対応アプリの先頭に配置するイメージヘッダー */
/* MCUbootが署名を検証してからアプリを起動する */
BOOT_IMAGE_MAGIC = 0x96f3b83d; /* マジックナンバー */
/* 署名付きイメージ生成(imgtoolを使用) */
// imgtool sign --key signing-key.pem --header-size 0x200 \
// --align 4 --version 1.0.0 --slot-size 0x60000 \
// app.bin app-signed.bin
ブートローダーのデバッグ
ブートローダーのデバッグは困難を伴います(OSなしの最初期フェーズのため)。主な手法:
- UARTデバッグ出力: U-Bootはシリアルコンソールを初期化後にログ出力
- JTAG: JTAGデバッガで最初の命令からステップ実行
- LEDトグル: DDR初期化等の到達確認に使用
- U-Boot nand/mmc コマンド: インタラクティブシェルでデバイス操作を確認
他技術との比較
U-Boot vs Barebox
Bareboxは2009年頃にU-Bootから派生したブートローダーで、Linuxカーネルに近い設計(デバイスツリー・デバイスモデル・仮想ファイルシステム)を持ちます。U-Bootの方が対応SoCが圧倒的に多く、産業界での採用実績も豊富です。
MCUboot vs 独自ブートローダー
MCUbootはZephyr・Mbed OS・nRF Connectと統合された標準的なMCU向けセキュアブートローダーです。独自実装より検証済みのセキュリティコードを使えるため、IoT機器での採用が増えています。署名鍵管理・イメージヘッダー形式は標準化されており、OTAツールとの連携も容易です。