Previously I wrote how to make USB bootable NixOS.
This time, I’ll cover the UEFI part so that you can boot NixOS with UEFI
Successfully tested on Lenovo ThinkPad T430 and Sony VAIO 13 Touch Ultrabook.
mount -o loop nixos-minimal-14.12.335.676e8d7-x86_64-linux.iso /mnt
mkdir iso
rsync -a /mnt/ iso/
umount /mnt
Depending on the version of syslinux, there are special considerations what directory and the config name should be.
mkdir iso/syslinux
cp /nix/store/hash-syslinux-6.03/share/syslinux/isolinux.bin iso/syslinux/syslinux.bin
cp /nix/store/hash-syslinux-6.03/share/syslinux/vesamenu.c32 iso/syslinux/
with syslinux v6.03 you also need to copy these files:
cp /nix/store/hash-syslinux-6.03/share/syslinux/ldlinux.c32 iso/syslinux/
cp /nix/store/hash-syslinux-6.03/share/syslinux/libcom32.c32 iso/syslinux/
cp /nix/store/hash-syslinux-6.03/share/syslinux/libutil.c32 iso/syslinux/
[root@nixos:~]# cat iso/loader/entries/nixos-livecd.conf
title NixOS LiveCD
linux /boot/bzImage
initrd /boot/initrd
options init=/nix/store/y606cp5rf75kfz8g36dcyaki2is79kcm-nixos-14.12.335.676e8d7/init root=LABEL=NIXOS_ISO boot.shell_on_fail loglevel=4
[root@nixos:~]# nano -w iso/syslinux/syslinux.cfg
[root@nixos:~]# cat iso/syslinux/syslinux.cfg
UI vesamenu.c32
PROMPT 1
TIMEOUT 50
DEFAULT nixos
SAY Now booting the kernel from SYSLINUX...
LABEL nixos
KERNEL /boot/bzImage
APPEND ro initrd=/boot/initrd init=/nix/store/y606cp5rf75kfz8g36dcyaki2is79kcm-nixos-14.12.335.676e8d7/init root=LABEL=NIXOS_ISO boot.shell_on_fail loglevel=4
If you look at nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
, the efi.img was created without a label. It is crucial to set any label but not equal to NIXOS_ISO
as we will generate ISO with this label -V NIXOS_ISO
later
[root@nixos:~]# mlabel -s -i iso/boot/efi.img
Volume has no label
[root@nixos:~]# mlabel -i iso/boot/efi.img ::EFIBOOT
[root@nixos:~]# mlabel -s -i iso/boot/efi.img
Volume label is EFIBOOT
Without this label, on UEFI boot, stage1
can’t mount the root device which is necessary for stage2
boot process to continue. However it is possible to workaround this by modifying kernel argument manually on boot to root=/dev/sda1
OR root=UUID=2015-02-03-10-11-46-00
OR root=/dev/disk/by-uuid/2015-02-03-10-11-46-00
instead of the default root=LABEL=NIXOS_ISO
genisoimage -o nixos-live-usb-uefi.iso -V NIXOS_ISO -R -b syslinux/syslinux.bin -c .boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot iso/
isohybrid --uefi nixos-live-usb-uefi.iso
Download OVMF binary. It enables UEFI firmware for QEMU and KVM so that you can test your ISO before writing it on your USB stick.
qemu-system-x86_64 -enable-kvm -cdrom nixos-live-usb-uefi.iso
qemu-system-x86_64 -enable-kvm -bios ./OVMF.fd -cdrom nixos-live-usb-uefi.iso
qemu-system-x86_64 -enable-kvm -hda nixos-live-usb-uefi.iso
qemu-system-x86_64 -enable-kvm -usb -usbdevice disk:nixos-live-usb-uefi.iso
qemu-system-x86_64 -enable-kvm -bios ./OVMF.fd -hda nixos-live-usb-uefi.iso
qemu-system-x86_64 -enable-kvm -bios ./OVMF.fd -usb -usbdevice disk:nixos-live-usb-uefi.iso
As -usb
runs very slow, I intentionally specified both -hda
and -usb
because in most of cases if -hda
boots then -usb
also boots.
Now it’s time to write your USB-bootable image onto your USB stick (in my case it was accessible at /dev/sdb
)
Be very careful using following commands, do not to overwrite any of your other devices!
[root@nixos:~]# cat nixos-live-usb-uefi.iso > /dev/sdX
[root@nixos:~]# echo 3 > /proc/sys/vm/drop_caches ; sync
[root@nixos:~]# udisksctl power-off -b /dev/sdb
Now you can try booting with UEFI.
If you will see similar error as this one, then all you have to do is to disable Secure Boot from your BIOS options, but keep UEFI enabled. If you really want to have Secure Boot then see this for an overview.
Secure Boot
Image failed to verify with *ACCESS DENIED*.
Press any key to continue.
If you wish, you can create/modify EFI partition on your own as follows
dd bs=2048 count=5120 if=/dev/zero of="iso/boot/efi.img"
mkfs.vfat -n "EFIBOOT" "iso/boot/efi.img"
mcopy -svi "iso/boot/efi.img" iso/efi iso/loader ::
mmd -i "iso/boot/efi.img" boot
mcopy -v -i "iso/boot/efi.img" iso/boot/bzImage ::boot/bzImage
mcopy -v -i "iso/boot/efi.img" iso/boot/initrd ::boot/initrd
[root@nixos:~]# blkid iso/boot/efi.img
iso/boot/efi.img: SEC_TYPE="msdos" LABEL="EFIBOOT" UUID="98D2-735E" TYPE="vfat"
[root@nixos:~]# blkid nixos-live-usb-uefi.iso
nixos-live-usb-uefi.iso: UUID="2015-02-03-10-11-46-00" LABEL="NIXOS_ISO" TYPE="iso9660" PTUUID="42719253" PTTYPE="dos"
Using this method you don’t have to run isohybrid --uefi
command
[root@nixos:~]# xorriso -as mkisofs -o nixos-live-usb-uefi.iso -V NIXOS_ISO -R -b syslinux/syslinux.bin -c .boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -isohybrid-mbr /nix/store/hash-syslinux-6.03/share/syslinux/isohdpfx.bin -eltorito-alt-boot -e boot/efi.img -no-emul-boot -isohybrid-gpt-basdat iso/