/home/tnishinaga/TechMEMO

日々行ったこと、面白かったことを書き留めます。

UEFIのHTTP BOOTを試してみる

UEFI 2.5からネットワークブートの方法として"HTTP BOOT"が増えました。

今回はこのHTTP BOOTは従来の方式に比べ何が嬉しいのか、この機能を使ってUEFIのアプリを起動するにはどのようにすればよいかを書いていこうと思います。

忙しい人のまとめ

  • ネットワークブートがHTTP経由でできます
  • DHCPの設定変更なしでもOKです
  • 対応バージョンはUEFI 2.5以上です

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の解説サイトを読むと、以下の点でも異なることがわかります。

  • DHCPサーバーの設定変更が必須ではない(家庭用ルーターでもネットワークブート可能)
  • TFTPサーバー不要

このように、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より構成図を引用します。

f:id:tnishinaga:20171221030526p:plain

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より構成図を引用します。

f:id:tnishinaga:20171221032502p:plain

この環境はDHCPサーバーにHTTP BOOT Extensionの設定を入れることのできない、一般的な家庭用ルーターでHTTP BOOTを行うことを想定しています。 この環境では一般的なDHCPサーバーからIPアドレス(とDNSサーバー等の情報)のみを取得し、HTTP BOOTのURL等はユーザーが自分で入力することでHTTP BOOTを行います。

よって、Home Environmentでサーバー側で用意する必要が出るのは、最大で以下の3つになります。

  • 一般的なDHCPサーバー(必須)
  • DNSサーバー(ドメイン名を使う場合は必要。IPアドレス指定の場合は不要)
  • HTTP(S)サーバー(外部の配布サイトを使う場合は不要)

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 から得られます。

github.com

QEMU環境の用意

HTTP BOOTを行うには、QEMU仮想マシンを、ホストマシンが繋がっている家庭用のLANにつなげる必要があります。

このために、QEMUの作り出すTAPデバイスとホストマシンのNICをブリッジで繋ぐ必要があります。

この作業は理解するのが大変なので、勝手に行ってくれるスクリプトを作りました。

github.com

最初に、init.shIFACE="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 コマンドを実行して一度マネージャーに戻ります。

f:id:tnishinaga:20171222221742p:plain

するとこのような画面が出てくるので、ここから Device Manager -> Network Device List -> NICのMACアドレスを選択 -> HTTP Boot Configuration と進みます。

f:id:tnishinaga:20171222012657p:plain

するとこのような画面が得られるので、 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.efiURIとして指定しています。

設定が終わったら ESCキー を押してください。 すると「設定を保存するならYをおしなさい」というメッセージが出るので、Yを押して保存します。 その後なんどかESCを押して、以下のマネージャーのTOPに戻ってください。

f:id:tnishinaga:20171222221742p:plain

次にBoot Manager を開くと一番最後に UEFI HTTP という項目が増えているはずなので、ここを選択してEnterを押します。

f:id:tnishinaga:20171222013348p:plain

しばらく待つとUEFIアプリが読み込まれて、私の作ったサンプルでは hello が表示されます。

f:id:tnishinaga:20171222014036p:plain

一つ注意として、HTTP BOOTはUEFIアプリの実行が終わるとすぐにブートマネージャーの画面に戻されてしまいます。 そうならないようしたい場合は、終了前にキー入力を待つような処理を最後に入れる必要がありそうです。

おわり

すみません、最近時間がなくて細かいところまで丁寧に書くことができませんでした。

質問をコメントでいただければ補足しますので、よろしくお願いします。