Loading your kernel, EfiLoaderData?

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
xxxxxxBANNEDxxxxxx
Posts: 14
Joined: Wed Jun 12, 2024 5:32 am

Loading your kernel, EfiLoaderData?

Post by xxxxxxBANNEDxxxxxx »

Hello,

Is it common practice for a UEFI OS loader to allocate memory of type EfiLoaderData when loading the entire kernel into memory?

The UEFI specs says that - in general - UEFI OS loaders should allocate memory of type EfiLoaderData, and also all the information on the web I've come across on loading your own kernel into memory use this type of memory and everything seems to be working just fine. Probably because the execute permission bit is set for EfiLoaderData pages, but is this guaranteed to always be the case though?

Wouldn't it be better to only load the data part of your kernel into memory of type EfiLoaderData and the executable part of your kernel into memory of type EfiLoaderCode, just to ensure that it can always be executed on different platforms?
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Loading your kernel, EfiLoaderData?

Post by nullplan »

No, you load the entire kernel as EfiLoaderData, and when you hand the memory map to the kernel, you tell it where the kernel is (given that you cannot know in advance). Or at least, that's what I do. I have to reformat the memory map to my bespoke format anyway, may as well reserve the kernel pages while I'm at it.

For the loader, the kernel is just data. It becomes code only once the kernel is executed, but then we are no longer in the loader phase.
Carpe diem!
xxxxxxBANNEDxxxxxx
Posts: 14
Joined: Wed Jun 12, 2024 5:32 am

Re: Loading your kernel, EfiLoaderData?

Post by xxxxxxBANNEDxxxxxx »

Allright, loading the entire kernel as EfiLoaderData it is. Thanks nullplan!
User avatar
zaval
Member
Member
Posts: 656
Joined: Fri Feb 17, 2017 4:01 pm
Location: Ukraine, Bachmut
Contact:

Re: Loading your kernel, EfiLoaderData?

Post by zaval »

Probably because the execute permission bit is set for EfiLoaderData pages
Such a bit is not set for this type at all nor does it matter.

You should get one thing: outside of UEFI running time, UEFI memory types are meant just for recognizing what to do with these pages next: whether it's free memory or it's firmware reserved, for ACPI or for run time services. And that's all of the purpose. You don't use these types for setting up attributes for pages where you put the kernel. You set up those attributes on your own, what exactly you need, in the page tables, built up by you. UEFI and its memory types have nothing to with that. EfiLoaderData for such allocations is used because it's all needed. For UEFI, it's really loader data. Those pages become code or data after your loader takes control over the map.
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).
xxxxxxBANNEDxxxxxx
Posts: 14
Joined: Wed Jun 12, 2024 5:32 am

Re: Loading your kernel, EfiLoaderData?

Post by xxxxxxBANNEDxxxxxx »

Yes, I think I understand. After loading the kernel into memory as EfiLoaderData, I can set up my own page tables, map the loaded kernel, set the appropriate attributes, and then jump to the kernel's main entry point and go from there.

However, rather than placing the page table creation code inside the OS loader, I would prefer to include it in the kernel's init function. But jumping to the kernel's init code might not work if the execution of code in EfiLoaderData is not allowed by the page tables created by the firmware. That's why I was wondering if it's ok for an OS loader to load the executable part of the kernel as EfiLoaderCode.

But looking at nullplan's post, we probably should only use EfiLoaderData.

In any case, thanks for your reply zaval. Much appreciated.
User avatar
zaval
Member
Member
Posts: 656
Joined: Fri Feb 17, 2017 4:01 pm
Location: Ukraine, Bachmut
Contact:

Re: Loading your kernel, EfiLoaderData?

Post by zaval »

However, rather than placing the page table creation code inside the OS loader, I would prefer to include it in the kernel's init function. But jumping to the kernel's init code might not work if the execution of code in EfiLoaderData is not allowed by the page tables created by the firmware.
I don't know your reason for that preference, but that would only mean, that you postponed one of the main loader's task to the kernel function (2 in fact: building up the mapping and trampoline (jumping from UEFI space to the kernel one)). That function then would have to start in the UEFI (identity mapped) address space, build up its page table structure and switch to its own address space. Meaning you would need to ExitBootServices() from the kernel, rather from the loader, as normally is being done. If you ExitBootServices() in the loader, but without your own page tables built up yet, that would be a massive mess, - you would need then to add to that yet one page allocator, page table building requires pages for itself... but, it's up to the designer.

Marking memory as EfiLoaderCode is used by UEFI internally for its payload's code section pages. It's for .efi files, intended for running in the UEFI environment.
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).
xxxxxxBANNEDxxxxxx
Posts: 14
Joined: Wed Jun 12, 2024 5:32 am

Re: Loading your kernel, EfiLoaderData?

Post by xxxxxxBANNEDxxxxxx »

Interesting. I was under the impression that a UEFI OS loader's job was to do just these two things: 1) gather system information that needs to be passed to the kernel, and 2) load the kernel into memory, get the memory map, call ExitBootServices, and finally hand off control to the loaded kernel image. The loaded kernel image would then enter an initialization stage in which it would create the PML4 page table and set up the necessary system tables, such as the GDT and IDT. I didn’t realize that these tasks were supposed to be part of the OS loader. To me, it felt like they needed to be part of the kernel's initialization process, but perhaps you are right, and it’s bad design. I’ll give it some more thought. Thank you.
Post Reply