Grub2 image (ELF64 bootloader)

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
evoex
Member
Member
Posts: 103
Joined: Tue Dec 13, 2011 4:11 pm

Grub2 image (ELF64 bootloader)

Post by evoex »

Hi all,

I'm working on my operating system on Mac OS X, and all is setup and running fine (well, as a side note, except for qemu's tendency to start without focus, which is a bit of a pain, if anyone has any idea ;-).
Anyways, I'm trying to move to 64 bits and want to have my kernel in an ELF64 file. My pre-installed grub legacy floppy image doesn't support ELF64, and I believe grub2 does. However, I can't get grub2 to install on my Mac. I did try installing it on my Linux laptop but I couldn't get a bootable image with ELF64 support.
I'll keep on trying, and I don't have any specific questions regarding how to create it yet, but I do have some questions:
- Does anyone know/have a working grub2 image with ELF64 support available? Floppy or harddrive doesn't matter.
- Does anyone know another multiboot boot loader that supports ELF64, because grub2 feels... painful to use... (I particularly liked about it complaining an argument wasn't specified even though it was, turned out it was ignoring all arguments at some point, I gave up trying to make sense of it, as I just want a stupid image so I can get on with development).

Thanks in advance!
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Grub2 image (ELF64 bootloader)

Post by Combuster »

Multiboot 1 does not support 64-bit elf, so by trying that you're making a non-multiboot binary for most loaders in the first place.

You can stick to multiboot and embed mostly 64-bit code into a 32-bit ELF file, and enter long mode manually (outlined here.)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
evoex
Member
Member
Posts: 103
Joined: Tue Dec 13, 2011 4:11 pm

Re: Grub2 image (ELF64 bootloader)

Post by evoex »

Thanks for your reply!

I've actually been trying hard getting this to work, but it's simply not working. So my question: how do I compile this?
I managed to get it to run, but the debug symbols never quite turn out correct, causing gdb to ignore breakpoints. The assembly files work just fine - no special compile flags, just ".code32" does the trick, it's just that g++ doesn't work. I've tried every combination of "-m32", "-mx32", "-march=..." flags that I could imagine, without luck.

So, any ideas on how I would compile this?
Octocontrabass
Member
Member
Posts: 5590
Joined: Mon Mar 25, 2013 7:01 pm

Re: Grub2 image (ELF64 bootloader)

Post by Octocontrabass »

Are you using a cross-compiler?
evoex
Member
Member
Posts: 103
Joined: Tue Dec 13, 2011 4:11 pm

Re: Grub2 image (ELF64 bootloader)

Post by evoex »

Octocontrabass wrote:Are you using a cross-compiler?
Yes, I'm using an x86_64-elf compiler, and it works fine for a purely 32-bit kernel. I do have an i686-elf cross compiler as well, but I don't think that would make a difference.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Grub2 image (ELF64 bootloader)

Post by sortie »

The trick is making GRUB think your ELF64 kernel is a ELF32 multiboot kernel. You basically do this:
  1. Write your pure 64-bit kernel.
  2. Make it slightly unpure by having the entry point (_start) contain 32-bit assembly instructions. These instructions switch to long mode and set up paging (identity map the areas you care about early on). It then jumps to the real 64-bit entry point.
  3. Compile and link this almost-pure 64-bit kernel into an ELF64 object that contains a few 32-bit instructions and a lot of 64-bit instructions.
  4. Run x86_64-elf-objcopy myos.elf64 -O elf32-i386 myos.elf32. This converts the ELF container to a 32-bit container (which GRUB understands) but doesn't actually change the code. The result is a nice 32-bit kernel using multiboot that GRUB understand, which immediately switches to long mode and jumps to 64-bit instructions.
  5. Feed your fake 32-bit kernel to GRUB as you would with a 32-bit multiboot kernel. It should now boot if everything went well.
Mind that a few things can go wrong. The x86_64 linker defaults to some huge alignments that can cause trouble for the multiboot header or make the kernel very big, you should pass -Wl,max-page-size=0x1000 when linking with your compiler. You must also be aware that you need to pass -mno-red-zone (if you don't implement it, otherwise terrible corruption happens when the kernel is interrupted by the CPU) and -mno-mmx -mno-sse and -mno-sse2 if you don't implement these features in the kernel (or don't want the kernel code to use them).

Don't randomly try combinations compile options. That doesn't lead to a reliable solution, you need to understand the low-level semantics of what is going on, so you can design a solution that works. Use tools like readelf(1) and objdump(1) to inspect the created binaries. Study the GRUB source code so you understand what is happening.
evoex
Member
Member
Posts: 103
Joined: Tue Dec 13, 2011 4:11 pm

Re: Grub2 image (ELF64 bootloader)

Post by evoex »

Thanks for your replies, guys!
I did get it to work with only assembly - I just would rather be allowed to use C++ for this portion as well. But it sounds like it's too much of a hassle, so I'll stick to assembly, unless anybody has any idea on how to set it up for C++ as well?
I did actually use readelf/objdump to inspect the results, btw, which is where I found out about the issues (that, and gdb).
Post Reply