Build Your Own OS #6

User modes

There are two modes of operation in the operating systems. These are user mode and kernel mode.

Loading an External Program

Usually, operating systems have drivers and file systems that enable them to load the software from a CD-ROM drive, a hard disk or other persistent media.

GRUB modules

GRUB can load any arbitrary into the memory from the ISO image. Those files are usually referred to as modules.

module /modules/program
mkdir -p iso/modules

Creating a program

Then we have to create a very simple program and compile it to make a binary file from that. Copy the following code and save it in a file called program.s in the /modules directory.

; test module à copier dans iso/modules                           
; set eax to some distinguishable number, to read from the log afterwards
bits 32
start:
mov eax, 0xDEADBEEF ; enter infinite loop, nothing more to do
jmp start

Compiling the program

In order to run the above created program, we need to compile it first. Since our kernel cannot parse advanced executable formats we need to compile the code into a flat binary. NASM can do this with the flag -f:

nasm -f bin program.s -o program

Instruct the GRUB

To instruct GRUB how to load our modules, the “multiboot header” — the first bytes of the kernel — must be updated as follows:

; in file `loader.s`


MAGIC_NUMBER equ 0x1BADB002 ; define the magic number constant
ALIGN_MODULES equ 0x00000001 ; tell GRUB to align modules

; calculate the checksum (all options + checksum should equal 0)
CHECKSUM equ -(MAGIC_NUMBER + ALIGN_MODULES)

section .text: ; start of the text (code) section
align 4 ; the code must be 4 byte aligned
dd MAGIC_NUMBER ; write the magic number
dd ALIGN_MODULES ; write the align modules instruction
dd CHECKSUM ; write the checksum

Finding the Program in Memory

Before jumping to the program we must find where it resides in memory. Assuming that the contents of ebx is passed as an argument to kmain, we can do this entirely from C.

int kmain(/* additional arguments */ unsigned int ebx)
{
multiboot_info_t *mbinfo = (multiboot_info_t *) ebx;
unsigned int address_of_module = mbinfo->mods_addr;
}

Jumping to the Code

The only thing left to do is to jump to the code loaded by GRUB. Since it is easier to parse the multiboot structure in C than assembly code, calling the code from C is more convenient (it can of course be done with jmp or call in assembly code as well). The C code could look like this:

typedef void (*call_module_t)(void);
/* ... */
call_module_t start_program = (call_module_t) address_of_module;
start_program();
/* we'll never get here, unless the module code returns */

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store