What is all this about?
I was looking for a way to boot directly from a ZFS-Root pool in order to include kernel and initramfs into snapshots for easy rollback. I know there is GRUB2 which has ZFS read-only capabilities but its “bloated” and thus pretty slow on boot and ain’t nobody got time for that…
Another solution would have been rEFInd which allows loading drivers from the ESP partition. There is a lot of available drivers provided by Pete Batard’s EfiFs. Unfortunately trying this always featured a bunch of driver-related errors claiming the location it’s reading is corrupted, followed by loading the vmlinuz image with an empty string handed over to the ZFS target dropping me into emergency shell. So dead end here too.
I eventually got curious about EFISTUB booting so I fired up an EFI shell and tried loading the driver directly (this is also found on the driver website):
\> fs0:
fs0:\> load \path\to\driver\zfs_x64.efi
Success! Now we need to load the kernel and add a few parameters (found in ArchWiki):
fs0:\> \vmlinuz-linux zfs=<poolname> rw initrd=/initramfs-linux.img
And a few seconds later it successfully loaded Arch Linux on ZFS, allowing me to login.
Okay, it works but this is super clunky and not automated in the slightest. I want this to be a seamless experience.
Attempt #1 - Using a script:
I put the above commands into a little script archzfs.nsh
and saved it to the ESP. Then I generated a boot entry using efibootmgr
:
# efibootmgr --create --disk /dev/sdc --part 1 --gpt --label "Arch Linux ZFS" --loader \archzfs.nsh
Which again worked in EFI shell however any attempt to boot it automatically ended in skipping the entry and booting the next OS on another drive. Actively choosing it by pressinf ‘F2’ and navigating through the BIOS didn’t work either (it flickered briefly but nothing happened).
Attempt #2 - BIOS modding:
Disclaimer: This is dangerous with a tendency to brick your motherboard. Do NOT do this unless you know what you are doing!
The necessary tools and instructions are available on Pete Batard’s Github Wiki and the Win-Raid Forum.
What I am doing here is the following:
- Turning the .efi driver into a BIOS compatible .ffs file using FFSTool
- Downloading your BIOS firmware from your motherboard manufacturer’s website
- Opening the firmware using UEFITool and search for “DXE” (I recommend looking very closely at the Win-Raid guide)
- Find the undermost DXE driver entry and insert your .ffs driver after it
- Save this and flash it to your motherboard
As I am using an Asus board which has Asus’ Flashback it was of pretty much no danger to me as I could replace the firmware as long as the board is powered. Your mileage may vary so again, do NOT try this unless you know what you are doing.
The result:
The motherboard posted successfully and entering drivers
in EFI shell shows the ZFS driver is loaded - this allows the command
fs0:\> \vmlinuz-linux zfs=tank rw initrd=/initramfs-linux.img
to work without needing to specifically load the driver as it’s now part of the firmware.
However, booting by EFISTUB still does not work and results in brief flickering and nothing else as described before. I used this command and a bunch of variations of it to generate the entry:
# efibootmgr --create --disk /dev/sdc --part 1 --gpt --label "Arch Linux Native-ZFS" --loader \vmlinuz-linux --unicode "zfs=tank rw initrd=/initramfs.img"
I couldn’t get it to work but still I have a feeling of being very close to the solution. Since I ran out of ideas I welcome your input on this topic. Maybe someone can figure it out or points to the simple error I am doing.
Thanks for reading!