uefi seems to load image incorrectly

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

uefi seems to load image incorrectly

Post by austanss »

I've been getting General Protection faults when running my EFI image. It doesn't make much sense. However, I investigated a bit.

When the machine throws an exception, I pause it and dump the memory. I disassembled the memory dump and looked for where the instruction pointer was located, a scasd instruction. In fact, the area is covered with scasd instructions...

Exception:

Code: Select all

/usr/bin/qemu-system-x86_64 -bios res/OVMF.fd -cdrom microNET.iso -m 512M -net none -serial stdio
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 - 0D(#GP - General Protection)  CPU Apic ID - 00000000 !!!!
ExceptionData - 0000000000000000
RIP  - 000000001EA372D9, CS  - 0000000000000038, RFLAGS - 0000000000000202
RAX  - AFAFAFAFAFAFAFAF, RCX - 000000001F16ADE0, RDX - 0000000000000000
RBX  - 000000001EB47018, RSP - 000000001FF078C0, RBP - 000000001FF07990
RSI  - 000000001F9EE018, RDI - 000000001EC32B18
R8   - 0000000000000001, R9  - 0000000000000001, R10 - 000000000000001F
R11  - 0000000000000010, R12 - 0000000000000000, R13 - 0000000000000001
R14  - 0000000000000004, R15 - 000000001F084F44
DS   - 0000000000000030, ES  - 0000000000000030, FS  - 0000000000000030
GS   - 0000000000000030, SS  - 0000000000000030
CR0  - 0000000080010033, CR2 - 0000000000000000, CR3 - 000000001FC01000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 000000001F9EEA98 0000000000000047, LDTR - 0000000000000000
IDTR - 000000001F175018 0000000000000FFF,   TR - 0000000000000000
FXSAVE_STATE - 000000001FF07520
!!!! Find image based on IP(0x1EA372D9) (No PDB)  (ImageBase=000000001EA34000, EntryPoint=000000001EA39530) !!!!
2020-11-08_19-41.png
2020-11-08_19-43.png
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: uefi seems to load image incorrectly

Post by nexos »

Where is the source to your EFI application?
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: uefi seems to load image incorrectly

Post by austanss »

nexos wrote:Where is the source to your EFI application?
https://github.com/microNET-OS/microCOR ... bootloader
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: uefi seems to load image incorrectly

Post by bzt »

You probably have an incorrect EFI call (which does not comply with the EFI ABI), that's why you end up executing code outside of the text segment.
I haven't found that yet, but I've found another error in your code: main.c.
In line 110 you get the size of the memory map. That's fine. But in line 126 you allocate more memory, which could increase the size of the memory map that you don't take into account. Therefore in line 135 the get memory map will return EFI_BUFFER_TOO_SMALL.

There are the following options:
1. you allocate exactly as many bytes as there are in a free slot. Then the memory map size doesn't change, only one entry gets "efi loader memory" type instead of "free" type (unlikely)
2. you allocate fewer bytes than the smallest free slots where it fits. Then the memory map size will grow, it's going to keep the free slot (but smaller in size), and there will be an additional "efi loader memory" entry (most likely)
3. in a very unusual circumstances your allocation could split a free slot into two. Then there'll be the original free entry (but with smaller size), an "efi loader memory" entry, and a new "free" entry (unlikely, but probable)

The solution is to allocate more memory for the map than reported, as suggested on the wiki (there's also an example code).

Cheers,
bzt
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: uefi seems to load image incorrectly

Post by austanss »

bzt wrote:You probably have an incorrect EFI call (which does not comply with the EFI ABI), that's why you end up executing code outside of the text segment.
I haven't found that yet, but I've found another error in your code: main.c.
In line 110 you get the size of the memory map. That's fine. But in line 126 you allocate more memory, which could increase the size of the memory map that you don't take into account. Therefore in line 135 the get memory map will return EFI_BUFFER_TOO_SMALL.

There are the following options:
1. you allocate exactly as many bytes as there are in a free slot. Then the memory map size doesn't change, only one entry gets "efi loader memory" type instead of "free" type (unlikely)
2. you allocate fewer bytes than the smallest free slots where it fits. Then the memory map size will grow, it's going to keep the free slot (but smaller in size), and there will be an additional "efi loader memory" entry (most likely)
3. in a very unusual circumstances your allocation could split a free slot into two. Then there'll be the original free entry (but with smaller size), an "efi loader memory" entry, and a new "free" entry (unlikely, but probable)

The solution is to allocate more memory for the map than reported, as suggested on the wiki (there's also an example code).

Cheers,
bzt
Alas, once I fixed that (I allocated memory_map_size + 2048, hope thats enough) the RIP was now located at 0x1EA372E0 when the exception was thrown. So it seems I have a few bad EFI calls... goodie :roll:
Any help?
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: uefi seems to load image incorrectly

Post by austanss »

So I was doing a good ole' debuggin' trick of moving around an infinite loop. The code seems to break when making any kind of EFI call. It'll call InitializeLib alright, but when using any EFI function, using uefi_call_wrapper or directly, or any form otherwise, it throws a general protection exception. Very confused... anyone know why? I'm thinking it could be improperly loaded/linked efi stuff, therefore causing the machine to jump to garbage...
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: uefi seems to load image incorrectly

Post by nexos »

The problem may be in how you are building. My EFI app skips GNU EFI. Basically, what I do is follow the build instructions at https://wiki.osdev.org/UEFI_App_Bare_Bones, and then I use the EFI header file from GNU EFI. You can find those headers at https://github.com/Nexware-Project/EfiHeaders. Simply copy those to your source directory, update you include path to include those files, and your good! Note that you will not have any functions to do things like copy memory, you will have to write those. Also, don't use uefi_call_wrapper when doing it this way, as you are actually using the MS ABI. My EFI bootloader's full source is at https://github.com/Nexware-Project/NexBoot, inside the Loader directory.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: uefi seems to load image incorrectly

Post by bzt »

If you want to keep GNU EFI, then compile with your native toolchain (not with mingw32), then as the last step convert the ELF into PE. This is the recommended way with GNU-EFI.
Mando wrote:This is the way :-)
This can be found on the wiki, and here's a working real-life example that I use and that's known to work under Linux. As you can see, I have an "objcopy" line in the Makefile's %.efi rule, that's responsible for creating the PE executable from the ELF shared object, otherwise I'm using the native compiler on x86_64.

Cheers,
bzt
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: uefi seems to load image incorrectly

Post by austanss »

bzt wrote:If you want to keep GNU EFI, then compile with your native toolchain (not with mingw32), then as the last step convert the ELF into PE. This is the recommended way with GNU-EFI.
Mando wrote:This is the way :-)
This can be found on the wiki, and here's a working real-life example that I use and that's known to work under Linux. As you can see, I have an "objcopy" line in the Makefile's %.efi rule, that's responsible for creating the PE executable from the ELF shared object, otherwise I'm using the native compiler on x86_64.

Cheers,
bzt
I had completely overhauled my code using nexos's method...

but this one is better. However I get exceptions when using ST->ConOut->OutputString specifically, not any other function. Don't know why, but I don't care anyway. The only thing I need to fix now is the kernel loading. Thanks everyone!
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: uefi seems to load image incorrectly

Post by bzt »

rizxt wrote:Alas, once I fixed that (I allocated memory_map_size + 2048, hope thats enough)
More than likely that's enough. But the first get memory map returned the exact descriptor entry size (usually 20 or 24 bytes), so you could add "+ 2*DescriptorSize".
rizxt wrote:the RIP was now located at 0x1EA372E0 when the exception was thrown. So it seems I have a few bad EFI calls... goodie :roll:
Any help?
Or a stack corruption (that's also possible). Try single-steping instructions from the point where your code gets control. Somewhere, something messes up the control flow.

Cheers,
bzt
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: uefi seems to load image incorrectly

Post by austanss »

My bootloader works! I can verify this via checking my serial line for GLOBAL CONSTRUCTORS CALLED, The only problem I have now is that I can't get my GOP framebuffer to work after I enter the kernel...
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
User avatar
zaval
Member
Member
Posts: 656
Joined: Fri Feb 17, 2017 4:01 pm
Location: Ukraine, Bachmut
Contact:

Re: uefi seems to load image incorrectly

Post by zaval »

rizxt wrote:My bootloader works! I can verify this via checking my serial line for GLOBAL CONSTRUCTORS CALLED, The only problem I have now is that I can't get my GOP framebuffer to work after I enter the kernel...
did you try to OutputString() inside your OSL? does it work? regarding GOP, I hope, you know, that you cannot use GOP functions outside Boot Services context (after ExitBootServices() call), only address of the framebuffer and its parameters handed over to you through the GOP instance are valid?
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).
Post Reply