This post is about some of the ways in which an operating system / kernel can be made to boot as a UEFI application image (through UEFI firmware).
To be clear, let’s make sure we have our definitions straight:
- UEFI firmware: The vendor firmware itself, which may or may not support legacy BIOS options. On the OSDev side, we won’t really have control over this. For emulation, I’ll be using TianoCore’s OVMF (OvmfPkgX64) specifically. More setup instructions here.
- UEFI application image: A relocatable
PE/COFFexecutable file which the UEFI firmware loads through a FAT partition, usually the file
/EFI/BOOT/BOOTX64.EFIon the filesystem.
With RTEMS, we use a cross-compiler toolchain (for eg.
instead of the host computer’s
gcc). The toolchain is built automatically by
the RTEMS Source Builder (RSB),
which does cool things like pull in a release version of the various tools,
backports patches that the RTEMS community may need (that are not in a release
version yet), and compiles the entire toolchain. These tools (
etc.) are then used to compile all of the RTEMS kernel, link the kernel to user
applications, the testsuite, etc.
gnu-efi, then use
objcopy to convert ELF to PEI
- Build an ELF64 shared library including an
- Link it with
gnu-efi’s libraries and
x86_64-rtems5-objcopydoesn’t support the
pei-x86-64target at the moment, but this is easy to add with this patch to bfd
- Put the PE image file on a FAT partition. Here’s a quick script I used.
- Boot the PE image with UEFI firmware now
- ALL GLORY TO THE HYPNOTOAD!
I’ve tested this process with a “hello world” UEFI image using the
x86_64-rtems5-* toolchain and confirmed it works in QEMU.
- Use the RSB with my bfd patch to add the
x86_64-rtems5-objcopy. (I’ll try to have this upstreamed based on discussions on the RTEMS developers mailing list.)
- Download gnu-efi
make CC=x86_64-rtems5-gcc OBJCOPY=x86_64-rtems5-objcopy ARCH=x86_64within the project
- Run the
make-img.shscript with the the path to the
t.efitest file (within
gnu-efi-3.0.8/x86_64/apps/at the moment)
qemu-system-x86_64 --bios /path/to/OVMF.fd -net none -cpu qemu64 -drive file=/path/to/uefi.img,if=ide)
Note: This will involve making
gnu-efi a part of the RTEMS build
process. I’m not sure where this will fit in yet and if there might be license
incompatibility issues here.
Use a tool such as
The iPXE bootloader includes a utility that can convert an existing ELF to an
EFI bootable image. I haven’t explored this option much since the one using
objcopy seemed more standardized and one that would need less maintenance
overall to me. There would also be licensing considerations, and we would have
to confirm that the tool runs on all hosts that RTEMS intends to support for
Use an assembly-generated PE header for a “chimera” ELF?
wimboot project associated with
iPXE includes a
prefix.S file which
seems to generate the PE header
in assembly, allowing us to possibly create a chimeric file which can act like a
PE - I’m not sure about the differences between ELF and PE and how compatible
they are, so I can’t speak to how viable this method is, but it seems like
something that has worked for some in the past; namely the Linux kernel uses a
technique called the EFI boot stub (or EFISTUB for short), using a
file to masquerade itself as a PE/COFF
is documented here and
on the Arch Wiki here as well.
Given the possible license incompatibilities with the RTEMS project and the need to shave a PE file-format yak, I’m leaning away from this method.
P.S. - I’d like to say thanks to Chris Johns for helping me discover that the last 2 options were even a possibility. Thank you! :D
Conclusion: I’m leaning towards the first method, but I’d love to hear what you think about the options I’ve laid out, and for any others I may have missed. Hit me up! The RTEMS mailing list discussion thread for this blog post is here.