Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UEFI Bootloader overrides memory without proper allocation #13

Open
adsnaider opened this issue Apr 8, 2021 · 2 comments
Open

UEFI Bootloader overrides memory without proper allocation #13

adsnaider opened this issue Apr 8, 2021 · 2 comments

Comments

@adsnaider
Copy link

This might have been intended to keep things simple and not have to worry about virtual memory, but I wanted to point this out as it was causing trouble with my setup. The affected code is in gnu-efi/bootloader/main.c:

int pages = (phdr->p_memsz + 0x1000 - 1) / 0x1000;
Elf64_Addr segment = phdr->p_paddr;
SystemTable->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, pages, &segment);

Kernel->SetPosition(Kernel, phdr->p_offset);
UINTN size = phdr->p_filesz;
Kernel->Read(Kernel, &size, (void*)segment);
...

This is supposed to allocate space for the kernel ELF, however, you are not checking the return status of the AllocatePages call. If you do, you'll see that it returns an error NOT_FOUND since it's attempting to allocate a page at address 0 which is not of type EfiLoaderData.

I believe the way to fix this issue is to set up virtual memory with UEFI SetVirtualAddressMap() and set appropriate addresses in the phdr to reference a physical page of EfiLoaderData type.

@kirstenjg
Copy link

I also had this issue(which particularly creeps up when I change to certain resolutions causing boot loops but sometimes undefined behavior in the kernel) and took me a while to figure this out but the first page at address 0 is already allocated. I assume by the bootloader? I have unallocated it and after that it allocates fine but then you are they overwriting memory which also causes boot failures or problems in the kernel.

What does work is changing this line to:
Elf64_Addr segment = phdr->p_paddr;
to
Elf64_Addr segment = phdr->p_paddr + 0x1000;

This starts loading the kernel at page 2.

Then change:
void (KernelStart)(BootInfo) = ((attribute((sysv_abi)) void ()(BootInfo) ) header.e_entry);
to
void (KernelStart)(BootInfo) = ((attribute((sysv_abi)) void ()(BootInfo) ) header.e_entry + 0x1000);

This loads the kernel from page 2.

Now the kernel boots fine and everything works except interrupts. To fix this and I am not happy with this fix is in the kernel kernelUtil.cpp change:
interrupt->SetOffset((uint64_t)handler);
to
interrupt->SetOffset((uint64_t)handler + 0x1000);

I do not want to have to add this offset to certain things inside the kernel.
Is there any way to tell the compiler or linker to account for this 0x1000 offset and remap the addresses?
I am sure there is a way I just don't know how.

If there is another solution let me know.

@kirstenjg
Copy link

It looks like the solution to above is not the changes I suggested above but rather change the kernel.ld script by adding this line:
. = 0x1000; just before _KernelStart = .;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants