PXEブートによるBitVisor開発環境の構築

本稿は手元環境向けに以下の記事をアレンジして実践してみたものです。こちらの記事ではiPXEをテスト機に書き込んでいますが、完全にPXEブートのみで納められるようにしてみました。

- [BitVisorをネットワークブートする](http://qiita.com/nvsofts/items/62f96dff5340b9d7c851) by nvsofts さん

# 概要
上記記事同様に、BitVisorを改造して遊ぶにあたり開発機からテスト機にいちいち書き込んだりコピったりするのは面倒なのでネットワークブートでどうにかしたいところです。ただし、テスト機側にgrubが入っていない場合もあります。ここではiPXE自体もPXEブートしてくることでテスト機側がLinuxでなくてもネットワークブートできるようにしてみました。

要件と想定はこんな感じです。

- すでにDHCPサーバが存在するセグメントにてBitVisorをネットワークブートさせたい
  - テスト機(BitVisorを動かす箱)はgrubを前提とせず、BIOS/EFIでPXEの有効化のみで動作できるようにする
  - /bootへの書き込み等を不要にする
- 開発機(BitVisorのビルドや開発をする箱)およびPXEサーバはUbuntu環境を想定

ここでは以下の手順でこれを実現します。

1. bitvisorのビルド: 最終的に起動するbitvisorのバイナリ生成
1. iPXEのビルド: bitvisor.elfの前段階のチェインローダ生成
1. TFTPサーバの用意: iPXE & bitvisor.elf配布用)
1. HTTPサーバの用意: bitvisor.elf配布用)
1. pxe-pdhcpの用意: 既存セグメントへのPXEブートの追加

流れとしてはpxe-pdhcpで既存セグメントでのPXEブートを可能にし、第一段階にiPXEを起動させそこからさらに第二段階でBitVisorをロードするという形を取っています。

# 開発機(PXEサーバ)でのセットアップ
## 1. BitVisorの用意

BitVisorは本家ページから落としてきてビルドしておきます。

```
% wget http://downloads.sourceforge.net/bitvisor/bitvisor-1.4.tar.gz
% tar zxvf bitvisor-1.4.tar.gz
% cd bitvisor-1.4
% make
# シリアルコンソールを有効にする場合は make CONFIG_TTY_SERIAL=1
```

これでソースディレクトリに __bitvisor.elf__ が生成されるので、そのパスをメモっておきます。
なお上記例ではシリアルコンソールを有効にする場合についても記載していますが、実際にシリアルコンソールしか持たない機器で試したところゲストOS(もともと入っているOS)のコンソールが取れなくなってしまいました。SSHなど別の手段を用いられない場合は、こちらは使わないほうが良いかもしれません。

## 2. iPXEの準備

まずiPXEがbitvisorをロードする手順を記述したファイルを適当な位置に作ります。ここでは$HOME/bitvisor.cfgとしています。bitvisor.elfをHTTP経由で取得する場合は以下のような内容で作成します。

```
#!ipxe

dhcp && kernel http://${開発機のIPアドレス}/bitvisor.elf && boot
```

なおTFTP経由にすることでHTTPサーバを介さずに起動させることも可能です。この場合は以下の様な内容になります。

```
#!ipxe

dhcp && kernel tftp://${開発機のIPアドレス}/bitvisor.elf && boot
```

あくまで筆者の手元環境でではありますが、TFTPを用いるとHTTPより格段に転送が遅い(数倍時間がかかる)傾向があるためHTTPの方を推奨しています。

```
# iPXEのダウンロード
% git clone http://git.ipxe.org/ipxe.git
% cd ipxe/src

# ここで config/console.h を編集してCONSOLE_SERIALを有効にしておく
% vim config/console.h

# 先ほどのbitvisor.cfgの起動方法を埋め込む
% make bin/undionly.kpxe EMBED=${先ほどのbitvisor.cfgの相対パス}
``` 

生成された __bin/undionly.kpxe__ が第一段階にPXEブートされ、bitvisor.elfをロードしする役割を担います。このファイルへのパスもメモっておきましょう。

## 3. TFTPサーバの用意

これまでに生成した、PXEブート時に必要なファイル転送のためにTFTPサーバを上げます。またこれまで生成したバイナリファイルへシンボリックリンクをはりtftp越しに取得できるようにしておきます。

```
# tftpdのインストール
% sudo apt install tftpd

# ルートは /tftpboot に作成
% mkdir /tftpboot

# xinetdにtftpの登録
% cat /etc/xinetd.d/tftp 
service tftp
{
        protocol        = udp
        port            = 69
        socket_type     = dgram
        wait            = yes
        user            = nobody
        server          = /usr/sbin/in.tftpd
        server_args     = /tftpboot
        disable         = no

}

# bitvisor.elfへのシンボリックリンクを /tftpboot/bitvisor.elf として置く (HTTP経由で転送する場合は不要)
% ln -s ${先ほどmakeしたbitvisor.elfへの絶対パス} /tftpboot/bitvisor.elf

# undionly.kpxeへのシンボリックリンクを /tftpboot/undionly.kpxe として置く
% ln -s ${先ほどmakeしたbin/undionly.kpxeへの絶対パス} /tftpboot/undionly.kpxe
```

これでTFTPで転送すべきファイルの配置は完了です。

## 4. HTTPサーバの用意

bitvisor.elfの転送にHTTPを用いる場合は、HTTPサーバを用意します。TFTPで完結させる場合はこの手順は不要です。ここでは apache2 を用います。

```
# apache2のインストール
% sudo apt install apache2

# /var/www がドキュメントルートと仮定して、bitvisor.elfへのシンボリックリンクを置く
# sudo ln -s ${先ほどmakeしたbitvisor.elfへの絶対パス} /var/www/bitvisor.elf
```

これでHTTPで転送すべきファイルの配置は完了です。

## 5. pxe-pdhcpの用意

pxe-pdhcpは frsyuki さん作の、DHCPサーバが存在するネットワークに後付けでPXEブートを可能にするプログラムです。これを用いることで、ルータと同居していてPXE用コンフィグを入れられないDHCPサーバが存在する環境でもPXEブートができる様になります。

- [frsyuki/pxe-pdhcp](https://github.com/frsyuki/pxe-pdhcp)

今回はこれを用いてiPXEをブートさせます。

```
# pxe-pdhcp のビルド
% git clone https://github.com/frsyuki/pxe-pdhcp.git
% cd pxe-pdhcp
% make

# pxe-pdhcp の起動
sudo ./pxe-pdhcp -d -i eth0 -l 0.0.0.0 -t ${開発機のIPアドレス} -b 255.255.255.255 undionly.kpxe
```

pxe-pdhcpに与えるパラメータとして以下を指定します。PXEの第一段階では /tftpboot/undionly.kpxe を起動させるためNBPとしてその名前を渡します。

- Listen Address(-l)
  - 0.0.0.0
- TFTP Address(-t)
  - 開発機のIPアドレス
- Broadcast Address (-b)
  - 255.255.255.255
- Network Boot Programの名前
  - undionly.kpxe

上記にて開発機側の設定は完了です。

# テスト機側のセットアップ

テスト機ではBIOS/EFIにてPXEを有効化しておきます。

# 起動！

上手くいくとこんな感じでiPXEをPXEブートしそこからBitVisorそしてゲストOSが上がるはず？

![スクリーンショット 2017-06-26 17.44.25.png](https://qiita-image-store.s3.amazonaws.com/0/2226/b1c1b4ce-42aa-5fe0-b982-a41c2120607a.png)

ほんとにBitVisorが動いているのか確認する術が良く分かりませんが、以下の様に
dbgshコマンドには反応しているのでおそらく動いているのでしょう(ということにしておく)。

![スクリーンショット 2017-06-26 17.48.12.png](https://qiita-image-store.s3.amazonaws.com/0/2226/cf982323-cfcf-b554-67d2-496ac6e0fa66.png)