Thursday, May 26, 2011

Bare Bones Kernel

Preface
This tutorial assumes you have a compiler / assembler / linker toolchain capable of handling ELF files. On a Windows machine, you are strongly encouraged to set up a GCC Cross-Compiler, as it removes all the various toolchain-specific issues you might have ("PE operation on a non-PE file", "unsupported file format", and a number of others). While technically a Linux machine already has an ELF-capable toolchain, you are still encouraged to build a cross-compiler, as it is the first step to do, and it keeps you from relying on things you shouldn't (header files, for example).
The code in this tutorial assumes you are using GRUB to boot the system. GRUB (a Multiboot compliant boot loader) puts the system in to the correct state for your kernel to start executing. This includes enabling the A20 line (to give you access to all available memory addresses) and putting the system in to 32-bit Protected Mode, giving you access to a theoretical 4GiB of memory.

Overview
Even when using GRUB, some setup is required before entering an int main() type function. The most basic setup to get an ELF format kernel to be booted by GRUB consists of three files:
loader.s - assembler "glue" between bootloader and kernel
kernel.c - your actual kernel routines
linker.ld - for linking the above files
The second part of this tutorial briefly describes how to boot the compiled kernel.
loader.s
loader.s takes over over control from the Multiboot bootloader, and jumps into the kernel proper.
NASM
global loader           ; making entry point visible to linker
extern kmain            ; kmain is defined elsewhere
; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ  1<<0                   ; align loaded modules on page boundaries
MEMINFO     equ  1<<1                   ; provide memory map
FLAGS       equ  MODULEALIGN | MEMINFO  ; this is the Multiboot 'flag' field
MAGIC       equ    0x1BADB002           ; 'magic number' lets bootloader find the header
CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum required
section .text
align 4
MultiBootHeader:
   dd MAGIC
   dd FLAGS
   dd CHECKSUM
; reserve initial kernel stack space
STACKSIZE equ 0x4000                  ; that's 16k.
loader:
   mov esp, stack+STACKSIZE           ; set up the stack
   push eax                           ; pass Multiboot magic number
   push ebx                           ; pass Multiboot info structure
   call  kmain                       ; call kernel proper
...


Read more: OsDev.org wiki