UEFI 2.5からネットワークブートの方法として"HTTP BOOT"が増えました。
今回はこのHTTP BOOTは従来の方式に比べ何が嬉しいのか、この機能を使ってUEFIのアプリを起動するにはどのようにすればよいかを書いていこうと思います。
忙しい人のまとめ
HTTP BOOT とは
HTTP BOOTはUEFI 2.5で追加されたネットワークブートのためのUEFIの機能です。
この機能を使うと、HTTP(またはHTTPS)サーバーからファイルを取得し、UEFIアプリやOSを起動することができるようになります。
HTTP BOOT と PXEブートの違い
よく知られたネットワークブートの方法としてPXEブートがあります。これとHTTP BOOTはどのような点が異なるのでしょうか。 この疑問に関しては、以下のSUSE LinuxのドキュメントのIntroductionにわかりやすく書かれています。
UEFI HTTPBoot with OVMF - openSUSE
ここに書かれている内容をまとめると、HTTP BOOTではPXEに比べ以下の点が異なります。
- HTTP URLを使って起動イメージ指定が可能
- アドレス指定にDNSが利用可能
- ローカルネットワーク外からもネットワークブート可能
また、UEFIの仕様書(24.7 HTTP Boot)やtinanocoreの解説サイトを読むと、以下の点でも異なることがわかります。
このように、HTTP BOOTでは従来PXEによるネットワークブートを行うために必要であったDHCPサーバーの設定変更、TFTPサーバーの用意等が必要なくなるため、ネットワークブートのハードルが非常に低くなります。
実際にどのくらい簡単になるかを、想定環境の説明より確認していきましょう。
HTTP BOOTの想定環境
HTTP BOOTの想定環境には、以下の2つがあります。
- Corporate Environment
- Home Environment
それぞれどのような想定環境かを見ていきましょう。
Corporate Environment
最初にCorporate Environmentについて説明するために、UEFIの仕様書「24.7.2.1 Use in Corporate environment」のFigure 76より構成図を引用します。
Corporate Environmentの想定は、基本的には従来のPXEブートを行える環境と同様です。
この環境ではDHCPサーバーに対しHTTP BOOT Extensionの設定を入れることで、クライアントの起動時にDHCPからアドレスと同時にHTTP BOOTのURL等をもらい、HTTP BOOTを使ったネットワークブートを開始することが可能です。
よって、Corporate Environmentでサーバー側で用意する必要が出るのは、最大で以下の3つになります。
- "HTTP Extension設定可能"なDHCPサーバー(必須)
- DNSサーバー(ドメイン名を使う場合は必要。IPアドレス指定の場合は不要)
- HTTP(S)サーバー(外部の配布サイトを使う場合は不要)
Home Environment
次にHome Environmentについて説明するために、UEFIの仕様書「24.7.2.2 Use case in Home environment」のFigure 77より構成図を引用します。
この環境はDHCPサーバーにHTTP BOOT Extensionの設定を入れることのできない、一般的な家庭用ルーターでHTTP BOOTを行うことを想定しています。 この環境では一般的なDHCPサーバーからIPアドレス(とDNSサーバー等の情報)のみを取得し、HTTP BOOTのURL等はユーザーが自分で入力することでHTTP BOOTを行います。
よって、Home Environmentでサーバー側で用意する必要が出るのは、最大で以下の3つになります。
HTTP BOOTでUEFIアプリを動かしてみる
HTTP BOOTの使い方を確かめるために、Home Environmentにおいて実際にUEFIアプリをHTTP BOOTしてみようと思います。 なお、今回は動作確認が目的なので、OSの起動やインストール等まではやりません。
また、ターゲットはARM64環境とします。趣味です。
実験環境はいつもおなじみ Thinkpad x201と Arch Linux(x86_64) です。
HTTP BOOTに対応したUEFIのビルド
LinaroのビルドしてくれているQemuのイメージはHTTP BOOTが有効になっていなかったので、自分で有効にしてedk2からビルドし直します。
変更するところは edk2/ArmVirtPkg/ArmVirtQemu.dsc の以下の部分です。
DEFINE HTTP_BOOT_ENABLE = FALSE
ここのFALSEをTRUEにするとHTTP BOOTが有効になります。
!if $(HTTP_BOOT_ENABLE) == TRUE HttpLib|MdeModulePkg/Library/DxeHttpLib/DxeHttpLib.inf !endif
残りのビルドの方法はansibleのスクリプトにしたので、このスクリプトを動かすか、中身を読んで同じことをコマンドで実行すればHTTP BOOTが有効になったQEMU用のUEFIファームウェア(ARM64用)が edk2/Build/ArmVirtQemu-AARCH64/RELEASE_GCC5/FV/QEMU_EFI.fd
から得られます。
QEMU環境の用意
HTTP BOOTを行うには、QEMUの仮想マシンを、ホストマシンが繋がっている家庭用のLANにつなげる必要があります。
このために、QEMUの作り出すTAPデバイスとホストマシンのNICをブリッジで繋ぐ必要があります。
この作業は理解するのが大変なので、勝手に行ってくれるスクリプトを作りました。
最初に、init.sh
の IFACE="enp0s25"
のenp0s25のところを任意の物理NIC名に変更して、init.sh
を実行してください。
sudo ./init.sh
これでホスト側にブリッジデバイスの作成とブリッジデバイスへのNICの追加が終わります。
次に、 run_qemu_aarch64.sh
を実行すると、自動で qemu-ifup
が実行され、QEMUの作ったTAPデバイスがブリッジに追加されます。
./run_qemu_aarch64.sh
これで、LANにつながるQEMU仮想マシン環境が出来上がります。
HTTP BOOT
./run_qemu_aarch64.sh
を実行してQEMU上でUEFI Shellが立ち上がったら、いよいよHTTP BOOTを行ってみます。
まずはじめに、IPアドレスの取得を行います。 これはUEFI Shellの上で以下のコマンドを打つと、簡単に設定できます。
ifconfig -s eth0 dhcp
UEFI Shell上ではpingコマンドが使えるので、ホストマシンのIPアドレスにPingをうってみて、疎通を確認してください。 疎通が確認できれば、次に進みます。
HTTP BOOTはUEFI Shell上ではコマンドがなく行えないため、Shell上で exit
コマンドを実行して一度マネージャーに戻ります。
するとこのような画面が出てくるので、ここから Device Manager -> Network Device List -> NICのMACアドレスを選択 -> HTTP Boot Configuration
と進みます。
するとこのような画面が得られるので、 Boot URI
のところに *.efi
のあるURLを指定します。
今回はhttpboot/hello 以下でビルドしたmain.efiを以下のコマンドで起動したHTTPサーバーから配布しています。
python3 -m http.sever
ホストのIPアドレスは 192.168.111.50
でHTTPサーバーの待受ポートは8000番なので、http://192.168.111.50:8000/main.efi
をURIとして指定しています。
設定が終わったら ESCキー を押してください。 すると「設定を保存するならYをおしなさい」というメッセージが出るので、Yを押して保存します。 その後なんどかESCを押して、以下のマネージャーのTOPに戻ってください。
次にBoot Manager
を開くと一番最後に UEFI HTTP
という項目が増えているはずなので、ここを選択してEnterを押します。
しばらく待つとUEFIアプリが読み込まれて、私の作ったサンプルでは hello
が表示されます。
一つ注意として、HTTP BOOTはUEFIアプリの実行が終わるとすぐにブートマネージャーの画面に戻されてしまいます。 そうならないようしたい場合は、終了前にキー入力を待つような処理を最後に入れる必要がありそうです。
おわり
すみません、最近時間がなくて細かいところまで丁寧に書くことができませんでした。
質問をコメントでいただければ補足しますので、よろしくお願いします。