OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 1:09 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 22 posts ]  Go to page Previous  1, 2
Author Message
 Post subject: Re: UEFI Bare Bones
PostPosted: Mon Apr 13, 2020 9:22 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
One thing I could never find a satisfactory answer to is where is UEFI allowed to load your bootloader in memory. Clearly a PE file can be relocated and I have tested that this is the case on 3 computers + QEMU. In all cases, by 0-based image gets relocated "somewhere" that is different on each machine.

I do load my kernel from the bootloader and setup virtual memory space so that my kernel is at 0xF0000000. If for any reason UEFI decided to load my bootloader at or above 0xF0000000, this would be a problem: turning on virtual memory would crash the bootloader. That's the 32 bits world. So as previously mentioned you can just ignore UEFI on ia32. But what about other 32-bits platforms?

As for the 64 bits world, I am less worried because I find it even less likely for something like this to happen. But still. I am surprised by the lack of information / clarity about this issue.

Now it so happened that Windows and Linux and any other sane OS probably wants to be at the end of the address space, but I don't know that's always true especially on non-PC platforms.

One could detect this and relocate some trampoline code out of the way, but that's pain I'd rather avoid if it is not necessary.

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: UEFI Bare Bones
PostPosted: Mon Apr 13, 2020 10:05 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
kzinti wrote:
One thing I could never find a satisfactory answer to is where is UEFI allowed to load your bootloader in memory. Clearly a PE file can be relocated and I have tested that this is the case on 3 computers + QEMU. In all cases, by 0-based image gets relocated "somewhere" that is different on each machine.
Yep, that is the entire definition you get. UEFI will put your bootloader anywhere in memory. The only guarantees you have are that physical address == virtual address.

What Linux does to work around this is to relocate. It is normal now to have a compressed kernel (in fact, building an uncompressed kernel with UEFI stub is unsupported right now). Compressed kernels work by having a decompressor unpack the raw kernel image. The decompressor is mostly position independent (unlike the rest of the kernel). It will detect if it is in the way of the uncompressed kernel and relocate itself elsewhere if so.

kzinti wrote:
Now it so happened that Windows and Linux and any other sane OS probably wants to be at the end of the address space, but I don't know that's always true especially on non-PC platforms.
On PowerPC, every operating system wants to be loaded at the start of physical address space. This is because all exceptions disable paging there, and then jump to predetermined addresses in the first 12kB of address space (unless a certain bit is set in the MSR, in which case the exception vectors are in the first 12kB of the last megabyte of address space). Therefore most OSes have a 12kB block of exception handlers at the start, to be copied to the start of address space, which is easiest if the entire kernel image is just loaded there. I am, however, unaware of a UEFI implementation for PowerPC.

Back to the PC: My kernel does not care where it is loaded in physical memory, or even if it is contiguous. The bootloader gives a list of reserved physical memory ranges to the kernel, and the kernel only knows that those ranges are unavailable, for whatever reason. Since in my case, the bootloader turns on the virtual memory (that is, it switches over to my kernel's paging scheme), the kernel itself does not have to know.

kzinti wrote:
One could detect this and relocate some trampoline code out of the way, but that's pain I'd rather avoid if it is not necessary.
Oh, come on, it is not that painful. My bootloader turns on virtual memory as the very last thing before invoking the kernel. Therefore the code that does that is mostly self-contained. So why not just compile the trampoline code into a raw binary, then tack that binary into the bootloader as data? Then you can just copy it always. You need to know where the trampoline will end up, anyway, for the identity-map. So instead of putting it in a constant address, you use as base address whatever the allocator returns to you. Copy, set function pointer, call, done.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: UEFI Bare Bones
PostPosted: Mon Apr 13, 2020 10:20 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
nullplan wrote:
Oh, come on, it is not that painful.

Lol. Fair enough. I'll just get it done :P.

nullplan wrote:
My bootloader turns on virtual memory as the very last thing before invoking the kernel.

Yes I do the same thing. I basically don't care where my kernel is loaded. I identity map everything from 0 to 0xEFFFFFFF and map the kernel to 0xF0000000. The very last bit I do is set CR3 and jump to the entry point (>= 0xF0000000). This will only fail if this last bit of code is not below 0xF0000000. I think I'll just dynamically generate the trampoline code out of the way and use that.

Thanks for your comments.

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: UEFI Bare Bones
PostPosted: Thu Apr 16, 2020 1:14 pm 
Offline
Member
Member
User avatar

Joined: Mon May 22, 2017 5:56 am
Posts: 812
Location: Hyperspace
Personally, I'm happy to see another UEFI article.

I am not quite so happy to see yet another article featuring that worst of all compilers to cross-compile with, but it won't actually affect me because I don't like C.

I would like clarification regarding the 32-bit issue because if you can boot 32-bit UEFI binaries on 64-bit UEFI machines, it would save me some work in the short term.

_________________
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


Top
 Profile  
 
 Post subject: Re: UEFI Bare Bones
PostPosted: Thu Apr 16, 2020 9:55 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
eekee wrote:
(...) if you can boot 32-bit UEFI binaries on 64-bit UEFI machines, it would save me some work in the short term.


That's not possible. But once your UEFI binary is loaded, you can do whatever you want including switching from 64 bits to 32 bits or vice-versa.

So if your UEFI app is a 64 bits bootloader, it can load and setup a 32 bits kernel. But UEFI won't be of any help here (well except for loading the kernel, of course).

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: UEFI Bare Bones
PostPosted: Fri Apr 17, 2020 12:24 am 
Offline
Member
Member
User avatar

Joined: Thu Aug 11, 2005 11:00 pm
Posts: 1110
Location: Tartu, Estonia
In the meantime I had a look at the GCC sources to figure out the implications of using a Windows (MinGW or Cygwin) targeted compiler vs. the ELF approach I used here. After all, I think the "cleanest" approach with GCC would be adding another target to GCC, something like i686-efi / x86_64-efi, which generates PE / PE+ executables with the proper subsystem and relocations, without pulling in any Cygwin / MinGW specific dependencies. This requires modifying the GCC sources, which I am not (yet) very familiar with. But maybe it's worth a shot.

Also I tried out Clang / LLVM and managed to compile some working examples with the i686-unknown-windows / x86_64-unknown-windows targets, but I also had to modify the sources a bit. I will update the wiki article once I have cleaned up things a bit. The result is definitely "better" / "cleaner" since it uses neither PIC nor ELF as an intermediate step, but directly yields a PE / PE+ executable with proper relocations. I'll take a look at the sources as well, to see whether also here one could add some *-efi target, and what is actually implied by targeting *-windows.

Speaking of relocations - one thing I'll try to investigate is where the file is loaded by different UEFI implementations and how relocations are handled there.

Finally, I still intend to extend this work to AArch32 / AArch64 :)

_________________
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS


Top
 Profile  
 
 Post subject: Re: UEFI Bare Bones
PostPosted: Sat Apr 18, 2020 5:31 am 
Offline
Member
Member
User avatar

Joined: Mon May 22, 2017 5:56 am
Posts: 812
Location: Hyperspace
kzinti wrote:
eekee wrote:
(...) if you can boot 32-bit UEFI binaries on 64-bit UEFI machines, it would save me some work in the short term.

That's not possible. But once your UEFI binary is loaded, you can do whatever you want including switching from 64 bits to 32 bits or vice-versa.

Thanks. I think I'll put the work in to convert this "Plain English" compiler to 64-bits. It'll be about as easy as such a conversion could be right now, and will familiarize me with the parts I'd need for porting it to other architectures.

_________________
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


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 22 posts ]  Go to page Previous  1, 2

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 15 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group