Difference between revisions of "Xen EFI"

From Xen
(Update with Xen 4.9)
(GRUB2 with multiboot2)
Line 137: Line 137:
 
API does not have enough data to provide information to Xen under the EFI platform.
 
API does not have enough data to provide information to Xen under the EFI platform.
  
As such a [http://lists.xenproject.org/archives/html/xen-devel/2013-10/msg01645.html proposal] had been discussed to add a ''multibootv2+EFI'' API which would provide enough data such
+
GRUB 2.02 has also support for 'multiboot2' which can pass the EFI ImageHandler
that GRUB2's ''multiboot'' module could pass that to Xen compiled as ELF binary (.gz).
+
to the underlaying payload. This allows:
 
 
This would allow:
 
  
 
EFI firmware => GRUB2.EFI -> multiboot2 -> [xen.gz, vmlinuz, ramdisk]
 
EFI firmware => GRUB2.EFI -> multiboot2 -> [xen.gz, vmlinuz, ramdisk]
Line 147: Line 145:
 
loading them in the memory.
 
loading them in the memory.
  
That work has been deferred to Xen 4.6.
+
Xen 4.9 and later implements both multiboot and multiboot2. Prior versions
 +
only implemented multiboot.
  
As such the current workaround is to use the GRUB2 ''chainloader''. Example:
+
If you are using an older version you can use the GRUB2 ''chainloader'' workaround. Example:
  
 
<pre>
 
<pre>
Line 159: Line 158:
 
}
 
}
 
</pre>
 
</pre>
 +
 +
To build GRUB2 from scratch and utilize it please follow these instructions:
 +
 +
* git clone https://git.savannah.gnu.org/git/grub.git
 +
* cd grub
 +
* ./configure --target=x86_64 --with-platform=efi
 +
* make
 +
* sudo make install
 +
[It will install the files in /usr/local so won't conflict with the installed version]
 +
* sudo mkdir -p /usr/local/etc/default
 +
* Setup an default GRUB entries:
 +
<pre>
 +
cat << EOF > /usr/local/etc/default/grub
 +
GRUB_DEFAULT=0
 +
GRUB_TIMEOUT=10
 +
GRUB_CMDLINE_LINUX="console=hvc0 loglevel=8 initcall_debug"
 +
GRUB_CMDLINE_XEN="loglvl=all guest_loglvl=all console=com1,vga com1=115200,8n1"
 +
GRUB_TERMINAL=serial
 +
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"
 +
EOF
 +
</pre>
 +
[This is optional]
 +
* sudo chmod 400 /usr/local/etc/grub.d/10_linux
 +
[This is optional, but this way you will only have Xen entries]
 +
* Script to combine the different grub modules in one EFI file:
 +
<pre>
 +
cat << EOF > $HOME/build-grub
 +
#!/bin/bash                                                                                                                       
 +
 +
GRUB_MODULES="  all_video boot btrfs cat chain configfile echo \
 +
                efifwsetup efinet ext2 fat font gfxmenu gfxterm gzio halt \
 +
                hfsplus iso9660 jpeg loadenv loopback lvm mdraid09 mdraid1x \
 +
                minicmd normal part_apple part_msdos part_gpt \
 +
                password_pbkdf2 png \
 +
                reboot search search_fs_uuid search_fs_file search_label \
 +
                serial sleep syslinuxcfg test tftp video xfs \
 +
              linux backtrace usb usbserial_common \
 +
              usbserial_pl2303 usbserial_ftdi usbserial_usbdebug  multiboot multiboot2"
 +
 +
echo $GRUB_MODULES
 +
./grub/grub-mkimage -v -O x86_64-efi -o grub2.efi -p /EFI/grub2 \
 +
                -d grub/grub-core ${GRUB_MODULES}
 +
EOF
 +
</pre>
 +
* chmod 755 $HOME/build-grub
 +
* $HOME/build-grub
 +
[That creates the grub2.efi with 'multiboot2' support along with other modules]
 +
* sudo mkdir /boot/efi/EFI/grub2
 +
* sudo cp $HOME/grub2.efi /boot/efi/EFI/grub2
 +
* ./grub-mkconfig -o /boot/efi/EFI/grub2/grub.cfg
 +
[Inspect the grub.cfg. Make sure that it has 'multiboot2' and 'module2' for Xen.
 +
You may need the patch titled: "[PATCH] Use grub-file to figure out whether multiboot2 should be used for Xen.gz"
 +
* sudo efibootmgr -w -L GRUB2 -l "\EFI\grub2\grub2.efi" -c
 +
[To create an EFI boot manager 'GRUB2' entry]
 +
 +
And you are good to go.

Revision as of 17:19, 8 March 2017

Xen in EFI

Xen 4.3 and later can be built as EFI binaries. Xen 4.5 can be built as an EFI binary under ARM. Xen 4.9 can be built with Multiboot2 support which GRUB2 2.02 uses.

Linux 3.17 and later when built with CONFIG_XEN_EFI can be booted under Xen in EFI platform.

Xen does support verifying of payloads, such as the initial kernel and its ramdisk via the Shim protocol (GUID: 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23).

For shim repo, please see shim.

Compiling Xen as EFI

Compiling under x86

During the compilation process most of the Xen hypervisor code is compiled using the normal compiler (GCC). Only during the link-time do we employ the EFI linker to built an EFI binary.


As of Ubuntu 16.04 the binutils is compiled with PE (EFI) support. To verify run ld -V. You are looking for i386pe in it, as so:

$ ld -V
GNU ld version 2.26.1-1.2.fc25
  Supported emulations:
   elf_x86_64
   elf32_x86_64
   elf_i386
   elf_iamcu
   i386linux
   elf_l1om
   elf_k1om
   i386pep
   i386pe

Alternatively you can build you GCC crosstool chainOSDev UEFI link

Or recompile your binutils (Fedora 25):

  • dnf download --source binutils
  • rpm -hiv binutil*.srpm
  • cd /usr/src/redhat/SPECS
  • sudo dnf builddep --spec binutils.spec
  • patch -p1 < pe_binutils.patch

The pe_binutils.patch looks as follow:

--- binutils.spec.orig  2017-01-31 09:24:18.988130013 -0500
+++ binutils.spec       2017-01-31 09:25:38.975347558 -0500
@@ -22,7 +22,7 @@
 Summary: A GNU collection of binary utilities
 Name: %{?cross}binutils%{?_with_debug:-debug}
 Version: 2.26.1
-Release: 1%{?dist}
+Release: 1.2%{?dist}
 License: GPLv3+
 Group: Development/Tools
 URL: http://sources.redhat.com/binutils
@@ -263,6 +263,11 @@
     ;;
 esac
 
+case %{binutils_target} in x86_64*|i?86*|arm*|aarch64*)
+  CARGS="$CARGS --enable-targets=x86_64-pep"
+  ;;
+esac
+
 %if 0%{?_with_debug:1}
 CFLAGS="$CFLAGS -O0 -ggdb2 -Wno-error -D_FORTIFY_SOURCE=0"
 %define enable_shared 0
@@ -519,6 +524,9 @@
 %endif # %{isnative}
 
 %changelog
+* Tue Jan 31 2017 Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> 2.26-1.1.2
+- Add PE support.
+
 * Mon Aug 15 2016 Nick Clifton <nickc@redhat.com> 2.26.1-1
 - Rebase on FSF binutils 2.26.1 release.
 - Retire: binutils-2.26-formatting.patch
  • rpmbuild -ba binutils.spec
  • cd ../RPMS/x86_64/
  • rpm -U binut*.rpm

In either way, you will have an xen.efi file.

Compiling under ARM

From: efi.html:

For arm64, the PE/COFF header is open-coded in assembly, so no toolchain support for PE/COFF is required. Also, the PE/COFF header co-exists with the normal Image format, so a single binary may be booted as an Image file or as an EFI application.

Booting Xen under EFI platform

There are two ways of booting Xen:

  • From the EFI platform - which shows up in BIOS boot menu.
  • Using an bootloader (such as GRUB2)

Xen as EFI binary (loading)

Xen.efi as an EFI binary can be executed by the EFI firmware immediately. As the firmware does not provide an command line (nor would you want to have it), Xen expects an configuration file to tell it what initial domain (and ramdisk) to load afterwards. This configuration file must reside in the same directory as the xen.efi. Also the payloads (vmlinuz and ramdisk) MUST also reside in said directory.

The boot mechanism is simple:

EFI firmware => Xen.efi [loads vmlinuz and ramdisk and executes vmlinuz]

One can put the files in the /EFI/Boot and with efibootmgr configure the system to boot it:

efibootmgr -w -L Xen -l "\EFI\Xen\xen.efi" -c

which will produce a new boot target (for example):

[root@localhost EFI]# ls /boot/efi/EFI/Xen
initramfs-3.17.1-302.fc21.x86_64.img  vmlinuz-3.17.1-302.fc21.x86_64  xen.cfg  xen.efi
[root@localhost Xen]# efibootmgr -w -L Xen -l "\EFI\Xen\xen.efi" -c
BootCurrent: 0000
Timeout: 0 seconds
BootOrder: 0005,0001,0002,0003,0004,0000
Boot0000* Fedora
Boot0001* UEFI: ASUS    DRW-24B1ST
Boot0002* CD/DVD Drive 
Boot0003* Hard Drive 
Boot0004* Network Card 
Boot0005* Xen

Xen as gz binary

GRUB2 loader when built as an EFI binary can load various OS-es. The most common one is Linux where it uses the linuxefi GRUB module. However GRUB2 also has support for multiboot protocol which is what Xen uses. Sadly v1 of multiboot API does not have enough data to provide information to Xen under the EFI platform.

GRUB 2.02 has also support for 'multiboot2' which can pass the EFI ImageHandler to the underlaying payload. This allows:

EFI firmware => GRUB2.EFI -> multiboot2 -> [xen.gz, vmlinuz, ramdisk]

And GRUB2 would be responsible for reading from the ESP the various files and loading them in the memory.

Xen 4.9 and later implements both multiboot and multiboot2. Prior versions only implemented multiboot.

If you are using an older version you can use the GRUB2 chainloader workaround. Example:

menuentry "Xen EFI" {
    insmod part_gpt
    insmod search_fs_uuid
    insmod chain
    chainloader (hd0,gpt1)/EFI/XEN/xen.efi
}

To build GRUB2 from scratch and utilize it please follow these instructions:

[It will install the files in /usr/local so won't conflict with the installed version]

  • sudo mkdir -p /usr/local/etc/default
  • Setup an default GRUB entries:
cat << EOF > /usr/local/etc/default/grub
GRUB_DEFAULT=0
GRUB_TIMEOUT=10
GRUB_CMDLINE_LINUX="console=hvc0 loglevel=8 initcall_debug"
GRUB_CMDLINE_XEN="loglvl=all guest_loglvl=all console=com1,vga com1=115200,8n1"
GRUB_TERMINAL=serial
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"
EOF

[This is optional]

  • sudo chmod 400 /usr/local/etc/grub.d/10_linux

[This is optional, but this way you will only have Xen entries]

  • Script to combine the different grub modules in one EFI file:
cat << EOF > $HOME/build-grub
#!/bin/bash                                                                                                                         

GRUB_MODULES="  all_video boot btrfs cat chain configfile echo \
                efifwsetup efinet ext2 fat font gfxmenu gfxterm gzio halt \
                hfsplus iso9660 jpeg loadenv loopback lvm mdraid09 mdraid1x \
                minicmd normal part_apple part_msdos part_gpt \
                password_pbkdf2 png \
                reboot search search_fs_uuid search_fs_file search_label \
                serial sleep syslinuxcfg test tftp video xfs \
               linux backtrace usb usbserial_common \
               usbserial_pl2303 usbserial_ftdi usbserial_usbdebug   multiboot multiboot2"

echo $GRUB_MODULES
./grub/grub-mkimage -v -O x86_64-efi -o grub2.efi -p /EFI/grub2 \
                -d grub/grub-core ${GRUB_MODULES}
EOF
  • chmod 755 $HOME/build-grub
  • $HOME/build-grub

[That creates the grub2.efi with 'multiboot2' support along with other modules]

  • sudo mkdir /boot/efi/EFI/grub2
  • sudo cp $HOME/grub2.efi /boot/efi/EFI/grub2
  • ./grub-mkconfig -o /boot/efi/EFI/grub2/grub.cfg

[Inspect the grub.cfg. Make sure that it has 'multiboot2' and 'module2' for Xen. You may need the patch titled: "[PATCH] Use grub-file to figure out whether multiboot2 should be used for Xen.gz"

  • sudo efibootmgr -w -L GRUB2 -l "\EFI\grub2\grub2.efi" -c

[To create an EFI boot manager 'GRUB2' entry]

And you are good to go.