Building My Own Operating System — Savitar OS

Asitha Nuwan
7 min readJul 16, 2021

--

This is the very first article in a series of articles. Today I’m going to tell you how to build a operating system.An operating system is simply known as a software that communication with the hardware and allows other programs to run.Every computer,smart phone and tablet includes an OS.So we will make a basic OS that provides basci functionality for the device. Let’s get started.

Step 1-Set up

In this part we are talking about what tools and technologies we are going to use for this development.

First of all we need to install the Oracle virtual box.

This is the link for it

https://www.virtualbox.org/wiki/Downloads

after that we need to install the ubuntu ISO file

This is the link for it

https://ubuntu.com/download/desktop

1.1 Quick setup

After ubuntu is installed (physical or virtual),following packages should be installed using apt-get:

You can install them using the this command in your terminal

“ sudo apt-get install build-essential nasm genisoimage bochs bochs-sdl ”

1.2 Programming languages

This operating system will be developed using the C programming language using GCC.when we developing a operating system it requires very precise control of the generated code and direct memory access because of that we use C programming language for this.you can use hypothetically write as OS in any programming language but in this we use C language.

The code will make use of the type attribution that is specific for GCC:

__attribute__((packed))

1.3 Host operating system

Ubuntu is used as the host operating system in this development. All code examples have been successfully compiled using ubuntu 11.04 and 11.10.All the code examples assume that the code is being compiled on a UNIX like operating system.

1.4 Virtual machine

When we developing an operating system it convenient t be able to run your code in a virtual machine instead of on a physical computer. The reason for this is starting the

Operating system in a virtual machine is way faster that getting the OS onto a physical medium and then running it on a physical machine. So boches will be used as our virtual machine in this development.

Step 2-Booting

Booting is the initial set of operations that a computer system performs when the electrical power to the CPU is switched on.Booting an operating system consists of transferring control along a chain of small programs namelynamelyand bootloader, each of them more powerful than the previous one,where the operating system is the last program.

2.1 BIOS

Basic input output system(BIOS)stored on a read only memory chip on thr motherboard of the computer. It’s start when the computer is turned on.It includes instructions on how to load basic computer hardware. Those BIOS programs was originally used to export some library functions for printing to the screen,reading keyboard inputs etc but today BIOS runs some early diagnostics,and then transfers controls to the bootloader.

2.2 Bootloader

This program transfers control to the operating system developers. This has two parts.The first part will transfer control to the second part and that gives control of the PC to the operating system.

Bootloader involves write a lot of low level codes that interacts with the operating system. So we aren’t write a bootloader in this.We will use an existing bootloader called the GNU Grand Unified Bootloader (GRUB).using GRUB ,the operating system can be built as an ordinary ELF executable, it will be loaded by GRUB into the correct memory location.

2.3 The operating system

GRUB transfers control to the operating system by jumping to a relevant position in memory. Before jump,GRUB will look for a magic number to ensure that it is actually jumping to an operating system and not some random code.This magic number is a part of the multiboot specification[19]which GRUB adhers to once GRUB has made the jump,the operating system has full control of the computer.

Step 3-development Process

This article will describe how to implement a small operating system that can be used together with GRUB.The only thing the operating system will do is write 0xCAFEBABE to the eax register.

First of all make a folder with a name of your choice.you must create all the files and sub folders in this folder.

3.1 Compiling the operating system

Save the following assembly code in a file called loader.s

“global loader ; the entry symbol for ELF

MAGIC_NUMBER equ 0x1BADB002 ; define the magic number constant

FLAGS equ 0x0 ; multiboot flags

CHECKSUM equ -MAGIC_NUMBER ; calculate the checksum

; (magic number + checksum + flags should equal 0)

section .text: ; start of the text (code) section

align 4 ; the code must be 4 byte aligned

dd MAGIC_NUMBER ; write the magic number to the machine code,

dd FLAGS ; the flags,

dd CHECKSUM ; and the checksum

loader: ; the loader label (defined as entry point in linker script)

mov eax, 0xCAFEBABE ; place the number 0xCAFEBABE in the register eax

.loop:

jmp .loop ; loop forever”

the file loader.s can be compiled into a 32 bits ELF object file using the following command:

“nasm -f elf32 loader.s”

Now you can see the file in the folder.

3.2 Linking the Kernel

Now the code must be linked to produce an executable file.The GRUB needs to load the kernel to the memory. For that we need the following linking script. GRUB will load the kernel at a memory address larger than or equal to 1MB because all the GRUB it self,BIOS and memory-mapped I/O use address lower than 1MB.

Open your text editor and type the following linking script:

“ENTRY(loader) /* the name of the entry label */

SECTIONS {
. = 0x00100000; /* the code should be loaded at 1 MB */

.text ALIGN (0x1000) : /* align at 4 KB */
{
*(.text) /* all text sections from all files */
}

.rodata ALIGN (0x1000) : /* align at 4 KB */
{
*(.rodata*) /* all read-only data sections from all files */
}

.data ALIGN (0x1000) : /* align at 4 KB */
{
*(.data) /* all data sections from all files */
}

.bss ALIGN (0x1000) : /* align at 4 KB */
{
*(COMMON) /* all COMMON sections from all files */
*(.bss) /* all bss sections from all files */
}
} ”

Save the linker script into a file called: link.ld

Now the executable can be linked with the following command:

ld -T link.ld -melf_i386 loader.o -o kernel.elf

Now you can see the final executable here:

kernel.elf.

3.3 Obtaining GRUB

The GRUB version we will use is GRUB Legacy since the operating system ISO image can then be generated on systems using both GRUB Legacy and GRUB 2.more specifically, the GRUB Legacy stage2_eltorito bootloader will be used.

The file can be downloaded here:

Then copy the file stage2_eltorito to your folder

3.4 Building as ISO Image

The executable must to placed on a media that can be loaded by a virtual or physical machine. The ISO image files will be used as the media here.We will create the kernel ISO image using the program genisoimage .First the folder must be created that contains the files that will be on the ISO image.The following commands create the folder and copy the files to their correct place.

mkdir -p iso/boot/grub # create the folder structure
cp stage2_eltorito iso/boot/grub/ # copy the bootloader
cp kernel.elf iso/boot/ # copy the kernel

A configuration file menu.lst for GRUB must be created and the following details must be saved.

default=0
timeout=0

title os
kernel /boot/kernel.elf

Place the file menu.lst in the folder iso/boot/grub/.Now the contents of the folder should look like following figure.

iso
| — boot
| — grub
| | — menu.lst
| | — stage2_eltorito
| — kernel.elf

Then the ISO image can be generated withe the following command:

genisoimage -R \
-b boot/grub/stage2_eltorito \
-no-emul-boot \
-boot-load-size 4 \
-A os \
-input-charset utf8 \
-quiet \
-boot-info-table \
-o os.iso \
iso

The ISO image os.isonow contains the kernel executable,the GRUB bootloader and the configuration file.

3.5 Running Bochs

Now we can run the operating system in the bochs emulator using the os.iso ISO image.Bochs needs a configuration file to start.an example for it is given below:

megs: 32
display_library: sdl
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
ata0-master: type=cdrom, path=os.iso, status=inserted
boot: cdrom
log: bochslog.txt
clock: sync=realtime, time0=local
cpu: count=1, ips=1000000

Save the Bochs configuration in a file called:

bochsrc.txt

Depending on how you installed Bochs you might need to change the path of and.

(For further information,browse the Boch’s website)

After that you can run Bochs with the following command:

bochs -f bochsrc.txt -q

After quitting Bochs,display the log produced by Boch:

cat bochslog.txt

Contents of the registers of the CPU simulated by Bochs will be display in the output on the terminal.If you find,

RRAX00000000CAFEABE or EAX=CAFEBABE in the outputyour Operating System has successfully booted!

Now you are a owner of a pocket operating system!

Hope to see you form the next article.

--

--

Responses (1)