This page looks best with JavaScript enabled

MercuryOS Boot Sector

 ·  🎃 kr0m

Who hasn’t fantasized about programming their own OS? This utopia can materialize with minimal knowledge of assembly and C. In this article, we will explain the boot process of a computer and how to boot our super-reduced OS.

To perform all our tests, we will need an ASM compiler and the qemu emulator. We will use qemu instead of a virtualization system like VirtualBox because the latter would execute instructions directly on our CPU for superior performance, but the environment may not be exactly the same as that of a physical machine. With an emulator, we can achieve this.

Depending on the OS, we will install the software in one way or another:

FreeBSD:

pkg install nasm qemu

Gentoo:

emerge -av dev-lang/nasm app-emulation/qemu

The article is based on the following document posted on the University of Birmingham website 2 ..

First of all, we must bear in mind that when a computer starts up, the first thing it does is load the BIOS from the integrated chip on the motherboard into RAM, and then perform a basic hardware check.

Once the hardware has been checked, it remains to determine where to boot from. The BIOS simply reads the first 512 bytes (boot sector) of all available disks in the system. If any of them contain the values AA 55 in bytes 511 and 512, it considers it to be a bootable disk.

These first 512 bytes are called the boot sector, and they are the instructions that will be loaded into RAM and then executed by the CPU.

We are going to create a very simple boot sector, we will simply mark bytes 511 and 512 with AA 55 so that the BIOS recognizes it as a valid boot sector, fill 510 bytes with 0s to reach a total of 512, and stay executing an infinite loop.

Remember that the CPU will blindly read from RAM what we have loaded from the first 512 bytes of the disk, if we did not define the infinite loop the CPU would continue reading RAM and executing random instructions, remains of previous program loads, this can be more or less dangerous depending on the instructions in question.

vi boot_sect_simple.asm
; Infinite loop (e9 fd ff)
loop:
    jmp loop 

; Fill with 510 zeros minus the size of the previous code
times 510-($-$$) db 0
; Magic number
dw 0xaa55

We generate the image:

nasm -f bin boot_sect_simple.asm -o boot_sect_simple.bin

We can see the content with xdd:

xxd boot_sect_simple.bin

00000000: ebfe 0000 0000 0000 0000 0000 0000 0000  ................  
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000030: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000040: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000080: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000090: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000000a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000000b0: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000000d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000000e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000000f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000100: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000110: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000120: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000140: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000150: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000160: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000170: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000180: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
00000190: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000001a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000001b0: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000001c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000001d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................  
000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

We load it into qemu:

qemu-system-x86_64 boot_sect_simple.bin

SeaBIOS (version rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org)  
iPXE (http://ipxe.org) 00:03.0 C980 PCI2.10 PnP PMM+07F91410+07EF1410 C980  
  
Booting from Hard Disk...

Impressive, we have been able to load our OS from scratch.

If you liked the article, you can treat me to a RedBull here