software development site map

How To Develop Your Own Boot Loader
We will describe what is going after you turn on a computer; how the system is loading. As the practical example we will consider how you can develop your own boot loader which is actually the first point of the system booting process.
Author:
Alexandr Kolesnyk,
Junior Software Developer of ApriorIT Inc.
Who may be interested
Most of all I’ve written this article for those who have been always interested in the way the different things work. It is for those developers who usually create their applications in high-level languages such as C, C++ or Java, but faced with the necessity to develop something at low-level. We will consider low-level programming on the example of working at system loading.
We will describe what is going after you turn on a computer; how the system is loading. As the practical example we will consider how you can develop your own boot loader which is actually the first point of the system booting process.
What is Boot Loader
Boot loader is a program situated at the first sector of the hard drive; and it is the sector where the boot starts from. BIOS automatically reads all content of the first sector to the memory just after the power is turned on, and jump to it. The first sector is also called Master Boot Record. Actually it is not obligatory for the first sector of the hard drive to boot something. This name has been formed historically because developers used to boot their operating systems with such mechanism.
Be ready to go deeper
In this section I will tell about knowledge and tools you need to develop your own boot loader and also remind some useful information about system boot.
So what language you should know to develop Boot Loader
On the first stage on the computer work the control of hardware is performed mainly by means of BIOS functions known as interruptions. The implementation of interruptions is given only in Assembler – so it is great if you know it at least a little bit. But it’s not the necessary condition. Why? We will use the technology of “mixed code” where it is possible to combine high-level constructions with low-level commands. It makes our task a little simpler.
In this article the main development languages is C++. But if you have brilliant knowledge of C then it will be easy to learn required C++ elements. In general even the C knowledge will be enough but then you will have to modify the source code of the examples that I will descried here.
If you know Java or C# well unfortunately it won’t help for our task. The matter is that the code of Java and C# languages that is produced after compilation is intermediate. The special virtual machine is used to process it (Java Machine for Java, and .NET for C#) which transform intermediate code into processor instructions. After that transformation it can be executed. Such architecture makes it impossible to use mixed code technology – and we are going to use it to make our life easier, so Java and C# don’t work here.
So to develop the simple boot loader you need to know C or C++ and also it would be good if you know something about Assembler – language into which all high-level code is transformed it the end.
What compiler you need
To use mixed code technology you need at least two compilers: for Assembler and C/C++, and also the linker to join object files (.obj) into the one executable.
Now let’s talk about some special moments. There are two modes of processor functioning: real mode and safe mode. Real mode is 16-bit and has some limitations. Safe mode is 32-bit and is fully used in OS work. When it starts processor works in 16-bit mode. So to build the program and obtain executable file you will need the compiler and linker of Assembler for 16-bit mode. For C/C++ you will need only the compiler that can create object files for 16-bit mode.
The modern compilers are made for 32-bit applications only so we won’t able to use them.
I tried a number of free and commercial compilers for 16-bit mode and choose Microsoft product. Compiler along with the linker for Assembler, C, C++ are included into the Microsoft Visual Studio 1.52 package and also can be downloaded from the official site of the company. Some details about compilers we need are given below.
ML 6.15 – Assembler compiler by Microsoft for 16-bit mode;
LINK 5.16 – the linker that can create .com files for 16-bit mode;
CL – ?, ?++ compiler for 16-bit mode.
You can also use some alternative variants:
DMC – free compile for Assembler, C, C++ for 16 and 32-bit mode by Digital Mars;
LINK – free linker for DMC compiler;
There are also some products by Borland:
BCC 3.5 – ?, ?++ compiler that can create files for 16-bit mode;
TASM – Assembler compiler for 16-bit mode;
TLINK – linker that can create .com files for 16-bit mode.
All code examples in this article were built with the Microsoft tools.
How system boots
In order to solve our task we should recall how the system is booting.
Let’s consider briefly how the system components are interacting when the system is booting (see Fig.1).
Fig.1 – “How it boots”
After the control has been passed to the address 0000:7C00, Master Boot Record (MBR) starts its work and triggers the Operating System boot. You can learn more about MBR structure for example here – http://en.wikipedia.org/wiki/Master_boot_record.
Let’s code
In the next sections we will be directly occupied with the low-level programming – we will develop our own boot loader.
Program architecture
Boot loader that we are developing is for the training only. Its tasks are just the following:
- Correct loading to the memory by 0000:7C00 address.
- Calling the BootMain function that is developed in the high-level language.
- Show “”Hello, world…”, from low-level” message on the display.
Program architecture is described on the Fig.2 that is followed by the text description.
Fig.2. – Program architecture description
The first entity is StartPoint that is developed purely in Assembler as far as high-level languages don’t have the necessary instructions. It tells compiler what memory model should be used, and what address the loading to the RAM should be performed by after the reading from the disk. It also corrects processor registers and passes control to the BootMain that is written in high-level language.
Next entity– BootMain – is an analogue of main that is in its turn the main function where all program functioning is concentrated.
CDisplay and CString classes take care of functional part of the program and show message on the screen. As you can see from the Fig.2 CDisplay class uses CStringclass in its work.
Development environment
Here I use the standard development environment Microsoft Visual Studio 2005 or 2008. You can use any other tools but I made sure that these two with some settings made the compiling and work easy and handy.
First we should create the project of Makefile Project type where the main work will be performed (see Fig.3).
File->NewProject->GeneralMakefile Project
Fig.3 – Create the project of Makefile type
BIOS interruptions and screen clearing
To show our message on the screen we should clear it first. We will use special BIOS interruption for this purpose.
BIOS proposes a number of interruptions for the work with computer hardware such as video adapter, keyboard, disk system. Each interruption has the following structure:
int [number_of_interrupt];
where number_of_interrupt is the number of interruption
Each interruption has the certain number of parameters that should be set before calling it. The ah processor register is always responsible for the number of function for the current interruption, and the other registers are usually used for the other parameters of the current operation. Let’s see how the work of int 10h interruption is perforemed in Assembler. We will use the 00 function that changes the video mode and clears screen:
mov al, 02h ; setting the graphical mode 80×25(text)
mov ah, 00h ; code of function of changing video mode
int 10h ; call interruption
We will consider only those interruptions and functions that will be used in our application. We will need:
int 10h, function 00h – performs changing of video mode and clears
; screen;
int 10h, function 01h – sets the cursor type;
int 10h, function 13h – shows the string on the screen;
«Mixed code»
Compiler for C++ supports the inbuilt Assembler i.e. when writing code in igh-level language you can use also low level language. Assembler Instructions that are used in the high level code are also called asm insertions. They consist of the key word __asm and the block of the Assembler instructions in braces:
__asm ; key word that shows the beginning of the asm insertion
{ ; block beginning
… ; some asm code
} ; end of the block
To demonstrate mixed code let’s use the previously mentioned Assembler code that performed the screen clearing and combine it with C++ code.
void ClearScreen()
{
__asm
{
mov al, 02h ; setting the graphical mode 80×25(text)
mov ah, 00h ; code of function of changing video mode
int 10h ; call interruption
}
}
CString implementation
CString class is designed to work with strings. It includes Strlen() method that obtains pointer to the string as the parameter and returns the number of symbols in that string.
// CString.h
#ifndef __CSTRING__
#define __CSTRING__
#include “Types.h”
class CString
{
public:
static byte Strlen(
const char far* inStrSource
);
};
#endif // __CSTRING__
// CString.cpp
#include “CString.h”
byte CString::Strlen(
const char far* inStrSource
)
{
byte lenghtOfString = 0;
while(*inStrSource++ != ‘