“Hello World” Boot Loader


Ever wondered what a boot loader is….??

A boot loader is a computer program (assembly language) that loads the Operating System  to the main memory. Boot loaders generally reside on the first sector of the memory. When we switch on a computer, the first program that runs is the BIOS which performs certain tests and them passes the CPU control to the Master Boot Record(MBR) which contains the boot loader program. Some of the most common linux boot loaders are LInux LOader(LILO), GRand Unified Boot loader(GRUB), LOAD LInux(LOADLIN), etc.

Again i was given the task of creating a custom boot loader program. First thing that came up when i researched, was that the boot loader programs are written in low level assembly language. Then we have to compile it using the NASM assembler. Then create an image of the boot loader to load in the memory. Lets take a step by step approh.

Step 1 :
Create the boot loader program

BITS 16                     
jmp main                    
nop                         
main:
    mov ax, 07C0h           
    add ax, 288             
    mov ss, ax
    mov sp, 4096
    mov ax, 07C0h           
    mov ds, ax              
    call PrintHelloWorld    
    jmp .InfiniteLoop
    .InfiniteLoop:          
        jmp .InfiniteLoop   

HelloWorld      db  "Hello World. This is from the bootloader", 0x0d, 0x0a, 0x00
PrintHelloWorld:            
    mov si, HelloWorld      
    call PrintStr           
    ret
PrintStr:                   
    push ax                 
    mov ah, 0Eh             
    .loop:
        lodsb               
        cmp al, 0x00        
        je .done
        int 10h             
        jmp .loop
    .done:
        pop ax              
        ret
times 510-($-$$) db 0       
dw 0xAA55

Step 2
Compile the Code

You can compile the boot loader program using ‘nasm’ command.

nasm -f bin -o hello_world_bootloader.bin hello_world_bootloader.asm

Step 3
Create Boot loader image

You need to create an empty file that will serve as the final image holding the bootloader. The command to create the file is given below.

dd if=/dev/zero of=hello_world_bootloader.img bs=512 count=2880

Now copy the bin file content to the image file

dd status=noxfer conv=notrunc if=hello_world_bootloader.bin of=hello_world_bootloader.img

Step 4
Testing your boot loader program

You can test your program using ‘qemu’ emulator

Command for 32-bit systems :

qemu-system-i386 hellow_world_bootloader.bin

Command for 64-bit systems :

qemu-system-x86_64 hello_world_bootloader.bin

Or

You can load the image file(.img) created in step 3 to a virtual machine and see your boot loader in action.

Advertisements

Hello World System Call


This was given to me as an assignment in my Operating Systems Lab. It took me a lot of time to finally crack it. So i thought of putting it up in my blog.  I implemented it on Ubuntu 12.04 LTS running on a virtual machine.

We will take a step by step approach in getting it done.

Step 1
Get a linux source

Ubuntu doesn’t come with the full linux source. So you may have to download it either from websites like kernel.org or you can download it using the following command.

sudo apt-get install linux-source

This downloads a tar.bz2 file to the /usr/src folder. Extract it to any folder you like and that will be your linux source root folder from now on.

Step 2
Add your custom system call to System Call Table

Open the file arch/x86/kernel/syscall_table_32.S and append the following line to the file

.long sys_hello_world

Step 3
Define the macros associated with your system call

Open the file arch/x86/include/asm/unistd_32.h. The file contains macro definitions for all the system calls. We have to add a macro for our system call in this file. Each system call is assigned an index number. My file had 348 such macro definitions. Hence i added my call indexed as 349 by adding the following line in the file.

#define __NR_hello_world 349

Do the same with the uistd_64.h file @ arch/x86/include/asm/unistd_64.h

#define __NR_hello_world 312
__SYSCALL(__NR_hello_world, sys_hello_world)

Now open the file include/linux/syscalls.h and add a prototype to your system call function

asmlinkage long sys_hello_world(void);

Now in the root directory in the kernel, create a folder named hello_world and create a file named hello_world.c with the following code

#include<linux/kernel.h>

asmlinkage long sys_hello_world(void){
printk("Hello World\n");
return 0;
}

Step 5
Pre-Compilation Settings

Create a file named Makefile within the hello_world directory and the following line to the file

obj-y := hello_world.o

This is done to ensure that the hello_world.c file is compiled and included in the new system kernel.
Now open the Makefile in the root directory(Source-linux), and change the following line

core-y          += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

to

core-y          += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ hello/

This is to tell the compiler that the source for the new system calls are available at the /hello_world directory

Step 6
Compile the kernel

You can compile the kernel using the following commands

sudo make

Now you have enough time to watch a football match until the compilation completes. Once compilation is done, reboot your system.

Step 7
Install the new kernel

sudo make modules_install install

Step 8 Check if your system call actually works

Create the following program and run it to check whether the system call works

#include <stdio.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>

#define __NR_hello_world 312

long hello_syscall(void) {
    return syscall(__NR_hello_world);
}

int main(intargc, char*argv[]) {
    long int a = hello_world_syscall();
    printf("System call returned %ld\n", a);
    return 0;
}

The program should output the following

System call returned 0

The printk() in the system call program will be updated in the system log which can be viewed using the following command.

dmesg

If everything works well, you can find your system call listed in the system log.