OKL4 Boot Sequence
The boot sequence is the set of operations performed to load an operating system; since most computers can only execute code stored on system's ROM or RAM, and hardware alone cannot load a program from a disk or other removable media, a sort of operating system itself is needed to load another much more complex operating system. This process is known as bootstrapping. A very small program or set of programs called a bootstrap-loader or bootloader is used to load into memory the necessary software for an operating system to start. OKL4 is no exception: it all starts with a bootloader, which is up to the user to select. The bootloader must boot the constructed image.boot, located in:
The OKL4 microkernel's entry point is architecture dependent. One might be led to believe that the main() function would be the first function to receive control - since this is the first user function to be called in an application - but the real entry function is called _start, which commonly sets up the environment, opens descriptors, and then invokes that main() we all know. The boot loader expects a declaration of _start from the first loaded file, so the kernel needs to define it.
OKL4 defines _start in a platform-specific assembly file. We'll use the example of IA32/PC99 for the rest of this explanation. _start is located in:
in which interrupts are disabled, a temporary stack pointer is loaded, and a jump is made to a platform-specific arch_init() function.
arch_init() is located at:
Timer initialization is performed by calling init_clocks(), located in:
which assigns the IRQ time tick interrupt to the timer_interrupt() function (located in the same file). When a time tick interrupt occurs, timer_interrupt ACKs the interrupt and then triggers the scheduler_handle_timer_interrupt method.
The generic_init function is located at:
which initialises Mutex and CapabilityList support, and calls startup_scheduler (located in the same file). startup_scheduler calls the init function on the current scheduler, creates the idle thread, sets the idle thread to run init_all_threads (by using the notify function on the idle thread TCB), and starts the current scheduler.
The scheduler class code is located in:
The schedule::init function initializes the priorities queue. The schedule:start function switches to the idle thread, which runs init_all_threads, located in the same file.
init_all_threads initialises the root server threads by calling init_root_servers, located in:
The RootServer runs in the root address space, giving it special access rights. Finally, init_all_threads becomes the proper idle thread by scheduling itself to call idle_thread.
If iguana is specified as the project to the build system (via argument project=iguana), then IguanaServer is set to be RootServer. By this stage the kernel is established and able to load user applications. _start is still our first function, but this time it's the standard libc _start, located in:
The standard _start calls __sys_entry, located in:
which initialises all libraries (such as stdio, setting up file descriptors etc.), and finally calls main().
IguanaServer's main() is located in:
OK Linux entry point is again a main() function and can be found at:
In main, a new thread is created called the main_thread and labeled L_Syscall. This thread is responsible for initialising the kernel and handling TrampolineSyscalls; it's execution is started at the start_kernel function. The initial thread which created L_Syscall renames itself as L_timer and will be responsible for acting as Linux's ISR.
L_timer code can be found in the interrupt_loop() function, located at:
which initially is woken by the main_thread, then the timer is initialized and enters an infinite loop which handle interrupts, forwarding them to the main_thread if necessary and signaling the linux scheduler when timer interrupts occur.
As mentioned, the L_Syscall thread begins execution with the start_kernel function, located in:
in which several aspects of the Linux kernel are initialised, such as the scheduler, signals and page writebacks. The L_timer thread is then woken up, and finally rest_init is called, in which /sbin/init, /etc/init, bin/init, and /bin/sh init processes are run via the run_init_process() function.
Acknowledgment: Guide by Jorge Torres, via http://lists.okl4.org/pipermail/developer/2007-June/000190.html