Creating a 64-bit kernel using a separate loader: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
No edit summary
m Bot: Replace deprecated source tag with syntaxhighlight
 
(4 intermediate revisions by 3 users not shown)
Line 2:
{{In_Progress}}
 
This page is an extension to [[Creating_a_64-bit_kernel|Creating a 64-bit kernel]], specifically the section [[Creating_a_64-bit_kernel#With_a_separate_loader|Loading with a separate loader]]. If you haven'thave not read that, go read it now.<br/>
<b>EverythingThis inmay thisor pagemay isnot basedwork onwith myyour own researchkernel and testing,you itmay or may not workneed exactlyto liketweak thisit forto yourwork ownwith your kernel.</b>
 
== 64-bit kernel ==
Line 12:
 
Compile C files with
<sourcesyntaxhighlight lang="bash">
x86_64-elf-gcc -m64 -c <sourcesyntaxhighlight file> -o <output> -ffreestanding -z max-page-size=0x1000 -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -std=gnu99 -O2 -Wall -Wextra -I <path to your header files>
</syntaxhighlight>
</source>
Link the kernel with
<sourcesyntaxhighlight lang="bash">
x86_64-elf-gcc -T <linker script> -o <output> <all object files> -ffreestanding -O2 -nostdlib -lgcc
</syntaxhighlight>
</source>
 
Your ouput should be copied to loader_build/boot/kernel.bin (See [[#GRUB|32-bit loader GRUB]])
Line 27:
It starts with a multiboot header and an assembly routine to set up a stack and call the C code. <br/>
Additionally it might check eax to see if it contains 0x2BADB002 (which means it was loaded by a multiboot bootloader)
<sourcesyntaxhighlight lang="asm">
_start:
cli ; Clear interrupts, we don't want them as long as we are in the loader
Line 35:
push ebx ; Push pointer to multiboot info structure
call lmain
</syntaxhighlight>
</source>
 
=== Loader ===
The loader must now set up its own <b>32-bit</b> [[Global Descriptor Table|GDT]] and parse the multiboot structure given to it by the bootstrap.<br/>
A header containing useful multiboot structures can be downloaded [https://www.gnu.org/software/grub/manual/multiboot/html_node/multiboot_002eh.html here]
<sourcesyntaxhighlight lang="C">
#include "multiboot.h"
 
Line 60 ⟶ 61:
}
}
</syntaxhighlight>
</source>
 
Every multiboot module has a command line associated with it, available from the multiboot_module_t is a pointer to it.<br/>
One might load all the modules available into memory at this point, or check them for a specific command line to load only a specific subset.
<sourcesyntaxhighlight lang="C">
const char* module_string = (const char*)module->cmdline;
/* Here I check if module_string is equals to the one i assigned my kernel
Line 71 ⟶ 72:
kentry = load_elf_module(module->mod_start, module->mod_end);
}
</syntaxhighlight>
</source>
 
Now, we must parse the kernel ELF file that the bootloader loaded into memory for us.<br/>
This can be done pretty easily using a helper function and a header I wrote following the ELF64 specification (Available [|here]) and function declarations (Available [|here])
 
<sourcesyntaxhighlight lang="C">
#include "elf64.h" // Also requires elf64.c
 
Line 96 ⟶ 97:
return NULL;
}
</syntaxhighlight>
</source>
 
Finally, we can set up long mode and jump to the 64-bit kernel.<br/>
We do this by putting 2 assembly functions at the end of the lmain function
 
<sourcesyntaxhighlight lang="C">
extern void setup_longmode();
extern void enter_kernel(void* entry, uint32_t multiboot_info);
Line 112 ⟶ 113:
enter_kernel(kentry, (uint32_t) mb_info);
}
</syntaxhighlight>
</source>
 
=== Setting up long mode ===
Line 129 ⟶ 130:
Now we are in Compatibility mode, to enter Long mode we have to set up a 64-bit GDT (This will be the GDT your kernel uses, so you have to set up everything here)<br/>
<b>The code below is not optimal in the slightest, and you should try to put together your own alternative.</b>
<sourcesyntaxhighlight lang="asm">
global enter_kernel
enter_kernel:
Line 154 ⟶ 155:
k_ptr:
dd 0
</syntaxhighlight>
</source>
 
=== Compiling and linking the loader ===
Line 180 ⟶ 181:
 
To build it:
<sourcesyntaxhighlight lang="bash">
grub-mkrescue -o os.iso loader_build/
</syntaxhighlight>
</source>
 
== See Also ==
Line 191 ⟶ 192:
[[Category:Tutorials|Creating a 64-bit kernel using a separate loader]]
[[Category:X86-64|Creating a 64-bit kernel using a separate loader]]
[[Category:Bootloaders]]