How to boot load the kernel using EFI stub (efistub) loader?

The commands below are more generic then for kernel version 3.13.0-35 only.

1. Mount the efi partition and copy the kernel files there

$ mount /dev/sda3 /boot/efi

$ mkdir -pv /boot/efi/EFI/ubuntu/

$ cp -uv /boot/vmlinuz-* /boot/initrd.img-* /boot/efi/EFI/ubuntu/
'/boot/vmlinuz-3.13.0-35-generic' -> '/boot/efi/EFI/ubuntu/vmlinuz-3.13.0-35-generic'
'/boot/initrd.img-3.13.0-35-generic' -> '/boot/efi/EFI/ubuntu/initrd.img-3.13.0-35-generic'

2. Change the kernel file name

Shorten the kernel file name by removing -generic because there seems to be a 39 character length path limit and Rename kernel file(s) to end in .efi, this ensures compatibility with most systems

$ for f in /boot/efi/EFI/ubuntu/vmlinuz-*-generic; do mv -uv -- "$f" "${f//-generic/}.efi"; done
'/boot/efi/EFI/ubuntu/vmlinuz-3.13.0-35-generic' -> '/boot/efi/EFI/ubuntu/vmlinuz-3.13.0-35-generic.efi'`

The above name kernel file name shortening is not enough for a dpkg installed mainline kernel, because for example /EFI/ubuntu/vmlinuz-3.16.0-031600rc6.efi without -generic is still 40 characters long.

3. Add new entry to EFI boot menu

Replace 3.13.0-35 in this example with your specific kernel version

$ kv=3.13.0-35;efibootmgr -c -p 3 -L $kv -l \EFI\ubuntu\vmlinuz-$kv.efi -u root=/dev/sda1 initrd=\\EFI\\ubuntu\\initrd.img-$kv-generic ro rootfstype=ext4 debug ignore_loglevel libata.force=dump_id crashkernel=384M-:128M

This new boot menu entry will become your default new boot choice.

You might not need the extra debugging parameters debug, ignore_loglevel, libata.force=dump_id and crashkernel=384M-:128M. Initrd must be present, otherwise boot hangs at "Switched to clocksource tsc." because the root device sda1 cannot be opened.


According to the Debian wiki, this can be done in a few simple steps that will survive a kernel update.

Note: this assumes that you have an EFI partition mounted at /boot/efi.

  1. Create /etc/kernel/postinst.d/zz-update-efistub with the following contents:

    #!/bin/sh
    cp /vmlinuz /initrd.img /boot/efi/EFI/ubuntu/
    

    This is a hook that will be ran on kernel update to copy the latest kernel image and initrd to the appropriate location. Then make it executable and run it:

    sudo chmod +x /etc/kernel/postinst.d/zz-update-efistub
    sudo /etc/kernel/postinst.d/zz-update-efistub
    
  2. Add the boot entry:

    sudo efibootmgr -c -d /dev/sdb -p 1 -L "Ubuntu (efistub)" -l /EFI/ubuntu/vmlinuz -u "root=/dev/sdb2 rw initrd=/EFI/ubuntu/initrd.img quiet splash"
    

    Don't forget to change the -d and -p arguments depending on where your EFI system partition is. In my case, it is /dev/sdb1, but this is likely to be different for you. You will probably also have to change the root= value in the kernel cmdline to your root partition.

    (You can change the label to anything you want by changing the -L parameter.)

    The boot entry you just added will become the default entry. And it won't break after a kernel update, since the hook will make sure vmlinuz and initrd.img are always updated.