The boot process and CRT

The boot process starts when the kernel is called by the bootloader. What it does is to set up the environment to prepare it for the kernel. This process varies by architecture, the files responsible for it can be found under each platform's HAL under the name start.S. It's usually written entirely in assembly due to the need of close interaction with the hardware, although for some platforms such as ARM, assembly is combined with a bit of C.


On x86 the boot process is very simple. It's written in assembly and composed of three. The first file that is called is start.S:

# Declare constants for the multiboot header.
.set ALIGN, 1<<0 # align loaded modules on page boundaries
.set MEMINFO, 1<<1 # provide memory map
.set FLAGS, ALIGN | MEMINFO # this is the Multiboot 'flag' field
.set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header
.set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot
# Declare a header as in the Multiboot Standard.
.global mboot
.align 4
.long MAGIC
.long FLAGS
# The kernel entry point.
.section .text
.global _start
.type _start, @function
push %esp
push %ebx
# Call the global constructors.
call _init
# Transfer control to the main kernel.
call kinit
# Hang if kernel_main unexpectedly returns.
.hang: jmp .hang
call _fini # swap this to be called before the loop with the first release
.size _start, . - _start

Let's break down this file and analyse it part by part. The first part of the file declares the MultiBoot header. MultiBoot is a standard used by some bootloaders such as GRUB, it allows the kernel to specify how it wants to be loaded. In order to let the bootloader know JSLK complies with this standard a header must be declared. The first lines of this file defines the constants we want the header to include, the second block actually declares the header. Later in the file we can see that the _init function is called. This is because JSLK implements the System V ABI, and to do so the global constructors must be called. This is done by the CRT, which contains some files mainly generated by the compiler to do this. The _init function is found in the crti.S file. Then, we can see that the code call kinit, which is the kernel entry point. Finally, there's a loop so that if the kernel returns because of an error, the hardware doesn't execute trash found further in memory.