BootISO
- 7 Devlogs
- 16 Total hours
Boot ISO images from UEFI, without burning them to a USB stick.
Like Ventoy, but small as small gets, and Free as in Freedom.
Boot ISO images from UEFI, without burning them to a USB stick.
Like Ventoy, but small as small gets, and Free as in Freedom.
I did a lot of research regarding the error from two devlogs ago. The Linux initrd tries to mount the disc drive to finish booting. However, there is no disc drive… There is a way to pass ramdisks from UEFI to Linux: The NVDIMM Firmware Interface Table (NFIT) can store entries pointing to ramdisks in reserved memory areas. And the Linux kernel includes a driver for this! The nfit modules creates device files at /dev/pmem*. Unfortunately, the Arch ISO doesn‘t seem to ship that module, or I‘ve run into a severe misunderstanding of the protocol. I really don‘t want to give up, and there must be a way to do this (Ventoy and iPXE (mostly) work), but I couldn‘t find it. Stardance is coming to an end. If you know how NFIT works, or how Ventoy does it, PLEASE tell me!
I added a builder to the flake, to build the image without entering the devshell. I also added a builder to automatically create a release archive containing BootISO, an ISO9660 driver and the UEFI Shell. There is also now a README with instructions on how to run bootiso, and a file with license notices for my dependencies.
The ramdisk is now mounted using another SimpleFileSystem. However, this comes with an external dependency on an ISO9660 driver, which must be loaded before bootiso.efi is launched. Maybe I can automate that too.
But yes, the ISO correctly loads its bootloader, and I get to the GRUB menu. Sadly, once Linux is loaded, there are errors about a missing fd0 device, which is probably one of the harder parts of this project (if it wasn’t hard enough up until now).
This is a small fix with a big effect: I forgot to initialize the DevicePath-pointer-pointer when registering the ramdisk. I now instead create a mutable reference of a pointer, which is initialized by Rust and automatically converted to a pointer by the FFI. And, lo and behold: The image loads (slowly…), and the RAM disk is mounted.
I also got QEMU to work again, the default behavior did not give the VM enough RAM. It now gets 2G, which should be enough for both the RamDisk and Arch. Just, don’t select copytoram.
I can now successfully read the file from disk into RAM!
Instead of uefi::fs, I again use the SimpleFileSystem protocol directly.
This is so I can allocate the buffer myself using allocate_pages, bypassing the heap. This unfortunately introduces another unsafe block, but that’s a small price to pay.
After that, the file also successfully reads into RAM. read contains logic to read in 1KiB blocks, to bypass bugs in some firmwares.
Next stop: Mounting the RAM Disk, using my self-made FFI wrapper.
Currently, it returns EFI_INVALID_PARAMETER, meaning that one of the parameters is NULL, for some reason.
In the last two and a half hours, I wrote my own wrapoer for the Ram Disk protocol.
The uefi crate doesn’t support this protocol yet, so I had to hack together my own support.
Now, it for some reason can’t find the LoadedImage handles… but that is something I will fix after lunch.
I started building BootISO, an EFI application to boot ISO images from GRUB/rEFInd, the EFI shell, or (on some systems and probably not really viable), the Boot Options menu.
Currently, it opens a file handle to an ISO file, which in further development will be copied to a ramdisk, which can then hopefully be used for booting. Unfortunately, neither OVMF nor my laptop seem to support Simple File System, so I’ll need to check how to load the file instead.
Up to there, there aren’t any errors, so I feel quite confident, although a debugger might end up coming in handy …
I’ve gotten used to the architecture of the UEFI crate by now, which should probably speed up development and reduce AI usage further along.
(edit: it turns out I accidentally used the LoadedImage handle to initialize SimpleFileSystem 🤦)