Page 2 of 3
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Wed Nov 18, 2015 4:48 pm
by intx13
albus95 wrote:It will contain the kernel.
So for now there is only one function that is the entry point of course.
I set the image base at 0x00400000 (in the linker option).
Does that single function just loop in place: "while(1)"? Or does it try to return? Are you setting up a stack frame? How are you calling the entry point?
So I, as arleady thought, I need to allocated pages using BS->AllocatesPages right?
I need than to know the number of pages but I think I can get them from the header of the PE file, right?
Just to get things going you don't even have to allocate the memory via AllocatePages if you don't want to. Of course, attempting to allocate some pages at that address verifies that the memory is available and prevents UEFI from using it in the future, so it's a good idea.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Wed Nov 18, 2015 5:08 pm
by albus95
The function is called CsEntryPoint and it have one paramater that is a pointer to a struct that will contain the uefi enviroment information.
it is in the form void __stdcall CsEntryPoint(EFI_LOADER_DATA *Data).
Right now the function just have a for(;;) inside.
How I can set up the stack frame?
I think I can't have inline assembly inside the efi image as I'm compiling it also in 64bit mode.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Wed Nov 18, 2015 6:14 pm
by albus95
So as I'm goingi no where with this, I have looked on the web and I fond this:
https://github.com/jethrogb/uefireverse ... peloader.c
but unfortunally it use some linux system call.
So as I understand I can replace the call of mmap with the read buffer right?
Also I have change sysconf(_SC_PAGE_SIZE) to EFI_PAGE_TABLE.
But unfortunaly it not work
.
I get a couple of "Section VirtualAddress/file offset mismatch" errors.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Thu Nov 19, 2015 9:50 am
by intx13
Again, I don't really know anything about PE files, but my understanding is that if you load the file into memory at its preferred address (so that rebasing isn't necessary) and if you don't care about enforcing section protections (i.e. making sure a read-only section is actually read-only) you can just call the entry point directly. So I don't think you're doing anything fundamentally wrong or missing some big concept... you shouldn't need to rely on patching somebody else's code to get it to work. But it would be good to have input from somebody that knows PE loading.
I think there's two things you need to verify:
- Is the target function actually located in memory where you think it is? You can check this by dumping memory after loading the PE but before calling the entry point and seeing what's at the entry point address.
- Does your function pointer actually point to that entry point? You can check this by casting it to a UINT64 and printing it out with Print(L"%llx\n", variable)
albus95 wrote:The function is called CsEntryPoint and it have one paramater that is a pointer to a struct that will contain the uefi enviroment information.
it is in the form void __stdcall CsEntryPoint(EFI_LOADER_DATA *Data).
Right now the function just have a for(;;) inside.
How I can set up the stack frame?
Well your kernel entry point uses the standard C calling convention so that should work fine, because that's what GCC will use when you dereference a function pointer in your EFI code (unless you specify differently). So I think you're good there.
I think I can't have inline assembly inside the efi image as I'm compiling it also in 64bit mode.
You can use inline assembly with GNU-EFI, it will work fine. It will need to be 64-bit assembly code, of course. But you can inline assembly just like you would in any GCC-compiled function.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Thu Nov 19, 2015 10:44 am
by albus95
Ok i will try when i will back home from university.
Any way i'm not use gcc as compiler but i use visual studio c compiler.
I have gun-efi ported version for vs.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Thu Nov 19, 2015 11:59 am
by intx13
albus95 wrote:Ok i will try when i will back home from university.
Any way i'm not use gcc as compiler but i use visual studio c compiler.
I have gun-efi ported version for vs.
Is your function pointer (that you dereference to call the entry point) defined to use the __stdcall calling convention? By default, Visual Studio C uses __cdecl. Might want to either change your kernel entry point function to __cdecl, compile your UEFI application with /Gz, or mark the function pointer as __stdcall.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Thu Nov 19, 2015 4:43 pm
by albus95
Ya I should have thought of that before.
Any way Im now going to try again, but still get no result.
So to read the PE file after I get the header of it, I need to:
Allocate using either BS->AllocatePool or AllocatePages the right amount of size.
So I'm doing right now this:
Code: Select all
UINT64 LoadStartAddress = NtHeader->OptionalHeader.ImageBase;
UINTN NumPages = NtHeader->OptionalHeader.SizeOfTheImage / EFI_PAGE_SIZE;
BS->AllocatePages(AllocateAddress, EfiLoaderData, NumPages, &LoadedStartAddress);
And than i get a memory pointer like this:
Code: Select all
UINT64 MemPointer = LoadStartAddress;
Than I need to copy the section into memory, and right now I'm doing:
Code: Select all
Shdrs = (EFI_IMAGE_SECTION_HEADER*)(((char*)OptionalHeader) + NTHeader->FileHeader.SizeOfOptionalHeader);
for(INT i = 0; i < NtHeader->FileHeader.NumberOfSection; i++)
{
CopyMem(MemPointer + Shdrs[i].VirtualAddress, MemPtr + Shdr[i].PointerData, Shdrs[i].SizeOfRawData);
}
Than later on when I have to call the entry point I'm doing:
Code: Select all
PLOADER_EFI_BLOCK LoadedBlock = AllocateZeroPool(sizeof(PLOADER_EFI_BLOCK));
typedef VOID (_stdcall *KernelEntryPoint)(PLOADER_EFI_BLOCK LoadedBlock);
KernelEntryPoint EntryPoint = (MemPointer + NtHeader->OptionalHeader.AddressOfEntryPoint);
(*Entry)(BootInfo);
So there have to be somethingh wrong as as soon as I call the (*Entry)(BootInfo) the vm crash.
I have no idea where to go!
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Thu Nov 19, 2015 5:18 pm
by intx13
Ok, I think I see the problem. First, can you clarify "MemPointer" vs "MemPtr" - are those two different variables, or a typo?
Edit: I'm guessing that MemPtr is the pointer to the raw file in memory, as opposed to MemPointer, the pointer used to copy the sections to their correct addresses. If that's correct, disregard this post.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Thu Nov 19, 2015 5:24 pm
by intx13
I think this is the problem:
Code: Select all
Shdrs = (EFI_IMAGE_SECTION_HEADER*)(((char*)OptionalHeader) + NTHeader->FileHeader.SizeOfOptionalHeader);
for(INT i = 0; i < NtHeader->FileHeader.NumberOfSection; i++)
{
CopyMem(MemPointer + Shdrs[i].VirtualAddress, MemPtr + Shdr[i].PointerData, Shdrs[i].SizeOfRawData);
}
You are copying the raw object code to the virtual address, but the object code has been compiled assuming that the
entire section has been copied to the virtual address, not just the object code. So you need to copy the entire section, including the section header, to the virtual address, not just the PointerData.
However, you can do something even easier. You can copy the
entire file to the ImageBase address, then call the entry point function. This is what tutorials mean by memory mapping: the entire file is in memory at the ImageBase address, and the code has been compiled assuming that's how it will be loaded. You don't need to extract the sections at all.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Fri Nov 20, 2015 12:53 am
by MollenOS
Ok, to get how many pages you will need to allocate, you'll need to parse the sections.
For help, you can see my PeLoader implementation:
https://github.com/Fadekraft/MollenOS/b ... PeLoader.c
The relevant code for you is in the function "Addr_t PeRelocateSections(MCorePeFile_t *PeFile, uint8_t *Data, Addr_t SectionAddr, uint16_t NumSections)"
If you want to skip the whole parsing sections and relocating them, and you just want to call the entry point directly, you need to compile your PE executable with a section alignment set to the file alignment. Normally the section alignment is page-aligned, and file-alignment is set to 0x400. If you set section-alignment to 0x400, the code layout will be the same and you don't need to relocate sections.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Fri Nov 20, 2015 1:21 am
by albus95
MollenOS wrote:Ok, to get how many pages you will need to allocate, you'll need to parse the sections.
For help, you can see my PeLoader implementation:
https://github.com/Fadekraft/MollenOS/b ... PeLoader.c
The relevant code for you is in the function "Addr_t PeRelocateSections(MCorePeFile_t *PeFile, uint8_t *Data, Addr_t SectionAddr, uint16_t NumSections)"
If you want to skip the whole parsing sections and relocating them, and you just want to call the entry point directly, you need to compile your PE executable with a section alignment set to the file alignment. Normally the section alignment is page-aligned, and file-alignment is set to 0x400. If you set section-alignment to 0x400, the code layout will be the same and you don't need to relocate sections.
Thanks i will try later today, now I'm at the university and not home
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Fri Nov 20, 2015 4:17 am
by albus95
intx13 wrote:Ok, I think I see the problem. First, can you clarify "MemPointer" vs "MemPtr" - are those two different variables, or a typo?
Edit: I'm guessing that MemPtr is the pointer to the raw file in memory, as opposed to MemPointer, the pointer used to copy the sections to their correct addresses. If that's correct, disregard this post.
It is typo by the way.
Now when i'll back i'll trry again.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Fri Nov 20, 2015 7:24 am
by intx13
albus95 wrote:intx13 wrote:Ok, I think I see the problem. First, can you clarify "MemPointer" vs "MemPtr" - are those two different variables, or a typo?
Edit: I'm guessing that MemPtr is the pointer to the raw file in memory, as opposed to MemPointer, the pointer used to copy the sections to their correct addresses. If that's correct, disregard this post.
It is typo by the way.
Now when i'll back i'll trry again.
If it's a typo, I'm a little confused... you're copying from within the file buffer to somewhere else within the file buffer? I would recommend following MollenOS's recommendations for compiling such that you can load the file once and be done with it - that way you don't have to parse/extract/move the sections at all. Should simplify things.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Fri Nov 20, 2015 8:56 am
by albus95
intx13 wrote:albus95 wrote:intx13 wrote:Ok, I think I see the problem. First, can you clarify "MemPointer" vs "MemPtr" - are those two different variables, or a typo?
Edit: I'm guessing that MemPtr is the pointer to the raw file in memory, as opposed to MemPointer, the pointer used to copy the sections to their correct addresses. If that's correct, disregard this post.
It is typo by the way.
Now when i'll back i'll trry again.
If it's a typo, I'm a little confused... you're copying from within the file buffer to somewhere else within the file buffer? I would recommend following MollenOS's recommendations for compiling such that you can load the file once and be done with it - that way you don't have to parse/extract/move the sections at all. Should simplify things.
Ya in fact is what u will probably do.
Re: Efi bootloader, PE Loading Image = really stuck.
Posted: Fri Nov 20, 2015 9:00 am
by albus95
MollenOS wrote:Ok, to get how many pages you will need to allocate, you'll need to parse the sections.
For help, you can see my PeLoader implementation:
https://github.com/Fadekraft/MollenOS/b ... PeLoader.c
The relevant code for you is in the function "Addr_t PeRelocateSections(MCorePeFile_t *PeFile, uint8_t *Data, Addr_t SectionAddr, uint16_t NumSections)"
If you want to skip the whole parsing sections and relocating them, and you just want to call the entry point directly, you need to compile your PE executable with a section alignment set to the file alignment. Normally the section alignment is page-aligned, and file-alignment is set to 0x400. If you set section-alignment to 0x400, the code layout will be the same and you don't need to relocate sections.
I think i found bug in the code, where you are checking for 32/64 headers you in both use sizeof( PeHeader64_t).
I mean line and line 364 are 352 equals!