# 機能設計書 78-電源管理

## 概要

本ドキュメントは、FreeBSDのACPI電源管理およびAPM対応機能の設計について記述する。acpiconf(8)によるACPI電源状態の制御、apm(8)によるAPM BIOSの電源管理情報取得・制御、apmd(8)によるAPMイベントの自動応答デーモンを提供する。

### 本機能の処理概要

**業務上の目的・背景**：ラップトップやサーバにおいて、バッテリー状態の監視、サスペンド/レジューム、電源状態の制御は重要なシステム管理機能である。ACPIおよびAPM BIOSインタフェースを通じて、ハードウェアの電源管理機能をユーザ空間から制御可能にする。

**機能の利用シーン**：バッテリー残量の確認（apm -l）、システムのスリープ/サスペンド（acpiconf -s）、APMイベントに基づく自動サスペンド（apmd）、電力消費の最適化（powerd）。

**主要な処理内容**：
1. apm(8): APM BIOSを通じたバッテリー情報取得、サスペンド/スタンバイ制御、APMの有効/無効切替
2. apmd(8): APMイベント（バッテリー低下、電源ボタン押下等）の監視と自動応答（設定ファイルに基づくアクション実行）
3. acpiconf(8): ACPIベースのスリープ状態（S1-S5）制御、バッテリー情報取得、ACPIテーブル操作
4. acpidump(8): ACPIテーブルのダンプ・解析

**関連システム・外部連携**：/dev/apmデバイス（APM BIOS）、/dev/acpi（ACPIサブシステム）、machine/apm_bios.h（APM BIOS ioctl定義）、powerd(8)（CPU周波数の動的制御）。

**権限による制御**：apm(8)の状態参照は一般ユーザでも可能だが、サスペンド/スタンバイ等の制御操作にはroot権限が必要。apmd(8)はroot権限で動作するデーモン。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | サービス選択画面 | 補助機能 | powerdサービスの起動設定 |

## 機能種別

デバイス制御 / システム管理

## 入力仕様

### 入力パラメータ（apm）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -a | フラグ | No | AC電源状態の表示 | なし |
| -b | フラグ | No | バッテリー状態の表示 | なし |
| -l | フラグ | No | バッテリー残量パーセントの表示 | なし |
| -s | フラグ | No | サスペンド実行 | root権限必要 |
| -t | フラグ | No | バッテリー残り時間の表示 | なし |
| -z | フラグ | No | スタンバイ実行 | root権限必要 |
| -Z | フラグ | No | スタンバイ実行（別方式） | root権限必要 |
| -d enable | 文字列 | No | ディスプレイ制御の有効/無効 | true/false/0/1 |
| -e enable | 文字列 | No | APMの有効/無効 | true/false/0/1 |
| -h enable | 文字列 | No | HLT命令での省電力の有効/無効 | true/false/0/1 |
| -r delta | 整数 | No | レジューム後の時計補正（秒） | 整数値 |

### 入力パラメータ（apmd）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| 設定ファイル | ファイル | No | APMイベントに対するアクション定義 | apmd.conf形式 |

### 入力データソース

- /dev/apm（APM BIOSデバイス）
- /dev/acpi（ACPIデバイス）
- apmd.conf（APMイベント応答設定ファイル）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| バッテリー残量 | 整数 | パーセント表示（0-100） |
| AC電源状態 | 文字列 | on-line / off-line / backup |
| バッテリー状態 | 文字列 | high / low / critical / charging |
| 残り時間 | 整数 | バッテリー残り時間（分） |

### 出力先

- 標準出力（apmコマンドの情報表示）
- syslog（apmdのイベントログ）

## 処理フロー

### 処理シーケンス

```
apm:
1. デバイスオープン
   └─ /dev/apmを開く
2. ioctl発行
   └─ APM BIOS ioctlでバッテリー/電源情報取得
3. 情報表示
   └─ 取得した情報を整形して標準出力に表示
4. 制御操作（オプション指定時）
   └─ サスペンド/スタンバイ等のioctlを発行

apmd:
1. 初期化
   └─ 設定ファイル読み込み、デーモン化
2. イベント監視ループ
   └─ /dev/apmからAPMイベントを読み取り
3. イベント処理
   └─ 設定ファイルに基づくアクション実行
```

### フローチャート

```mermaid
flowchart TD
    A[apm起動] --> B[/dev/apmオープン]
    B --> C{オプション判定}
    C -->|情報取得| D[ioctl APMIO_GETINFO]
    C -->|サスペンド| E[ioctl APMIO_SUSPEND]
    C -->|スタンバイ| F[ioctl APMIO_STANDBY]
    C -->|APM有効/無効| G[ioctl APMIO_ENABLE/DISABLE]
    D --> H[情報表示]
    E --> I[サスペンド実行]
    F --> J[スタンバイ実行]
    G --> K[設定変更]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-78-01 | APM BIOS互換性 | APM BIOSが利用可能な場合のみapm/apmdが動作する | 常時 |
| BR-78-02 | APM_UNKNOWN値 | バッテリー情報が不明の場合は255（APM_UNKNOWN）が返される | バッテリー情報取得時 |
| BR-78-03 | is_true関数 | enable/disable引数はtrue/false/yes/no/enable/disable/0/1を受け付ける | -d/-e/-hオプション |
| BR-78-04 | CMOS時計 | レジューム後の時計補正はCMOS時計がWall TimeかUTCかで挙動が異なる | -rオプション |
| BR-78-05 | ACPIスリープ状態 | S1(Power On Suspend), S3(Suspend to RAM), S4(Hibernate), S5(Soft Off)をサポート | acpiconf使用時 |

### 計算ロジック

- BCD変換: int2bcd/bcd2int関数でBCD形式とint形式の相互変換（apm.c 80-93, 96-100行目）
- レジューム時計補正: CMOS時計からdelta秒を加減算

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベースは使用しない |

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | デバイスオープンエラー | /dev/apmが存在しない（APM非対応） | エラーメッセージ出力 |
| 1 | ioctlエラー | APM BIOSエラー | warn/errでエラーメッセージ出力 |
| 1 | 引数エラー | 無効なboolean引数 | "invalid boolean argument"警告 |

### リトライ仕様

リトライは行わない。

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

該当なし。

## パフォーマンス要件

特になし。apmコマンドはワンショット実行、apmdはイベント駆動。

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

- サスペンド/スタンバイはroot権限のみ実行可能（/dev/apmのパーミッション制御）
- apmd.confの設定によりイベント発生時に任意のコマンドが実行されるため、設定ファイルの保護が重要

## 備考

- APMは旧式のBIOSベース電源管理で、現代のシステムではACPIが主流
- FreeBSDではpowerd(8)がACPIベースのCPU周波数制御を担当
- acpiconf/acpidumpはACPI関連の別ディレクトリ（usr.sbin/acpi/）に配置

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | apm_bios.h | `sys/i386/include/apm_bios.h` (or machine/) | apm_info構造体（APM情報）、APM ioctl定義（APMIO_GETINFO等）を理解する |

**読解のコツ**: APM BIOSインタフェースはi386/amd64固有。machine/apm_bios.hはアーキテクチャ依存のヘッダ。APMERR(a)マクロはAPMエラーコードの上位バイトを抽出する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | apm.c | `usr.sbin/apm/apm.c` | APMDEVマクロ（/dev/apm）、is_true関数（boolean引数パーサ）、int2bcd/bcd2int関数（BCD変換）を理解する |

**主要処理フロー**:
1. **31行目**: APMDEV = "/dev/apm"
2. **33行目**: APM_UNKNOWN = 255
3. **39行目**: cmos_wall変数（CMOS時計がWall TimeかUTCか）
4. **54-77行目**: is_true関数（文字列boolean解析: true/false/yes/no/enable/disable/0/1）
5. **79-93行目**: int2bcd関数（10進数→BCD変換）
6. **96-100行目**: bcd2int関数（BCD→10進数変換）

#### Step 3: apmdのデーモン処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | apmd.c | `usr.sbin/apmd/apmd.c` | デーモンの初期化、イベントループ、設定ファイルに基づくアクション実行を理解する |
| 3-2 | apmdparse.y | `usr.sbin/apmd/apmdparse.y` | yacc文法によるapmd.confのパーサを理解する |
| 3-3 | apmdlex.l | `usr.sbin/apmd/apmdlex.l` | lex定義による字句解析を理解する |

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

```
apm (usr.sbin/apm/apm.c)
    |
    +-- main()
          +-- open("/dev/apm")
          +-- ioctl(APMIO_GETINFO)    # 情報取得
          +-- ioctl(APMIO_SUSPEND)    # サスペンド
          +-- ioctl(APMIO_STANDBY)    # スタンバイ
          +-- ioctl(APMIO_ENABLE)     # APM有効化
          +-- ioctl(APMIO_DISABLE)    # APM無効化

apmd (usr.sbin/apmd/apmd.c)
    |
    +-- main()
          +-- 設定ファイル読み込み (apmdparse.y/apmdlex.l)
          +-- デーモン化
          +-- イベントループ
                +-- ioctl(APMIO_NEXTEVENT)  # イベント取得
                +-- アクション実行           # 設定に基づく応答
```

### データフロー図

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

/dev/apm                apm:                           標準出力
(APM BIOS) ----------> ioctl(APMIO_GETINFO)  -------> (バッテリー情報等)

APMイベント            apmd:                           syslog
(電源ボタン等) ------> イベントループ                --> (イベントログ)
                        +-- アクション実行
apmd.conf                                              コマンド実行
(設定ファイル) ------> パーサ(yacc/lex)                (設定されたアクション)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| apm.c | `usr.sbin/apm/apm.c` | ソース | apmコマンドのメイン処理 |
| apmd.c | `usr.sbin/apmd/apmd.c` | ソース | apmdデーモンのメイン処理 |
| apmd.h | `usr.sbin/apmd/apmd.h` | ヘッダ | apmdの型定義 |
| apmdparse.y | `usr.sbin/apmd/apmdparse.y` | ソース | apmd.confパーサ（yacc文法） |
| apmdlex.l | `usr.sbin/apmd/apmdlex.l` | ソース | apmd.conf字句解析（lex定義） |
| apmd.conf | `usr.sbin/apmd/apmd.conf` | 設定 | APMイベント応答設定のサンプル |
| acpiconf/ | `usr.sbin/acpi/acpiconf/` | ソース | ACPI設定コマンド |
| acpidump/ | `usr.sbin/acpi/acpidump/` | ソース | ACPIテーブルダンプコマンド |
| apm.8 | `usr.sbin/apm/apm.8` | マニュアル | apmコマンドのmanページ |
| apmd.8 | `usr.sbin/apmd/apmd.8` | マニュアル | apmdデーモンのmanページ |
