Part 1.1.3 Boot Process
In this part of the tutorial, we will introduce the booting process of the computer, from the time we tap on the power button of the computer to the time our Operating System begins to run. This process involves a chain of programs. One example is illustrated in the figure below. When the computer first powers on, it is “hardcoded” to run a small program, BIOS. BIOS then loads and calls the entry function of a larger program, bootloader. The bootloader then loads our Operating System into memory and calls the entry function. (Line 19 of start.S in Part 1.1.2)
A computer generally has two types of memory: volatile and non-volatile memory. When a computer is powered off, all the data stored on volatile memory is lost while those stored on non-volatile memory are not.
Non-volatile memory includes read-only memory (ROM) and hard drives. Data or program stored in ROM is set during manufacture and cannot be electronically modified after the manufacture of the memory device. ROM usually stores code or data that are rarely changed. One example is the BIOS program. Hard drives on the other hand hold almost all of the user programs and data.
However CPU requires the code or data to be inside one type of volatile memory, called random-access memory or RAM. (Since ROM is non-modifiable and hard drives can be slow.) RAM is usually referred to as physical memory and cannot persist data when the computer is powered off (given that it is one type of volatile memory). Therefore before we run a program, be it Operating System or user program, we need to load it from hard drives to physical memory.
BIOS is a program pre-installed on virtually all personal computers and is stored in ROM. The computer is “hardcoded” to run the BIOS program when it powers on. BIOS first does some hardware initialization and testing. After which, it loads a special program called bootloader from some storage device, such as hard drive or CD, and calls the entry function of the bootloader. BIOS doesn’t know which program is the bootloader or where the bootloader is located in the hard drives. It simply loads the first sector (512 bytes) of the hard drive and runs the code inside it. Therefore we need to place our bootloader inside the first sector.
Bootloader is a program that loads our Operating System into memory and transfers control to it. When the bootloader loads our Operating System, it will read the memory layout information from the Operating System program and load the code to the location we specified in the link.ld file. After that, it calls the entry function of the Operating System, `start`.
In this tutorial, we will make use of GRUB instead of writing our own bootloader. The GRUB program can be downloaded at our Github project. [https://github.com/megstechcorner/meg-os/tree/part-1.1-bare-bone-os]
Our Operating system needs to put some “magic” number at the beginning so that it can be recognized by GRUB. (Line 15–17 of start.S)
Putting it together
First download the file, stage2_eltorito, from our Github project. This file contains the GRUB bootloader we need.
Next we need to create a configuration file for GRUB, menu.lst. It tells GRUB where the kernel file is located.
To generate the Operating System image file, os.iso, we need to set up a directory structure as follows.
Finally, we need to run the `genisoimage` command line to generate the os.iso file. To save time, we provide a makefile that contains the instructions to set up the directory structure and runs the `genisoimage` command line.
To generate the os.iso file, we only need to run
> make os
We can then run the Operating System using QEMU. -cdrom option tells QEMU to use os.iso as CD-ROM image. (This simulates the process of burning the Operating System program to a CD and installing the OS with the CD.) -monitor flag tells QEMU to redirect monitor input and output to our command line. QEMU monitor allows users to issue some commands to the QEMU simulator. GDB doesn’t work well with os.iso file, therefore we use the QEMU monitor to inspect the register content instead.
> qemu-system-x86_64 -cdrom os.iso -monitor stdio
To verify the content of the registers, we can run another command
> (qemu) info registers
We should then be able to see that register EAX did have the correct content.