UEFI Invalid Opcode
Posted: Mon Dec 30, 2024 12:52 pm
Happy New Year's everyone! I've been experimenting with UEFI via QEMU + OVMF. I put together my own EFI header's and starting putting together simple unit tests to validate said headers. Outputting to the console works great, but I've found that the EFI 'stall' instructions causes a #UD fault.
https://uefi.org/specs/UEFI/2.10_A/07_S ... ices-stall
Looking for help troubleshooting. Building Arch Linux 6.11, with QEMU version 9.1.0, and clang 19.1.0
❯ clang --version
clang version 19.1.0
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/eatmorecookies/opt/llvm19.1.0/bin
The OVMF_* files in the command below came from the Arch install.
Here are the relevant compile and link flags from the Makefile. I've googled clang with EFI and tried variations of this but nothing has helped. What I'm using below seems to be the minimum that everyone agrees should be included.
And here is the actual code:
Removing the call to the Stall command allows the code to run successfully.
Also, thinking it may be a mistake in my EFI headers, I substituted another set of EFI headers I found online but got the same result.
Thanks for any assistance!
https://uefi.org/specs/UEFI/2.10_A/07_S ... ices-stall
Looking for help troubleshooting. Building Arch Linux 6.11, with QEMU version 9.1.0, and clang 19.1.0
❯ clang --version
clang version 19.1.0
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/eatmorecookies/opt/llvm19.1.0/bin
The OVMF_* files in the command below came from the Arch install.
Code: Select all
> qemu-system-x86_64 \
-drive if=pflash,format=raw,unit=0,readonly=on,file=OVMF_CODE.fd \
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd \
-drive file=uefi.img,if=ide \
-net none \
-display curses \
-nographic
Code: Select all
WARNING: Image format was not specified for 'uefi.img' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
BdsDxe: loading Boot0001 "EFI Internal Shell" from Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
BdsDxe: starting Boot0001 "EFI Internal Shell" from Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
UEFI Interactive Shell v2.2
EDK II
UEFI v2.70 (EDK II, 0x00010000)
Mapping table
FS0: Alias(s):HD0a1:;BLK1:
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)/HD(1,GPT,CBF14CDC-0386-4457-89E9-A0ED9DE5BEF3,0x800,0x16614)
BLK0: Alias(s):
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
BLK2: Alias(s):
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
Press ESC in 1 seconds to skip startup.nsh or any other key to continue.
Shell> fs0:
FS0:\>bootx64.efi
Executing stall instruction...
!!!! X64 Exception Type - 06(#UD - Invalid Opcode) CPU Apic ID - 00000000 !!!!
RIP - 00000000000B0000, CS - 0000000000000038, RFLAGS - 0000000000010247
RAX - 0000000006B15160, RCX - 0000000000000032, RDX - 0000000000000000
RBX - 0000000000000000, RSP - 0000000007EFA458, RBP - 0000000007EFA500
RSI - 0000000000000007, RDI - 00000000063C9418
R8 - 0000000000000000, R9 - 0000000007EF98DF, R10 - 0000000007EF98C0
R11 - 0000000000000260, R12 - 00000000063C9B98, R13 - 0000000007EFA568
R14 - 0000000007EFA6E8, 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 - 0000000007EFA0B0
!!!! Can't find image information. !!!!
Code: Select all
CC = clang
CFLAGS = -I ./include -target x86_64-unknown-windows -mno-red-zone -ffreestanding -fno-stack-protector
LD = lld-link
LDFLAGS = -entry:efi_main -subsystem:efi_application -dll
obj/boot/bootx64.efi: obj/boot/boot.o obj/boot/check_sum.o
$(LD) $(LDFLAGS) $^ -out:$@
obj/boot/boot.o: src/boot/boot.c
mkdir -p obj/boot
$(CC) $(CFLAGS) -c $< -o $@
obj/boot/check_sum.o: src/boot/check_sum.c
mkdir -p obj/boot
$(CC) $(CFLAGS) -c $< -o $@
Code: Select all
#include "efi/base_types.h"
#include "efi/system_table.h"
#include "check_sum.h" // printf definition
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *console;
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *table)
{
console = table->ConOut;
printf(u"Executing stall instruction...\r\n");
table->BootServices->Stall(50); // microseconds
printf(u"Stall complete...\r\n");
return EFI_SUCCESS;
}
Also, thinking it may be a mistake in my EFI headers, I substituted another set of EFI headers I found online but got the same result.
Thanks for any assistance!