User:Zesterer/Bare Bones: Difference between revisions

Content deleted Content added
Zesterer (talk | contribs)
No edit summary
mNo edit summary
 
(8 intermediate revisions by 4 users not shown)
Line 1:
{{Rating | 1|}}{{Template: Kernel designs}}
 
This is an introductory tutorial for kernel development on the x86 architecture. It is a minimal example only, and does not show you how to structure a serious project. However, completing this project is a good first step for aspiring kernel developers.
Line 56:
 
== Building A Cross-Compiler ==
:''{{Main article: [[|GCC Cross-Compiler]], [[|Why do I need a Cross-Compiler?]]}}
 
The first thing we need to do is to build ourselves a cross-compiler toolchain to let us compile and link code for the x86. Until we have that, we can't do anything. A standard C compiler won't work: it doesn't understand how to generate the machine code we need for this project.
Line 92:
First, we create '''start.s'''. To best understand the code, I recommend typing it out by hand such that you can understand each part in detail.
 
<sourcesyntaxhighlight lang = "text">
// We declare the 'kernel_main' label as being external to this file.
// That's because it's the name of the main C function in 'kernel.c'.
Line 121:
// This section contains data initialised to zeroes when the kernel is loaded
.section .bss
// Our C code will need a stack to run. Here, we allocate 10244096 bytes (or 14 KilobyteKilobytes) for our stack.
// We can expand this later if we want a larger stack. For now, it will be perfectly adequate.
.align 16
stack_bottom:
.skip 10244096 // Reserve a 10244096-byte (1K4K) stack
stack_top:
Line 146:
hlt // Halt the CPU
jmp hang // If that didn't work, loop around and try again.
</syntaxhighlight>
</source>
 
=== kernel.c ===
Line 152:
'kernel.c' contains our main kernel code. Specifically, it contains code for displaying text on the screen using the VGA textmode buffer.
 
<sourcesyntaxhighlight lang = "c">
// GCC provides these header files automatically
// They give us access to useful things like fixed-width types
Line 254:
term_print("Welcome to the kernel.\n");
}
</syntaxhighlight>
</source>
 
=== linker.ld ===
 
This file is a '''link script'''. It is used to define how bits of the final kernel executable will be stitched together. It allows us to specify alignment, address offset, and other such useful properties of parts of the code that we need when our kernel gets linked together into an executable. You don't normally do this when you're writing C code - the compiler will do this for you. But this an operating system kernel, so we need to explicitly define a lot of these things.
 
<sourcesyntaxhighlight lang = "text">
/* The bootloader will start execution at the symbol designated as the entry point. In this case, that's 'start' (defined in start.s) */
ENTRY(start)
Line 306:
}
 
</syntaxhighlight>
</source>
 
== Compiling And Linking ==
Line 370:
=== grub.cfg ===
 
<sourcesyntaxhighlight lang = "text">
menuentry "My Kernel" {
multiboot /boot/mykernel.elf
boot
}
</syntaxhighlight>
</source>
 
Once you have done this, copy your final kernel '''.elf''' executable that we linked previously into the 'isoroot/boot' directory.
Line 395:
</pre>
 
Congratulations! If all went to plan, you've just produced your first everyever working x86 kernel ISO disk image. This disk image will happily run on emulators like VMWare, QEMU, VirtualBox and Microsoft VirtualPC. If you want to run it on real hardware, simply flash it to a USB or disk drive like you would a Linux distribution LiveCD. For a good tutorial on how to do this, take a look at [[https://help.ubuntu.com/community/BurningIsoHowto Ubuntu: Burning ISO File Tutorial]].
 
Note: The x86 VGA textmode device we rely on in this tutorial is dependent on the existence of the BIOS. This ISO can only be booted properly from a UEFI system if it is in a BIOS compatibility mode (often referred to as 'legacy mode').
Line 418:
 
=== Create A Build System For Your Kernel ===
:''{{Main article: [[|Meaty Skeleton]]}}
 
At the moment, we compile and link our kernel by manually running several commands. As your kernel grows, this will no longer be a realistic way of doing things. You'll need to design and implement a build system that can build your kernel for you. Common kernel build systems use 'make', 'CMake', 'autoconf', 'SCons' or 'Tup'.
 
=== Call Global Constructors ===
:''{{Main article: [[|Calling Global Constructors]]}}
 
In C and particularly C++, the compiler will often generate code that is meant to be run when the program starts. Currently, we don't have any means to run such code. As our kernel grows, we'll need to add support for this.
 
=== Going Further On x86 ===
:''{{Main article: [[|Going Further on x86]]}}
 
There is a whole world of interesting things to explore through operating system development. To improve our kernel further, we will need to better understand the x86 and what hardware we have available.
 
[[:Category:Bare bones tutorials]]
[[:Category:C]]
[[:Category:C++]]
[[Category:User drafts]]