# 機能設計書 66-ブートローダ（loader）

## 概要

本ドキュメントは、FreeBSDのシステムブートローダ（loader）の機能設計を記述する。loaderはシステム起動時にカーネルとモジュールをロードし、ブートパラメータを設定してカーネルに制御を渡すプログラムである。EFI（UEFI）およびBIOS環境の両方に対応する。

### 本機能の処理概要

**業務上の目的・背景**：OSの起動プロセスにおいて、ファームウェア（BIOS/UEFI）とカーネルの間を橋渡しするブートローダは不可欠な存在である。FreeBSDのloaderは、カーネルの選択、ブート環境の切り替え、カーネルモジュールのプリロード、ブートパラメータの設定など、柔軟な起動制御を提供する。

**機能の利用シーン**：システム起動時に自動的に実行される。カーネルバージョンの選択、シングルユーザモードでの起動、カーネルモジュールの事前ロード、ブート環境（ZFS BE）の選択、ネットワークブート（kboot）などで利用される。

**主要な処理内容**：
1. ファームウェア（EFI/BIOS）からの制御受け取り
2. ファイルシステムの認識（UFS, ZFS, FAT等）
3. カーネル（/boot/kernel/kernel）のロード
4. カーネルモジュールのプリロード（/boot/kernel/*.ko）
5. loader.conf の読み込みとパラメータ設定
6. Luaスクリプトによる対話的ブートメニュー
7. ZFS Boot Environment の選択
8. カーネルへの制御移行

**関連システム・外部連携**：EFIファームウェア（EFI Boot Services/Runtime Services）またはBIOS INT 13hを通じてディスクにアクセスする。ZFSプール、UFS/FFSファイルシステムからカーネルをロードする。ACPIテーブルを検出してカーネルに渡す。

**権限による制御**：ブートローダはOS起動前に動作するため、権限管理の概念は適用されない。物理アクセスがあればブートパラメータを変更可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はテキストベースのブートメニューを提供するが、bsdinstall画面との直接関連はない |

## 機能種別

システム起動 / ブートローダ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| /boot/loader.conf | 設定ファイル | No | ブートパラメータ設定 | key=value形式 |
| /boot/loader.conf.local | 設定ファイル | No | ローカル追加設定 | key=value形式 |
| ユーザ入力 | キーボード | No | ブートメニューでの選択・コマンド入力 | loaderコマンド文法 |

### 入力データソース

- EFIシステムパーティション（ESP）またはMBRパーティション
- /boot/loader.conf: ブート設定
- /boot/defaults/loader.conf: デフォルト設定
- /boot/lua/: Luaスクリプト群

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ロード済みカーネル | ELFイメージ | メモリ上のカーネルイメージ |
| モジュール群 | バイナリ | プリロードされたカーネルモジュール |
| ブートパラメータ | 環境変数 | カーネルに渡される設定値 |

### 出力先

- 物理メモリ: カーネルイメージとモジュール
- カーネル起動パラメータ: 環境変数とメタデータ

## 処理フロー

### 処理シーケンス

```
1. ファームウェアからの起動
   └─ EFI: efi_main() / BIOS: ステージ1→ステージ2
2. libsa初期化
   └─ スタンドアロンライブラリの初期化、コンソール設定
3. ファイルシステム認識
   └─ ブートデバイスの検出、UFS/ZFS/FAT等の認識
4. loader.conf読み込み
   └─ デフォルト設定 → /boot/loader.conf → loader.conf.local
5. ブートメニュー表示
   └─ Lua スクリプトによるメニュー表示（タイムアウト付き）
6. カーネルロード
   └─ ELFカーネルイメージのメモリへのロード
7. モジュールプリロード
   └─ loader.confで指定されたモジュールのロード
8. カーネル起動
   └─ カーネルエントリポイントへのジャンプ
```

### フローチャート

```mermaid
flowchart TD
    A[ファームウェア] --> B{EFI or BIOS?}
    B -->|EFI| C[efi_main]
    B -->|BIOS| D[ステージ1→2]
    C --> E[libsa初期化]
    D --> E
    E --> F[ブートデバイス検出]
    F --> G[ファイルシステム認識]
    G --> H[loader.conf読み込み]
    H --> I{自動ブート?}
    I -->|Yes| J[タイムアウト待機]
    I -->|No| K[ブートメニュー表示]
    J -->|タイムアウト| L[カーネルロード]
    J -->|キー入力| K
    K --> L
    L --> M[モジュールプリロード]
    M --> N[カーネル起動]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-66-01 | 設定ファイル優先順序 | defaults/loader.conf → loader.conf → loader.conf.local の順で上書き | 常時 |
| BR-66-02 | 自動ブートタイムアウト | autoboot_delayで指定された秒数後に自動起動 | 対話モード時 |
| BR-66-03 | ZFS BE選択 | vfs.root.mountfromによりZFSブート環境を指定 | ZFS起動時 |
| BR-66-04 | モジュールプリロード | *_load="YES"のモジュールをカーネル起動前にロード | loader.conf設定時 |

### 計算ロジック

特になし。

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | カーネル読み込み失敗 | カーネルファイルが存在しない | 代替パスからのロード試行 |
| - | ファイルシステム認識失敗 | ブートデバイスが認識不能 | 対話モードでデバイス指定 |
| - | モジュールロード失敗 | モジュールファイルが存在しない | 警告出力、起動継続 |
| - | メモリ不足 | カーネル/モジュールがメモリに収まらない | エラー表示 |

### リトライ仕様

カーネルロード失敗時は対話モードに遷移し、ユーザによる手動操作を受け付ける。

## トランザクション仕様

トランザクション管理は不要。

## パフォーマンス要件

- ブート時間への影響を最小限にするため、必要なモジュールのみプリロード
- ZFSプール検索の効率化

## セキュリティ考慮事項

- ブートローダは物理アクセスで操作可能なため、シングルユーザモードへの移行制御が重要
- Secure Boot（UEFI）対応によるブートチェーン検証
- veriexec対応版（version.veriexec）によるカーネル/モジュールの署名検証

## 備考

- stand/ディレクトリ配下にアーキテクチャ別（amd64, arm64, i386, powerpc, riscv）のコードが存在
- Lua（旧Forth）スクリプトによるブートメニューのカスタマイズが可能
- kbootはLinux上でFreeBSDカーネルを起動するためのブートローダ

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | bootstrap.h | `stand/common/bootstrap.h`（推定） | ブートローダ共通インタフェース |
| 1-2 | loader_efi.h | `stand/efi/loader/loader_efi.h` | EFIローダ固有定義 |

**読解のコツ**: stand/配下はOS起動前環境で動作するため、通常のlibcは使用できない。stand/libsa/がスタンドアロンライブラリとして基本機能を提供する。

#### Step 2: EFIエントリポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | efi_main.c | `stand/efi/loader/efi_main.c` | EFI環境でのエントリポイント |
| 2-2 | main.c | `stand/efi/loader/main.c` | EFIローダメイン処理 |

**主要処理フロー**:
1. **EFI Boot Services初期化**
2. **ブートデバイス検出（ディスク、ネットワーク）**
3. **ファイルシステム認識（UFS/ZFS/FAT）**
4. **loader.conf読み込み**

#### Step 3: 共通ローダフレームワークを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | autoload.c | `stand/efi/loader/autoload.c` | モジュール自動ロード |
| 3-2 | conf.c | `stand/efi/loader/conf.c` | 設定ファイル処理 |
| 3-3 | bootinfo.c | `stand/efi/loader/bootinfo.c` | カーネルへのブート情報渡し |

#### Step 4: Luaスクリプトを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | lua/ | `stand/lua/` | Luaブートメニュースクリプト群 |
| 4-2 | liblua/ | `stand/liblua/` | 組み込みLuaライブラリ |

### プログラム呼び出し階層図

```
ファームウェア (EFI/BIOS)
    |
    +-- efi_main() [stand/efi/loader/efi_main.c]
    |       +-- main() [stand/efi/loader/main.c]
    |               +-- ブートデバイス検出
    |               +-- FS認識 (UFS/ZFS/FAT)
    |               +-- loader.conf読み込み
    |               +-- Luaブートメニュー [stand/lua/]
    |               +-- カーネルロード
    |               +-- モジュールプリロード
    |               +-- bootinfo設定
    |               +-- カーネルジャンプ
    |
    +-- libsa [stand/libsa/]
            +-- ファイルI/O
            +-- コンソールI/O
            +-- メモリ管理
```

### データフロー図

```
[入力]                        [処理]                       [出力]

ファームウェア ──────▶ efi_main() ──────────────▶ 初期化完了
ブートデバイス ──────▶ FS認識 ───────────────────▶ ファイルアクセス
/boot/loader.conf ──▶ 設定読み込み ──────────────▶ 環境変数設定
/boot/kernel/kernel ─▶ カーネルロード ────────────▶ メモリイメージ
/boot/kernel/*.ko ──▶ モジュールロード ──────────▶ メモリイメージ
                                                    |
                                            カーネルエントリ ──▶ カーネル起動
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| main.c | `stand/efi/loader/main.c` | ソース | EFIローダメイン |
| efi_main.c | `stand/efi/loader/efi_main.c` | ソース | EFIエントリポイント |
| autoload.c | `stand/efi/loader/autoload.c` | ソース | モジュール自動ロード |
| bootinfo.c | `stand/efi/loader/bootinfo.c` | ソース | ブート情報設定 |
| conf.c | `stand/efi/loader/conf.c` | ソース | 設定ファイル処理 |
| framebuffer.c | `stand/efi/loader/framebuffer.c` | ソース | フレームバッファ設定 |
| efizfs.h | `stand/efi/loader/efizfs.h` | ヘッダ | EFI ZFSブート定義 |
| lua/ | `stand/lua/` | スクリプト | Luaブートメニュー |
| libsa/ | `stand/libsa/` | ライブラリ | スタンドアロンライブラリ |
| defaults/ | `stand/defaults/` | 設定 | デフォルトloader.conf |
