Closed diekmann closed 9 months ago
I will not merge this. It's specific to your testing environment and even the comment mostly describes your situation. All things don't need to be merged upstream, it's still ok to keep them locally.
To make your testing experience smoother, you can copy the .efi file to efi_test/EFI/boot/bootx64.efi
which is loaded by default, or you can create a UEFI shell script efi_test/startup.nsh
with contents FS0:\EFI\HackBGRT\loader.efi
. Tested on Arch Linux with QEMU 8.1.2 and edk2-ovmf 202308.
Howdy Metabolix, thanks a lot for taking the time to look at this PR! I totally understand that this is your repo and that you don't want to merge a PR which may be opinionated towards my system.
I tried building your software. It compiled, but it always crashed for me. In qemu, with this X64 Exception Type - 06(#UD - Invalid Opcode) and with just a blank screen on real hardware. Cross-compiling an UEFI application with w64-mingw32
seems to be a rather uncommon choice and I had quite a lot of fun debugging why I could not get this running on my system. 😄
On my system (ubuntu 22.04 on wsl on win 11), it looked like the gnu-efi w64-mingw32
compiled, but produced a buggy library which messed up the calling convention. I finally found this via printf
debugging and when I realized that specifying my own uefi_call_wrapper
made the thing work. My uefi_call_wrapper
was basically just passing through the function call without adapting calling convention, since w64-mingw32
already uses the correct calling convention. I fund that my gnu-efi version 3.0.15 did not compile correctly with mingw, because the mingw MAKEFILE file choked on the mingw gcc version, but did not abort compilation.
I have modified the HackBGRT Makefile
such that it vendors gnu-efi as a git submodule and passes the compiler options to make this compile. The -DGNU_EFI_USE_MS_ABI
for both gnu-efi and HackBGRT is the important option which makes sure both use the default calling convention.
If I find the time to cleanup all these custom hacks I added and create a clean branch, would you be interested in a PR which vendors gnu-efi as a submodule to help compiling HackBGRT more hermetically?
Thanks for the detailed explanation. Funny, my problem is quite the opposite: I can't make a working binary with the native (Linux) gnu-efi linker scripts and objcopy magic, and that's why I ended up using MinGW, which works great. In the long run, I would prefer to switch to the native GCC. Another interesting alternative is to rewrite the whole thing in Rust, which seems to produce EFI working binaries out-of-the-box with the uefi-rs
crate.
Meta: I think we can close this PR, this discussion is now basically off-topic chat 😄 Thanks for your explanations 💟
Heh, interesting. I once played with the objcopy magic to build an UEFI application and even linked a Rust library into it. I borrowed heavily from shim. Limitations: I only used gnu-efi headers and I did not link against the gnu-efi lib.
While debugging my MinGW issues, I found this interesting article: Goodbye Gnu-EFI! While I haven't tried it, it looks like clang is a sweet spot for a compiler: It can natively compile to the PE Windows style (no cross-compilation) and clang and rust work together nicely. For some architectures, folks even claim that cross-language link-time-optimization is working between the two. When I tried 2.5 years ago for the wasm target thoug, it did not work. But wasm limitations do not apply here.
Haha, I reopened this by accident. Thanks for your useful research. I've now switched to Clang, included gnu-efi as a submodule to get the headers but also reimplemented some functions to avoid actually building and linking the whole gnu-efi. Maybe it now works for you too?
I think I got a working bootx64.efi
compiled with your clang
setup at 7ccdcc4a7706e11753a387f5f7424c885d855bf7. 👍
Very smooth 👍
I did not test the csharp or shim or signing part, I just took the compiled bootx64.efi
and copied it to my working 2.1.0 branch and installed it.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.3 LTS
Release: 22.04
Codename: jammy
$ clang --version
Ubuntu clang version 14.0.0-1ubuntu1.1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
and
lld-14 (1:14.0.0-1ubuntu1.1)
on wsl on win 11
Selecting the loader.efi in OVMF manually is not super convenient, but at least it is a reproducible way to run the compiled EFI binary without rebooting the whole machine.
I still cannot produce a working binary on my system, but at least, this Makefile target allows me to fail faster.
Tested on vanilla Windows 11 with WSL Ubuntu and gnu-efi 3.0.11 and qemu 6.2.0.