[SOLVED] EFI App: Can't open file in write MODE

Programming, for all ages and all languages.
Post Reply
NathanLAAS
Posts: 7
Joined: Fri Mar 14, 2025 1:58 am

[SOLVED] EFI App: Can't open file in write MODE

Post by NathanLAAS »

Hey!

I'm new to EFI applications and tried to open a file (in the EFI partition) to write on it. To do so I tried to follow https://wiki.osdev.org/Loading_files_under_UEFI which works for the read mode case but crashes on write.
I'm stuck with an issue as if I wrote on "ROM" (I don't know at all if it's that tho...).

I'm using gnu-efi and my C file is:

Code: Select all

#include <efi.h>
#include <efiapi.h>
#include <efilib.h>

EFI_FILE_HANDLE GetVolume(EFI_HANDLE image)
{
  EFI_LOADED_IMAGE *loaded_image = NULL;                  /* image interface */
  EFI_GUID lipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;      /* image interface GUID */
  EFI_FILE_IO_INTERFACE *IOVolume;                        /* file system interface */
  EFI_GUID fsGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; /* file system interface GUID */
  EFI_FILE_HANDLE Volume;                                 /* the volume's interface */

  /* get the loaded image protocol interface for our "image" */
  uefi_call_wrapper(BS->HandleProtocol, 3, image, &lipGuid, (void **) &loaded_image);
  /* get the volume handle */
  uefi_call_wrapper(BS->HandleProtocol, 3, loaded_image->DeviceHandle, &fsGuid, (VOID*)&IOVolume);
  uefi_call_wrapper(IOVolume->OpenVolume, 2, IOVolume, &Volume);
  return Volume;
}

EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
  InitializeLib(ImageHandle, SystemTable);
  EFI_FILE_HANDLE Volume = GetVolume(ImageHandle);
  CHAR16              *FileName = L"DATA.TXT";
  EFI_FILE_HANDLE     FileHandle;
  CHAR8       *AsciiBuffer = "hello";
  // UINTN       SizeBuffer = 5;
  
  /* open the file */
  uefi_call_wrapper(Volume->Open, 5, Volume, &FileHandle, FileName, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, NULL);

  /* close the file */
  uefi_call_wrapper(FileHandle->Close, 1, FileHandle);
  return EFI_SUCCESS;
}

When compiling with the

Code: Select all

UINTN SizeBuffer = 5;
commented I'm having the error below:

Code: Select all

BdsDxe: loading Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Master,0x0)
BdsDxe: starting Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Master,0x0)
!!!! X64 Exception Type - 06(#UD - Invalid Opcode)  CPU Apic ID - 00000000 !!!!
RIP  - 00000000062971B3, CS  - 0000000000000038, RFLAGS - 0000000000010A06
RAX  - 000000000628A018, RCX - 0000000007E8F740, RDX - 0000000007E8F740
RBX  - 0000000000000000, RSP - 0000000007E8F6B8, RBP - 0000000007E8F720
RSI  - 0000000007E8F740, RDI - 00000000062BDFB8
R8   - 0000000006287000, R9  - 8000000000000002, R10 - 0000000006A460B4
R11  - 0000000000000000, R12 - 000000000700B218, R13 - 00000000079EC018
R14  - 0000000000000000, R15 - 0000000006B85818
DS   - 0000000000000030, ES  - 0000000000000030, FS  - 0000000000000030
GS   - 0000000000000030, SS  - 0000000000000030
CR0  - 0000000080010033, CR2 - 0000000000000000, CR3 - 0000000007C01000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 00000000079DC000 0000000000000047, LDTR - 0000000000000000
IDTR - 000000000751B018 0000000000000FFF,   TR - 0000000000000000
FXSAVE_STATE - 0000000007E8F310
!!!! Find image based on IP(0x62971B3) (No PDB)  (ImageBase=0000000006279000, EntryPoint=000000000627C000) !!!!
When uncommenting this part, I'm left with a kvm crash:

Code: Select all

VNC server running on ::1:5900
KVM internal error. Suberror: 1
extra data[0]: 0x0000000000000000
extra data[1]: 0x0000000000000030
extra data[2]: 0x0000000000000584
extra data[3]: 0x0000000000000000
extra data[4]: 0x0000000000000000
extra data[5]: 0x0000000000000000
emulation failure
RAX=0000000000000000 RBX=0000000000000000 RCX=0000000000000004 RDX=0000000000000004
RSI=0000000000000004 RDI=0000000000000000 RBP=0000000007e8f720 RSP=0000000007e8f6a8
R8 =0000000006287000 R9 =8000000000000002 R10=0000000006a460b4 R11=0000000000000000
R12=000000000700b218 R13=00000000079ec018 R14=0000000000000000 R15=0000000006b85818
RIP=00000000000b0000 RFL=00010246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0038 0000000000000000 ffffffff 00a09b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT=     00000000079dc000 00000047
IDT=     000000000751b018 00000fff
CR0=80010033 CR2=0000000000000000 CR3=0000000007c01000 CR4=00000668
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
EFER=0000000000000d00
Code=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <ff> ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
I'm starting qemu with

Code: Select all

qemu-system-x86_64 -drive if=pflash,format=raw,file=OVMF.4m.fd -cdrom boot.img -cpu host -serial tcp::6666,server -s -accel kvm
and compiling with

Code: Select all

CFLAGS ?= -I../gnu-efi/inc -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args
LDFLAGS ?= -shared -Bsymbolic -L../gnu-efi/x86_64/lib -L../gnu-efi/x86_64/gnuefi -T../gnu-efi/gnuefi/elf_x86_64_efi.lds ../gnu-efi/x86_64/gnuefi/crt0-efi-x86_64.o
OBJCOPYFLAGS ?= -j .text -j .sdata -j .data -j .rodata -j .dynamic -j .dynsym  -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target efi-app-x86_64 --subsystem=10

.SILENT:

all: clean main

compilation: debug.c
	gcc $(CFLAGS) -c debug.c -o main.o

linking: compilation
	ld $(LDFLAGS) main.o -o main.so -lgnuefi -lefi

main: linking
	objcopy $(OBJCOPYFLAGS) main.so ../build/main.efi
(the compilation flags is taken from an OSDev page that I do not seem to find again)

I tried to start it out of qemu (from a "bare-bone" uefi shell) and it crashes so I don't think it's due to a kvm issue...

Could you help me please?

Nathan
Last edited by NathanLAAS on Thu Mar 20, 2025 4:16 am, edited 1 time in total.
Octocontrabass
Member
Member
Posts: 5721
Joined: Mon Mar 25, 2013 7:01 pm

Re: EFI App: Can't open file in write MODE

Post by Octocontrabass »

NathanLAAS wrote: Tue Mar 18, 2025 10:13 am

Code: Select all

!!!! X64 Exception Type - 06(#UD - Invalid Opcode)
Add "-mgeneral-regs-only" to your CFLAGS.
NathanLAAS wrote: Tue Mar 18, 2025 10:13 am

Code: Select all

RIP=00000000000b0000
Check return values. You might be calling through an invalid function pointer because you got an error when you were expecting a handle.

...Or it might be a problem with how you're building things. GNU-EFI is a disgusting pile of ugly hacks, but it does work if you use its build scripts instead of writing your own.
NathanLAAS wrote: Tue Mar 18, 2025 10:13 am(the compilation flags is taken from an OSDev page that I do not seem to find again)
Probably this one.
User avatar
zaval
Member
Member
Posts: 667
Joined: Fri Feb 17, 2017 4:01 pm
Location: Ukraine, Bachmut
Contact:

Re: EFI App: Can't open file in write MODE

Post by zaval »

sigh. For your own good, do not use that abomination, gnu-efi. There should be already UEFI headers, just headers, defining UEFI types, data structures and etc, no need for all these lame doodles put atop for no reason, I am sure, there are such, created by someone, or just write them on your own, it would be much less of work, than trying to use that abysmall mess, but most importantly, it will work and do it in the cleanest and most elegant way. Then what you did above would be as simple as:

Code: Select all

/* LIP of our image handle */
	Status = bs->OpenProtocol(ImageHandle, &gEfiLoadedImageGuid, &lip, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
	if(Status != EFI_SUCCESS){return YourExitFunction(Status, L"Some text");}

/* SFSP of the Home Volume */
	Status = bs->OpenProtocol(
			lip->DeviceHandle, &gEfiSimpleFileSystemGuid, &sfspHomeVolume, ImageHandle,
			NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL
		);
	if(Status != EFI_SUCCESS){return YourExitFunction(Status, L"Some text");}

/* Root Directory of the Home Volume */
	Status = sfspHomeVolume->OpenVolume(sfspHomeVolume, &fpHomeVolumeRoot);
	if(Status != EFI_SUCCESS){return YourExitFunction(Status, L"Some text");}
	
/* now, having the Home Volume root directory open, proceed to open whatever other dirs and files, you need */
Also, are you trying to write to cdrom? Anyway, the crash is due to the totally wrecked nature of gnu-efi, it obviously can't handle anything and jumps into random memory location. I can't get why people are so persistent on using such anti helping things.
ANT - NT-like OS for x64 and arm64.
efify - UEFI for a couple of boards (mips and arm). suspended due to lost of all the target park boards (russians destroyed our town).
NathanLAAS
Posts: 7
Joined: Fri Mar 14, 2025 1:58 am

Re: EFI App: Can't open file in write MODE

Post by NathanLAAS »

Thanks to both of you for your replies :)
Add "-mgeneral-regs-only" to your CFLAGS.
This doesn't change the output :/
Check return values. You might be calling through an invalid function pointer because you got an error when you were expecting a handle.
Which return value do you want me to check? The uefi_call_wrapper calls in GetVolume does not seems to return a status. Or are you referring to the ret value in the stack? I tried to add a stack chk guard but I'm having the kvm error... I'll try to do a step-by-step execution if it's possible.
GNU-EFI is a disgusting pile of ugly hacks, but it does work if you use its build scripts instead of writing your own.
Haha, maybe I should open an issue on their end if so.
Probably this one.
Yep. Thanks for the link!
I can't get why people are so persistent on using such anti helping things.
Well, I'm a noob trying to get into EFI Apps so when I'm reading
The biggest advantage of 'uefi_call_wrapper' is that doesn't matter what ABI your gcc is using, it will always correctly translate that into UEFI ABI.
from https://wiki.osdev.org/GNU-EFI I can only try it first :p
Also, are you trying to write to cdrom?
Exactly, that's what I'm trying to do.
Then what you did above would be as simple as:
I'm having an `EFI_INVALID_PARAMETER` error on the Load Image Protocol :/ Thought, tbh I tried using the boot services given by gnu-efi :roll:

I'll try to dig into this issue later on, If my answers gave you some idea of stuff to test don't hesitate to tell me ;)
NathanLAAS
Posts: 7
Joined: Fri Mar 14, 2025 1:58 am

Re: EFI App: Can't open file in write MODE

Post by NathanLAAS »

Oh... Just noticed that by changing

Code: Select all

  uefi_call_wrapper(Volume->Open, 5, Volume, &FileHandle, FileName, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, NULL);
to

Code: Select all

  uefi_call_wrapper(Volume->Open, 5, Volume, &FileHandle, FileName, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
The #UD disappears. The kvm error seems to be on the

Code: Select all

uefi_call_wrapper(FileHandle->Close, 1, FileHandle);
NathanLAAS
Posts: 7
Joined: Fri Mar 14, 2025 1:58 am

Re: EFI App: Can't open file in write MODE

Post by NathanLAAS »

Bruh... I spoke too fast, the #UD appears when commenting

Code: Select all

CHAR8       *AsciiBuffer = "hello";
while the SizeBuffer line doens't change anything this time...

Weird...
User avatar
eekee
Member
Member
Posts: 911
Joined: Mon May 22, 2017 5:56 am
Location: Kerbin
Discord: eekee
Contact:

Re: EFI App: Can't open file in write MODE

Post by eekee »

NathanLAAS wrote: Wed Mar 19, 2025 6:40 am
I can't get why people are so persistent on using such anti helping things.
Well, I'm a noob trying to get into EFI Apps so when I'm reading
The biggest advantage of 'uefi_call_wrapper' is that doesn't matter what ABI your gcc is using, it will always correctly translate that into UEFI ABI.
from https://wiki.osdev.org/GNU-EFI I can only try it first :p
If you have a toolchain outputting PE64 format, (also called PE32/64,) you could work with UEFI directly.
NathanLAAS wrote: Wed Mar 19, 2025 6:40 am
Also, are you trying to write to cdrom?
Exactly, that's what I'm trying to do.
You can't write files to recordable CD and DVD media. You have to create an ISO-9660 filesystem with the files, and burn that as a track to the disk. I don't think UEFI supports any of that. You'd have to write your own drivers to access the hardware directly.

You can write individual files to DVD-RAM media, but it probably still requires drivers which UEFI doesn't have.
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie
NathanLAAS
Posts: 7
Joined: Fri Mar 14, 2025 1:58 am

Re: EFI App: Can't open file in write MODE

Post by NathanLAAS »

You can't write files to recordable CD and DVD media.
Oh... Sad lol
However I just found out that some efi-shell support pipes :o I didn't even considered this to be possible haha
I think that I'll go with it and consider this problem as solved, thanks for your help!
User avatar
eekee
Member
Member
Posts: 911
Joined: Mon May 22, 2017 5:56 am
Location: Kerbin
Discord: eekee
Contact:

Re: [SOLVED] EFI App: Can't open file in write MODE

Post by eekee »

Okay. Have fun!
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie
Post Reply