Page 1 of 1

uefi_call_wrapper() calls an invalid opcode

Posted: Thu May 02, 2024 9:09 am
by BlazingBlast
Every call to uefi_call_wrapper() I have tried to make, has resulted in RIP = 0xB0000, and an Invalid opcode exception.

The full error message is:

Code: Select all

!!!! X64 Exception Type - 06(#UD - Invalid Opcode)  CPU Apic ID - 00000000 !!!!
RIP  - 00000000000B0000, CS  - 0000000000000038, RFLAGS - 0000000000000A86
RAX  - 0000000007F00743, RCX - 0000000007EFA330, RDX - 000000000636B470
RBX  - 0000000000000000, RSP - 0000000007EFA308, RBP - 0000000007EFA340
RSI  - 00000000063E9C98, RDI - 0000000007F00743
R8   - 0000000000000000, R9  - 0000000007EF9B4F, R10 - 0000000007EF9B30
R11  - 0000000000000260, R12 - 00000000063E9C98, R13 - 00000000075EC018
R14  - 0000000000000000, R15 - 00000000062BA740
DS   - 0000000000000030, ES  - 0000000000000030, FS  - 0000000000000030
GS   - 0000000000000030, SS  - 0000000000000030
CR0  - 0000000080010033, CR2 - 0000000000000000, CR3 - 0000000007801000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 00000000075DC000 0000000000000047, LDTR - 0000000000000000
IDTR - 0000000007249018 0000000000000FFF,   TR - 0000000000000000
FXSAVE_STATE - 0000000007EF9F60
!!!! Can't find image information. !!!!
My code can be found at https://github.com/Blazing-Blast/os64/

Does anyone know why this happens, and how to prevent it?

Re: uefi_call_wrapper() calls an invalid opcode

Posted: Thu May 02, 2024 9:31 pm
by Octocontrabass
BlazingBlast wrote:Every call to uefi_call_wrapper() I have tried to make,
You shouldn't be trying to make any calls to uefi_call_wrapper(), that's a leftover from before GCC supported the function attribute to switch between the two x64 ABIs.
BlazingBlast wrote:My code can be found at https://github.com/Blazing-Blast/os64/
There's no such thing as a UEFI OS. You can have a UEFI bootloader in your OS, but the rest of your OS shouldn't depend on UEFI for anything.

Also, you don't need startup.nsh, just name your bootloader the default for your target CPU architecture (e.g. efi/boot/bootx64.efi for x64) and it'll boot.

Also, you don't need to build a disk image, QEMU can generate FAT32 disk images on-the-fly from a directory of files.
BlazingBlast wrote:Does anyone know why this happens, and how to prevent it?
I would guess it's happening because the GNU-EFI build process is a disgusting hack and disgusting hacks tend to be fragile.

You can prevent it by using a cross-compiler that targets Windows. You can steal the necessary UEFI headers from GNU-EFI (or elsewhere), or write your own headers mostly by copy/pasting the UEFI specification.

If you really want to use GNU-EFI, share your binaries so I can examine them.

Re: uefi_call_wrapper() calls an invalid opcode

Posted: Fri May 03, 2024 3:56 am
by BlazingBlast
Octocontrabass wrote:QEMU can generate FAT32 disk images on-the-fly from a directory of files.
Thank you for the tip. What command line options would I use for this? I've figured it out myself:

Code: Select all

-hdb fat:rw:$(EFIROOT_DIR)
Octocontrabass wrote:You can prevent it by using a cross-compiler that targets Windows.
Can I use the mingw-w64 compiler my distro ships, or do I need to compile my own?
The distro's compiler seems to work.
Octocontrabass wrote:You can steal the necessary UEFI headers from GNU-EFI (or elsewhere), or write your own headers mostly by copy/pasting the UEFI specification.
Works fine, but functions like Print() or StatusToString() aren't linked. I assume that this is because they are part of GNU-UEFI, but how do I go about printing these things? Do I need to write my own string formatting implementation?

Re: uefi_call_wrapper() calls an invalid opcode

Posted: Fri May 03, 2024 11:36 am
by Octocontrabass
BlazingBlast wrote:

Code: Select all

-hdb
Why the second hard disk instead of the first?
BlazingBlast wrote:The distro's compiler seems to work.
Indeed it does, though you may need to pass some additional parameters to get everything to work correctly. Here's all the parameters my build script passes to MinGW-w64 GCC when building a 64-bit binary:

Code: Select all

-ffreestanding -nostdlib -mno-stack-arg-probe -mgeneral-regs-only -fno-asynchronous-unwind-tables -pie -s -Wl,--subsystem,10 -march=x86-64 -mtune=generic -Wall -Os -flto -fno-ident -e efi_main
Unfortunately I didn't take notes on why I added each parameter; some of them might only be there because they fixed a problem with 32-bit binaries or with Clang. (Some are just to make the binary smaller.)
BlazingBlast wrote:I assume that this is because they are part of GNU-UEFI, but how do I go about printing these things? Do I need to write my own string formatting implementation?
Yeah, with bare UEFI there's no string formatting, just printing. Fortunately, doing string formatting without the C standard library is a common enough problem that there are plenty of ready-made solutions you can easily adapt to UEFI if you don't feel like writing your own from scratch.