EFI stub kernel

From Gentoo Wiki
Jump to: navigation, search

The (U)EFI firmware present in many newer computers can function as bootloader, allowing you to boot without installing a separate bootloader.

Partitioning

You need to create a partition of type "EFI System partition", which is EF00 on GPT and EF on MBR. Example using sys-apps/gptfdisk:

root # gdisk /dev/sda
Command (? for help): n
Partition number (1-128, default 1): 1
First sector: (enter desired start sector and size, 100 MB should be plenty)
Command (? for help): t
Partition number (1-2): 1
Hex code or GUID (L to show codes, Enter = 8300): EF00
Command (? for help): w

Create a FAT32 filesystem inside:

root # mkfs.vfat -F 32 /dev/sda1

If you don't have mkfs.vfat (part of sys-fs/dosfstools) installed, you can use busybox:

root # busybox mkfs.vfat /dev/sda1

Kernel

Configuration

In order to boot directly from UEFI, the kernel needs to have CONFIG_EFI_STUB support enabled.

Kernel configurationEnable EFI stub support

Processor type and features  --->
    [*] EFI runtime service support 
    [*]   EFI stub support

UEFI does not pass kernel parameters to the kernel during normal boot, so you need to hardcode them via CONFIG_CMDLINE. Example for the root partition on /dev/sda2:

Kernel configurationEnable built-in kernel parameters

Processor type and features  --->
    [*] Built-in kernel command line
    (root=/dev/sda2)

For GPT systems, using root=PARTUUID=... might be preferable. To find out, you can use gdisk:

root # gdisk /dev/sda
Command (? for help): i
Partition number (1-5): 2
Partition unique GUID: (pass the ID that is shown here to the kernel)
Command (? for help): q
Note
The partition's UUID is distinct from the filesystem's UUID.

Initramfs

EFI Stub can load an initramfs and pass it to the kernel, but this requires passing a parameter from the EFI bootloader (ie. initrd=\efi\boot\myinitrd.img). This parameter cannot be built into CONFIG_CMDLINE as outlined above. This may defeat the purpose of using EFI stub as many users prefer it as a way to avoid the necessity of a bootloader and/or dealing with efi bootmgr. Another possibility is to embed the initramfs directly in the kernel image. In order to do this:

  • Generate the initramfs using your preferred method (Genkernel, Dracut, etc.)
  • Ensure the image is not compressed (just a cpio archive). Genkernel and Dracut both have command line switches for this.
  • Rename the initramfs with a .cpio extension, the kernel requires this to embed a cpio archive. The kernel image (with the cpio archive within it) will still be compressed as usual.
  • Ensure that the initramfs has the correct read-permissions for the user building the kernel. Most users build the kernel as the root user and may skip this step. Dracut makes the initramfs image readable only by the root user, so if you build the kernel as any other user adjust its permissions first. Failing to do so, and ignoring the kernel build warnings will result in a kernel with no embedded initramfs and potentially an unbootable system.
Kernel configurationBuild in the initramfs CPIO archive

General setup  --->
    [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
    (/boot/initramfs-3.12.21-gentoo-r1.cpio) Initramfs source file(s)
  • Install the kernel on the EFI partition.


However, if you do wish to pass an initramfs as a boot parameter, you still can using only efibootmgr (ie. no GRUB2). An external initramfs has some advantages over building the initramfs directly into the kernel (see the kernel help on CONFIG_INITRAMFS_SOURCE for details on its limitations). In fact you can use both a built-in and external initramfs simultaneously. Create and install your initramfs with genkernel, dracut, by hand, etc.. Install your kernel as outlined in the Installation section below. Then:

root # cp /boot/vmlinuz-3.14.14-gentoo /mnt/EFI/EFI/Boot/bootx64.efi
root #
cp /boot/initramfs-3.14.14-gentoo.img /mnt/EFI/EFI/Boot/initramfs.img
root #
efibootmgr --create --part 1 --label "Gentoo" --loader '\efi\boot\bootx64.efi' -u initrd='\efi\boot\initramfs.img'
Note
EFI uses \ as path separator.
Note
The system tested on required the kernel arguments to be passed as Unicode text (-u option). YMMV.

Installation

Now build the kernel and copy the image to your EFI partition as EFI/Boot/bootx64.efi. Example (with your EFI partition mounted to /mnt/EFI):

root # cd /usr/src/linux
root #
make -jN
root #
make install modules_install
root #
mkdir -p /mnt/EFI/EFI/Boot
root #
cp /boot/vmlinuz-3.7.9-gentoo /mnt/EFI/EFI/Boot/bootx64.efi

Adding more kernels

Note
In order to modify UEFI boot entries, your system needs to be booted in EFI mode. This means that you need to already have booted the EFI stub image as described above, or some EFI capable live media.

You can optionally make additional kernels known to UEFI. This is especially useful if you want to test more kernels or dual-boot with another operating system. These will be shown in the boot selection prompt, normally shown after you press a hotkey at the right time during system initialization.

Ensure that you have CONFIG_EFI_VARS enabled in your kernel, install sys-boot/efibootmgr and make them known to your UEFI.

Kernel configurationEnable EFI sysfs controls

Firmware Drivers  --->
    <*> EFI Variable Support via sysfs
root # cp /boot/vmlinuz-3.6.11-gentoo /mnt/EFI/EFI/Boot/vmlinuz.efi
root #
efibootmgr --create --part 1 --label "Gentoo" --loader '\efi\boot\vmlinuz.efi'
Note
EFI uses \ as path separator.

See also

External resources