Converting my Raspberry Pi 4B's to boot with UEFI

I don't know if there's an especially good reason to do this, but you can, and I wanted to. It kind of makes the Raspberry Pi be more like a normal computer. I guess that's cool.

I've got three Raspberry Pi 4B's that I bought several years ago. They run NixOS, like everything else in my homelab. That's relevant because some of these steps will be specific to that setup.

So let's get into how it's done.

Update the EEPROM

The UEFI firmware for the Raspberry Pi 4 recommends being on the latest EEPROM. That's not too hard to do:

# nix shell nixpkgs#raspberrypi-eeprom
# mount /dev/disk/by-label/FIRMWARE
# BOOTFS=/mnt FIRMWARE_RELEASE_STATUS=latest rpi-eeprom-update -d -a

After that, rebooting should apply the update.

Install the new firmware on the SD card

Power off the Raspberry Pi and sticks its SD card in another Linux machine. I used my M2 MacBook Pro, which will have benefits later due to also being an aarch64 machine.

=> Raspberry Pi 4 UEFI Firmware Images

Grab the latest release of the UEFI firmware. Before copying its contents to the firmware partition on the SD card, I copied the old firmware to my computer as a backup. Now clear out the firmware drive and replace it with the contents of the archive of the new firmware.

Optional: Test that the new firmware boots

At this point, you won't be able to boot for real, since there's no bootloader installed, but you can at least check if the firmware works by putting the SD card back in the Raspberry Pi and powering it on.

It should show a Raspberry Pi logo and then offer you the option of setup, shell, or boot. If you let it try to boot, it'll try to do PXE stuff and eventually fail to find anything to boot. That's fine and good.

Now put the SD card back in your other computer.

Fix the partitions

To boot with UEFI, you'll need a reasonably sized FAT partition to use as the EFI system partition (ESP). In theory, the existing firmware partition could serve as this, but if yours is anything like mine, it's way too small for that. Instead, you'll need a new partition. You probably also need to fix the partition table to be GPT, or installing systemd-boot later will complain. Might as well kill two birds with one stone.

First, shrink the existing ext4 filesystem by about 1G to make room for the new partition. Then use gdisk to convert the partition table. And then you can use whatever tool you prefer to shrink the partition to match the filesystem, and make the new ESP partition.

# nix shell nixpkgs#e2fsprogs nixpkgs#gptfdisk
# e2fsck -f /dev/sda2
# resize2fs /dev/sda2 115G
# gdisk /dev/sda
# cfdisk /dev/sda

Now you should have a third partition. Don't forget to format it.

# mkfs.fat -F 32 /dev/sda3

With that, the SD card should be ready to receive a new bootloader.

Mount the filesystems

This process is going to be very similar to what happens when you install NixOS to begin with. So similar to that, mount the filesystems under /mnt:

# mkdir -p /mnt
# mount /dev/sda2 /mnt
# mount /dev/sda3 /mnt/boot

The firmware partition doesn't need to be mounted, but the root FS and ESP do.

Update the NixOS config

It's time to replace the existing bootloader in the machine's NixOS config with systemd-boot. So you can take lines like this:

boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;

And replace them with:

boot.loader.systemd-boot.enable = true;

Don't we still need to disable GRUB? No, because the systemd-boot module does that already when you enable it. No, I don't know why the generic-extlinux-compatible one doesn't do that. Probably just an oversight?

You're not quite done yet. You also need to add a fileSystems entry for /boot, to mount the ESP that now exists. Otherwise, when you update your NixOS config, you won't be able to add new generations to the boot loader.

fileSystems."/boot" = {
  device = "/dev/disk/by-uuid/DEAD-BEEF";
  fsType = "vfat";
  options = [
    "fmask=0077"
    "dmask=0077"
  ];
};

You can "ls -l /dev/disk/by-uuid" to find which link is pointing to that partition. There's probably a more direct way but this is what I usually do.

Build the NixOS config

With the NixOS config updated, it's time to build it. Note that at this point in the process, the Raspberry Pi SD card is not bootable: it has UEFI firmware but no boot loader installed yet. So you have two options for this step:

I'm doing the second one, so that's what I'm going to describe. If you're using flakes, maybe that looks something like:

$ nix build .#nixosConfigurations.my-rpi.config.system.build.toplevel

I don't use flakes and have my own weird tooling so I did something different, but as long as the toplevel ends up linked at ./result, it's all the same from here.

Copy the NixOS config to the SD card

With the config built, it needs to get copied to the Nix store on the SD card. Thankfully, that's quite easy:

# nix copy --to /mnt ./result --no-check-sigs

Note that it's /mnt, not /mnt/nix/store: the /nix/store is added automatically.

Add the new generation and install the bootloader

Almost there. Now that the new generation is present on the SD card's store, use nix-env to set it as the current generation for the system profile.

# nix-env --store /mnt --profile /mnt/nix/var/nix/profiles/system --set $(readlink ./result)

And finally, use nixos-enter to activate the new generation using the boot goal:

# NIXOS_INSTALL_BOOTLOADER=1 nixos-enter --root /mnt -- /run/current-system/bin/switch-to-generation boot

If you've done everything right, this should have completed without error and populated /mnt/boot with a bunch of stuff. Now you can unmount the SD card and put it back in the Raspberry Pi!

# umount /mnt/boot
# umount /mnt

Boot the thing!

When you power on the Raspberry Pi, it should be able to find systemd-boot and boot your system through there. If you did this process from another machine like I did, then the SD card is probably still the lowest boot option, since the systemd-boot install wasn't able to mess with EFI variables to make sure it was the default option. So you'll probably want to go into the setup of the firmware and fix the ordering manually, unless you really enjoy waiting for PXE boot to fail first.

If it boots, you're done! It should now behave pretty much like a normal PC in terms of booting. Enjoy the spoils of your success: your Raspberry Pi now functions basically the same as before, but something intangible feels different, maybe better.

If you have 4GB+ of RAM in your Pi, you probably want to go into the firmware setup and disable the setting that limits it to 3GB. There may be other things you want to tweak too. Have fun!

Proxy Information
Original URL
gemini://midna.dev/posts/2026/07-04-booting-raspberry-pi-4-with-uefi.gmi
Status Code
Success (20)
Meta
text/gemini;lang=en-US
Capsule Response Time
25.987154 milliseconds
Gemini-to-HTML Time
0.63607 milliseconds

This content has been proxied by September (UNKNO).