# 画面設計書 27-ファームウェアインストール画面

## 概要

本ドキュメントは、FreeBSD bsdinstallインストーラにおける「ファームウェアインストール画面」の画面設計書である。fwgetコマンドで検出されたハードウェアファームウェアパッケージをpkg経由でインストールするチェックリスト画面の仕様を定義する。

### 本画面の処理概要

本画面は、FreeBSDのインストールプロセスにおいて、システムのハードウェアに必要なファームウェアパッケージを検出し、インストールするための画面である。fwgetコマンドによりハードウェアを自動検出し、必要なファームウェアパッケージの一覧をチェックリストで表示する。

**業務上の目的・背景**：多くのハードウェア（特に無線LANアダプタやGPU）は、動作にファームウェアバイナリを必要とする。これらのファームウェアはライセンスの関係でFreeBSDの基本システムには含まれないため、pkgを通じて別途インストールする必要がある。本画面により、インストール時に必要なファームウェアを自動検出して一括インストールできる。

**画面へのアクセス方法**：autoスクリプト（455行目）から `bsdinstall firmware` として呼び出される。環境変数 `BSDINSTALL_SKIP_FIRMWARE` が設定されている場合は省略される。また、最終設定メニュー画面から「Firmware」を選択することで再度アクセスできる。ネットワーク接続が必要。

**主要な操作・処理内容**：
1. chroot環境内で `fwget -q -n` を実行し、必要なファームウェアパッケージを検出
2. 検出結果をチェックリストで表示（全てデフォルトON）
3. ユーザが選択したパッケージを `pkg install` でインストール
4. インストール結果の確認とエラーハンドリング

**画面遷移**：
- 遷移元：セキュリティ強化設定画面（No.26）、最終設定メニュー画面（Firmware選択時）
- 遷移先：ユーザ追加確認画面（No.28）

**権限による表示制御**：特になし。fwgetがファームウェアを検出しなかった場合、「No firmware to install, continuing...」メッセージを5秒間のpauseダイアログで表示して自動的に次へ進む。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 61 | devdデバイスイベント | 主機能 | fwgetによるハードウェアファームウェアパッケージ検出・pkg経由インストール |
| 55 | ネットワークデバイスドライバ | 補助機能 | ネットワーク・デバイスファームウェアパッケージの特定 |

## 画面種別

設定（チェックリスト選択）/ 情報表示（ファームウェア検出なし時）

## URL/ルーティング

シェルスクリプトベースのTUIアプリケーション。`bsdinstall firmware` コマンドにより起動される。

## 入出力項目

| 項目名 | 入出力 | 型 | デフォルト | 説明 |
|--------|--------|-----|----------|------|
| ファームウェアパッケージ一覧 | 入力 | チェックボックス（複数） | 全てON | fwgetで検出されたファームウェアパッケージ |

## 表示項目

| 項目名 | 表示位置 | 説明 |
|--------|----------|------|
| タイトル | ダイアログタイトル | "$OSNAME Firmware Installation" |
| バックタイトル | 画面上部 | "$OSNAME Installer" |
| プロンプトメッセージ | ダイアログ本文 | "This menu allows you to install firmware packages for your system" |
| ファームウェアチェックリスト | ダイアログ本文 | 検出されたファームウェアパッケージ一覧 |
| ファームウェアなしメッセージ | ダイアログ本文 | "No firmware to install, continuing..."（検出なし時） |
| インストール中メッセージ | インフォボックス | "Installing firmware. This may take a moment." |

## イベント仕様

### 1-OKボタン押下（ファームウェアあり時）

OKボタン押下時、以下の処理が実行される：
1. resolv.confをchroot環境にコピー（名前解決のため）
2. "Installing firmware. This may take a moment." インフォボックスを表示
3. 選択された各ファームウェアパッケージを1つずつ `ASSUME_ALWAYS_YES=YES chroot $BSDINSTALL_CHROOT pkg install -qy` でインストール
4. いずれかのインストールに失敗した場合、失敗パッケージ名をエラーダイアログに表示

### 2-Cancelボタン押下

Cancelボタン押下時、ファームウェアをインストールせずに画面を終了する。

### 3-ファームウェア未検出時

fwgetがファームウェアを検出しなかった場合：
1. "No firmware to install, continuing..." メッセージを5秒間のpauseダイアログで表示
2. 自動的に画面を終了

## データベース更新仕様

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

| 操作（イベント） | 対象 | 操作種別 | 概要 |
|----------------|------|---------|------|
| OKボタン押下 | $BSDINSTALL_CHROOT内のpkgデータベース | INSERT | ファームウェアパッケージのインストール |
| OKボタン押下 | $BSDINSTALL_CHROOT/etc/resolv.conf | UPDATE | 名前解決用にresolv.confをコピー |

### テーブル別更新項目詳細

#### pkgデータベース

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| INSERT | ファームウェアパッケージ | fwgetで検出されたパッケージ名 | pkg install -qy で実行 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| MSG-01 | 情報 | No firmware to install, continuing... | fwgetがファームウェアを検出しなかった場合 |
| MSG-02 | 情報 | Installing firmware. This may take a moment. | ファームウェアインストール中 |
| MSG-03 | エラー | Error fetching firmware file(s) {パッケージ名} | pkg installが失敗した場合 |

## 例外処理

- **fwgetコマンドが空結果**：5秒間のpauseダイアログを表示して自動終了
- **pkg installの失敗**：失敗したパッケージ名を蓄積し、全パッケージ処理後にエラーダイアログを表示。5秒間のスリープ後にエラーメッセージを表示し、exit 1で終了
- **ネットワーク未接続**：pkg installがパッケージをダウンロードできずエラーとなる
- **resolv.confの不在**：DNS解決ができずpkg installが失敗する可能性がある
- **BSDINSTALL_SKIP_FIRMWARE設定時**：firmwareスクリプトが呼ばれず、本画面は表示されない

## 備考

- fwgetの `-q` オプションはquietモード、`-n` オプションはdry-run（実際にインストールせずパッケージ名のみ出力）
- ファームウェアパッケージは1つずつインストールされる。これは、一部のパッケージが利用不可の場合に他のパッケージのインストールを継続するため（121-122行目のコメント参照）
- ASSUME_ALWAYS_YES=YES により、pkg installの確認プロンプトを抑制している
- bsdconfig/dialog.subr、mustberoot.subr、packages/packages.subr の各ライブラリを読み込んでいる
- ネットワーク接続が前提条件であり、オフライン環境ではファームウェアインストールは不可

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | firmware | `usr.sbin/bsdinstall/scripts/firmware` | 19-23行目：メッセージ定数の定義 |
| 1-2 | firmware | `usr.sbin/bsdinstall/scripts/firmware` | 34行目：fwgetによるファームウェアリスト取得 |

**読解のコツ**: このスクリプトはbsdconfig/dialog.subrを使用しており、$DIALOGや f_dialog_checklist_size 等のbsdconfig関数を多用する。bsddialogを直接呼ぶ他のスクリプトとはダイアログ呼び出し方式が異なる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | auto | `usr.sbin/bsdinstall/scripts/auto` | 455行目：`bsdinstall firmware` の呼び出し条件 |
| 2-2 | firmware | `usr.sbin/bsdinstall/scripts/firmware` | 97-108行目：メイン処理の開始 |

**主要処理フロー**:
1. **11-17行目**: bsdconfigライブラリの読み込み
2. **25-95行目**: dialog_menu_main関数の定義
3. **97-99行目**: ダイアログタイトルとバックタイトルの設定
4. **102行目**: dialog_menu_main関数の呼び出し
5. **103行目**: f_dialog_menutag_fetchで選択結果取得
6. **106-108行目**: 選択結果が空の場合は終了
7. **113行目**: resolv.confのコピー
8. **115-116行目**: インストール中インフォボックス表示
9. **120-127行目**: 各パッケージのインストールループ
10. **128-135行目**: エラーハンドリング

#### Step 3: dialog_menu_main関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | firmware | `usr.sbin/bsdinstall/scripts/firmware` | 25-95行目：dialog_menu_main関数 |

**主要処理フロー**:
- **34行目**: `chroot $BSDINSTALL_CHROOT fwget -q -n` でファームウェアリスト取得
- **35-57行目**: ファームウェアなし時のpauseダイアログ表示
- **58-94行目**: ファームウェアあり時のチェックリスト構築と表示

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

```
auto (455行目: bsdinstall firmware)
    |
    +-- firmware
            |
            +-- common.subr (共通関数読み込み)
            +-- dialog.subr (ダイアログライブラリ)
            +-- mustberoot.subr (root権限確認)
            +-- packages.subr (パッケージ管理)
            |
            +-- dialog_menu_main()
            |       |
            |       +-- chroot fwget -q -n (ファームウェア検出)
            |       |
            |       +-- [検出なし] $DIALOG --pause (5秒タイムアウト)
            |       +-- [検出あり] $DIALOG --checklist (チェックリスト表示)
            |
            +-- resolv.conf コピー
            |
            +-- $DIALOG --infobox (インストール中表示)
            |
            +-- pkg install ループ
            |       +-- ASSUME_ALWAYS_YES=YES chroot pkg install -qy
            |
            +-- [失敗時] bsddialog --msgbox (エラー表示)
```

### データフロー図

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

ハードウェア情報 ──────────> chroot fwget -q -n ──────────> fwlist変数
                                     |                      (パッケージ名リスト)
                                     v
                              dialog_menu_main()
                                     |
                                     v
ユーザ選択 ──────────────> $DIALOG --checklist ──────────> selected変数
                                     |
                                     v
$BSDINSTALL_TMPETC/          resolv.confコピー
  resolv.conf ──────────> $BSDINSTALL_CHROOT/etc/resolv.conf
                                     |
                                     v
                              pkg install ループ ──────────> pkgデータベース更新
                                     |
                                     +-- [失敗時] pkg_install_fail変数
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| firmware | `usr.sbin/bsdinstall/scripts/firmware` | ソース | ファームウェアインストール画面のメインスクリプト |
| auto | `usr.sbin/bsdinstall/scripts/auto` | ソース | インストーラメインフロー（firmware呼び出し元） |
| finalconfig | `usr.sbin/bsdinstall/scripts/finalconfig` | ソース | 最終設定メニュー（firmware再呼び出し元） |
| common.subr | `/usr/share/bsdconfig/common.subr` | ライブラリ | bsdconfig共通関数ライブラリ |
| dialog.subr | `/usr/share/bsdconfig/dialog.subr` | ライブラリ | bsddialogラッパー関数ライブラリ |
| mustberoot.subr | `/usr/share/bsdconfig/mustberoot.subr` | ライブラリ | root権限確認ライブラリ |
| packages.subr | `/usr/share/bsdconfig/packages/packages.subr` | ライブラリ | パッケージ管理ライブラリ |
| fwget | `/usr/sbin/fwget` | コマンド | ハードウェアファームウェア検出コマンド |
| resolv.conf | `$BSDINSTALL_TMPETC/resolv.conf` | 設定 | DNS設定ファイル（コピー元） |
