Home Wiki > UEFI HTTPBoot with OVMF
Sign up | Login

UEFI HTTPBoot with OVMF

tagline: From openSUSE

UEFI HTTPBoot with OVMF
UEFI HTTPBoot with OVMF
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.


Tested on openSUSE Recommended articles Related articles
Icon-checked.png

Icon-manual.png Icon-help.png

Please refer to Help:Editing in order to write a quality approved article.

Introduction

HTTPBoot was added into UEFI SPEC since 2.5. It aims to replace PXE and provides more features. Actually, the concept of HTTPBoot is similar to PXE. It starts with the HTTP URL from the DHCP server and fetches the data with the HTTP protocol. The key difference between HTTPBoot and PXE is the support of DNS. With DNS, the firmware and the bootloader can resolve the domain name so it's possible to pass the well-known URL to download the image instead of the explicit IP URL. Besides, HTTP is designed to cross different domains, while tftp (PXE) is only for the local network. This article provides the HOWTO to set up the simplest scheme of HTTPBoot: one server and one client. The server is the host computer and the client is the guest virtual machine.


Preparation

There are several networking settings in qemu. The tap networking is the best choice since it utilizes the virtual interface to achieve the two way communication between the host and the guest. It provides a complete isolated network as long as we don't bridge the virtual interface the any real one. This is very important since we are going to setup the dhcp server which could easily mess up the local network.

[host] <--> (tap0) <--> [guest]

This article uses the IP subnets 192.168.111.0/24 (v4) and 2001:db8:f00f:cafe::/64 (v6). Please adjust the related settings in case any conflict exists.

The Server

As a HTTPBoot server, the host computer has to install the following packages: dhcp-server, lighttpd (or any other HTTP service), dnsmasq, and tunctl.

The Client

To set up a virtual machine with the latest UEFI, the host needs qemu and OVMF. OVMF is the UEFI implementation for qemu. For the better support of HTTPBoot, it's recommended to use ovmf >= r18743.

The latest OVMF is available in https://build.opensuse.org/package/show/Virtualization/ovmf

Just install qemu-ovmf-x86_64 which contains the firmware files for qemu.

OS Image

SUSE Linux Enterprise starts to support HTTPBoot since 12-SP3. For openSUSE, the HTTPBoot support is planned for 15.


The Configuration of The Server

Network Interface

First, we set up the a tap interface for the communication between the host and the guest.

 # tunctl -u <username> -t tap0

If the firewall is enabled, it's recommended to add tap0 to the "Internal Zone", so the ports won't be blocked.

Add the IP address with ip:

 # ip link set dev tap0 up
 # ip addr add 192.168.111.1/24 dev tap0
 # ip addr -6 add 2001:db8:f00f:cafe::1/64 dev tap0

Add the IPv4 and IPv6 address with 'ifconfig' (deprecated):

 # ifconfig tap0 192.168.111.1
 # ifconfig tap0 inet6 add 2001:db8:f00f:cafe::1/64

In case ifconfig complains "Permission Denied" when adding the ipv6 address, try to enable ipv6 for tap0 with

 # sysctl net.ipv6.conf.tap0.disable_ipv6=0

DNS Server

DNS is optional but it's nice to give your server a well-known name. To set up the DNS server, add the following lines to /etc/dnsmasq.conf

 interface=tap0
 addn-hosts=/etc/dnsmasq.d/hosts.conf

Then, create the mapping of the domain name of the IP address in /etc/dnsmasq.d/hosts.conf

 192.168.111.1 www.httpboot.local
 2001:db8:f00f:cafe::1 www.httpboot.local

Now, it's time to start the DNS server.

 # systemctl start dnsmasq

NOTE: UEFI 2.7 changes the device path of HTTPBoot and inserts a DNS node, and the shim bootloader is currently incompatible with the change. The patch is now pending in upstream (https://github.com/rhboot/shim/pull/103). To work around this issue, just remove the name server from the dhcp server settings and replace the domain name with the server IP.

DHCPv4 Server

Here we will set up the mixed DHCPv4 server for both PXEBoot and HTTPBoot. Add the following lines to /etc/dhcpd.conf:

 option domain-name-servers 192.168.111.1;
 option routers 192.168.111.1;
 default-lease-time 14400;
 ddns-update-style none;
 subnet 192.168.111.0 netmask 255.255.255.0 {
   range dynamic-bootp 192.168.111.100 192.168.111.120;
   default-lease-time 14400;
   max-lease-time 172800;
   class "pxeclients" {
     match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
     next-server 192.168.111.1;
     filename "/bootx64.efi";
   }
   class "httpclients" {
     match if substring (option vendor-class-identifier, 0, 10) = "HTTPClient";
     option vendor-class-identifier "HTTPClient";
     filename "http://www.httpboot.local/bootloader.efi";
   }
 }

First, we match the identifier from the client to tell what kind of service it requests. For HTTPBoot, the DHCPv4 server MUST use "HTTPClient" for option 60 since the client use it to identify whether this is a HTTPBoot offer or not.

Start the dhcp daemon:

 # systemctl start dhcpd

DHCPv6 Server

To set up the DHCPv6 server, add the following lines to /etc/dhcpd6.conf:

 option dhcp6.bootfile-url code 59 = string;
 option dhcp6.vendor-class code 16 = {integer 32, integer 16, string};
 subnet6 2001:db8:f00f:cafe::/64 {
         range6 2001:db8:f00f:cafe::42:10 2001:db8:f00f:cafe::42:99;
         option dhcp6.bootfile-url "http://www.httpboot.local/bootloader.efi";
         option dhcp6.name-servers 2001:db8:f00f:cafe::1;
         option dhcp6.vendor-class 0 10 "HTTPClient";
 }

First, we define the type of the boot URL and the vendor class and then set the details. Like the DHCPv4 settings, we have to assign the boot URL. Please note that we have to use the IPv6 name in the boot URL. Similar to option 60 in DHCPv4, we have to specify the vendor class. The vendor class option in DHCPv6 consists of the enterprise number and the vendor class data (length and the content). The HTTPBoot driver doesn't care the enterprise number, so we just use 0. The content of the vendor class data has to be "HTTPClient", or the client will just ignore the offer.

For the older HTTPBoot implementation, it doesn't follow RFC 3315 and will need a different setting like this:

 option dhcp6.bootfile-url code 59 = string;
 option dhcp6.vendor-class code 16 = string;
 subnet6 2001:db8:f00f:cafe::/64 {
         range6 2001:db8:f00f:cafe::42:10 2001:db8:f00f:cafe::42:99;
         option dhcp6.bootfile-url "http://www.httpboot.local/bootloader.efi";
         option dhcp6.name-servers 2001:db8:f00f:cafe::1;
         option dhcp6.vendor-class "HTTPClient";
 }

Now start the DHCPv6 daemon.

 # systemctl start dhcpd6

It's also possible to setup a DHCP6 server for both PXEBoot and HTTPBoot. Like this:

 option dhcp6.bootfile-url code 59 = string;
 option dhcp6.vendor-class code 16 = {integer 32, integer 16, string};
 
 subnet6 2001:db8:f00f:cafe::/64 {
         range6 2001:db8:f00f:cafe::42:10 2001:db8:f00f:cafe::42:99;
 
         class "PXEClient" {
                 match substring (option dhcp6.vendor-class, 6, 9);
         }
 
         subclass "PXEClient" "PXEClient" {
                 option dhcp6.bootfile-url "tftp://[2001:db8:f00f:cafe::1]/bootloader.efi";
         }
 
         class "HTTPClient" {
                 match substring (option dhcp6.vendor-class, 6, 10);
         }
 
         subclass "HTTPClient" "HTTPClient" {
                 option dhcp6.bootfile-url "http://www.httpboot.local/bootloader.efi";
                 option dhcp6.name-servers 2001:db8:f00f:cafe::1;
                 option dhcp6.vendor-class 0 10 "HTTPClient";
         }
 }

It could also go further to match the vendor-class for different architecture. For example, "HTTPClient:Arch:00016" means a x86_64 HTTPBoot client, and it can be rewritten as:

         class "HTTPClient" {
                 match substring (option dhcp6.vendor-class, 6, 21);
         }
 
         subclass "HTTPClient" "HTTPClient:Arch:00016" {
                 option dhcp6.bootfile-url "http://www.httpboot.local/boot/bootx64.efi";
                 option dhcp6.name-servers 2001:db8:f00f:cafe::1;
                 option dhcp6.vendor-class 0 10 "HTTPClient";
         }

Then the server can serve different architectures at the same time.

TFTP server(Optional)

In case you need to support both PXE and HTTPBoot, a tftp server is necessary. Just install tftp and start the service:

 # systemctl start tftp.socket
 # systemctl start tftp.service

openSUSE/SLE now provide a special package, tftpboot-installation, for PXE. For example, just install tftpboot-installation-openSUSE-Tumbleweed-x86_64 and the Tumbleweed bootloader and related files will be installed in /srv/tftpboot/openSUSE-Tumbleweed-x86_64/. Read /srv/tftpboot/openSUSE-Tumbleweed-x86_64/README for more information.

HTTP Server

There is no special setting for the HTTP server. Just copy the bootloader.efi (or whatever UEFI application) to /srv/www/htdocs/ and start the daemon.

 # systemctl start lighttpd

For SLE, just copy everything (or at least boot and EFI) in the first iso image to /srv/www/htdocs/sle/, and replace "http://www.httpboot.local/bootloader.efi" in dhcp.conf with "http://www.httpboot.local/sle/EFI/BOOT/bootx64.efi". This should at least bring up the grub2 menu. The rest is similar to PXEBoot, and please refer the deployment guide(*) to setup grub.cfg.

(*) https://www.suse.com/documentation/sles-12/singlehtml/book_sle_deployment/book_sle_deployment.html#part.installserver

Launch The Client

Now it's time to set up a virtual machine as the HTTPBoot client. There are a few qemu options needed to create a UEFI virtual machine.

  1. Specify the firmware
 -drive if=pflash,format=raw,readonly,file=/usr/share/qemu/ovmf-x86_64-code.bin \
 -drive if=pflash,format=raw,file=ovmf-x86_64-vars.bin

Please note that ovmf-x86_64-vars.bin must be writable. Just copy /usr/share/qemu/ovmf-x86_64-vars.bin to the working directory.

  1. Specify the network device
 -netdev tap,id=hostnet0,ifname=tap0,script=no,downscript=no \
 -device virtio-net-pci,romfile=,netdev=hostnet0

Since the host uses tap0 to communicate with the guest, we must specify the interface. "romfile=" is to disable the iPXE support so the virtual machine will use the native PXE and HTTPBoot functions from OVMF instead from iPXE.

The complete qemu command would be like this:

 $ qemu-system-x86_64 -enable-kvm \
                      -drive if=pflash,format=raw,readonly,file=/usr/share/qemu/ovmf-x86_64-code.bin \
                      -drive if=pflash,format=raw,file=ovmf-vars.bin \
                      -hda fat:hda-contents/ -monitor stdio \
                      -netdev tap,id=hostnet0,ifname=tap0,script=no,downscript=no \
                      -device virtio-net-pci,romfile=,netdev=hostnet0

If you are using libvirt, then you can use "rom bar" to disable iPXE support. For example:

    <interface type='bridge'>
      <mac address='00:11:22:33:44:55'/>
      <source bridge='br0'/>
      <model type='virtio'/>
      <rom bar='off'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </interface>

When the TianoCore logo shows, press "ESC" to enter the firmware menu.

Press "DOWN" to go to "Boot Manager" and press "Enter".

There will be several boot options, and two "EFI Network" options are the HTTPBoot IPv4 and HTTPBoot IPv6. Although the name of the boot options doesn't hint HTTPBoot, the device path does. If there is a URI() node appended in the end of the device path, it's a HTTPBoot boot option.

For example:

HTTPBoot IPv4

HTTPBoot IPv6

Just choose one of the boot options, and the firmware will start to download your UEFI application and execute it!


Another way to test http boot is download a iso image from a URL. The benefit of this way is that you don't need to setup DHCP on host machine. Just need to launch http server on host.

The first step is putting iso file to /srv/www/htdocs on server side:

e.g. /srv/www/htdocs/openSUSE-Leap-42.1-NET-x86_64.iso

On client code, you should launch UEFI firmware UI:

Device Manager -> Network Device List

e.g. IPv4

Enable DHCP or you can set static ip

Create a boot option by "HTTP Boot Configuration"

Edit "Boot URI", point to the position of ISO file

Select "UEFI HTTP" to boot to the ISO image


See also

Related articles

External links