16

I have Ubuntu 14.04 running in UEFI mode as only operating system, no dual-boot here. The kernel version is 3.13.0-24-generic. There is an EFI partition. In this case the EFI partition is not at the default /dev/sda1 but at /dev/sda3 because I did actually convert BIOS mode to EFI mode. I have used the grub-efi-amd64 package, though that actually loads GRUB boot menu from UEFI firmware boot menu (UEFI boot loads \EFI\ubuntu\grubx64.efi).

I want to skip that double boot menu loading step, and boot faster, directly from UEFI into the kernel. The Ubuntu kernels since 12.10 have "Kernel EFI stub loader" feature.

I know I do need to copy the Ubuntu kernel to the EFI partition (possibly rename) and create an entry in UEFI boot menu (for instance using efibootmgr). Which exact terminal commands are necessary to do this?

2 Answers 2

16

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.

3
  • I don't know how you figured this out but you are amazing. There is surprisingly little doc around this neat feature. Feb 27, 2015 at 1:34
  • In case it isn't working for you try to put arguments of -l and -u in double quotes (or escape backslash manually). You can test if this is the issue by executing efibootmgr -v after you've added new entry to EFI boot menu. Also, in case your machine has more than one disks (say a SSD and a HDD) then you'll need to specify one by -d which defaults to /dev/sda (see man efibootmgr) Apr 8, 2018 at 5:31
  • is that 39 character length limit still around or has it since been changed? Apr 13 at 19:51
7

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.

5
  • Any way to get it to work with secure boot since on my HP laptop when I try this it gives a secure boot error (of course I can disable secure boot too)
    – Suici Doga
    Feb 3, 2018 at 13:19
  • It looks like you would have to use cryptboot and some tools to sign the kernel first. It's a bit of a hassle especially if you're not using Arch (as there is no ready-to-use tool), so I'd just disable secure boot.
    – Léo Lam
    Feb 5, 2018 at 11:08
  • What about copying the .signed kernel ?
    – Suici Doga
    Feb 6, 2018 at 4:17
  • does this work on ubuntu also because I'm not seeing the /vmlinuz and /initrd.img links on my system when I do a ls / Apr 13 at 22:19
  • for the record, seems like on ubuntu 22.04 they can be found under /boot/vmlinuz and /boot/initrd.img respectively. Apr 13 at 22:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .