本稿は手元環境向けに以下の記事をアレンジして実践してみたものです。こちらの記事ではiPXEをテスト機に書き込んでいますが、完全にPXEブートのみで納められるようにしてみました。
- BitVisorをネットワークブートする by nvsofts さん
概要
上記記事同様に、BitVisorを改造して遊ぶにあたり開発機からテスト機にいちいち書き込んだりコピったりするのは面倒なのでネットワークブートでどうにかしたいところです。ただし、テスト機側にgrubが入っていない場合もあります。ここではiPXE自体もPXEブートしてくることでテスト機側がLinuxでなくてもネットワークブートできるようにしてみました。
要件と想定はこんな感じです。
- すでにDHCPサーバが存在するセグメントにてBitVisorをネットワークブートさせたい
- テスト機(BitVisorを動かす箱)はgrubを前提とせず、BIOS/EFIでPXEの有効化のみで動作できるようにする
- /bootへの書き込み等を不要にする
- 開発機(BitVisorのビルドや開発をする箱)およびPXEサーバはUbuntu環境を想定
ここでは以下の手順でこれを実現します。
- bitvisorのビルド: 最終的に起動するbitvisorのバイナリ生成
- iPXEのビルド: bitvisor.elfの前段階のチェインローダ生成
- TFTPサーバの用意: iPXE & bitvisor.elf配布用)
- HTTPサーバの用意: bitvisor.elf配布用)
- 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ブートができる様になります。
今回はこれを用いて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が上がるはず?
ほんとにBitVisorが動いているのか確認する術が良く分かりませんが、以下の様に
dbgshコマンドには反応しているのでおそらく動いているのでしょう(ということにしておく)。