Page 1 of 1

Grub2 image (ELF64 bootloader)

Posted: Thu Jul 03, 2014 1:55 pm
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!

Re: Grub2 image (ELF64 bootloader)

Posted: Fri Jul 04, 2014 12:57 am
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.)

Re: Grub2 image (ELF64 bootloader)

Posted: Wed Jul 09, 2014 1:59 am
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?

Re: Grub2 image (ELF64 bootloader)

Posted: Wed Jul 09, 2014 2:42 am
by Octocontrabass
Are you using a cross-compiler?

Re: Grub2 image (ELF64 bootloader)

Posted: Wed Jul 09, 2014 3:29 am
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.

Re: Grub2 image (ELF64 bootloader)

Posted: Wed Jul 09, 2014 5:52 am
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.

Re: Grub2 image (ELF64 bootloader)

Posted: Wed Jul 09, 2014 6:59 am
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).