Let’s continue from where we left off. After long mode check is passed, what we are going to do next is we are going to
load our kernel file.
As we have loaded the loader file, loading kernel
is pretty much the same except that there are several parameters need to change.
So we just copy and paste the code here.
We create a label called load kernel
First off, we take a look at memory map and decide where we load the kernel file into memory.
As you can see, this is a rough demo of the memory usage in the boot process. At the bottom we have the interrupt vectors
and bios data.
Then we get a small area of free memory. At address 7c00 our boot code is loaded by the BIOS.
And the boot code load the loader file at address 7e00. Then we get
a relatively large area of free memory we can use. Our kernel can be loaded here.
The area above it is reserved for hardware and bios data. Starting from 100000 which is 1mb,
we have free memory again.
Note that this area also gets some space reserved for hardware which is not available for us.
And the memory map may vary among different computers. Therefore, we need to get a memory map
by calling the bios service so that we know which part of the memory is available to use.
We will see how to do it in the next lecture.
So with this in mind, we choose to load the kernel at address 10000
and when we jump to 64-bit mode, we copy the kernel into the memory above 1mb.
Alright, back to our file.
here we want to load 100 sectors of data roughly 50 kilobytes which is enough for our kernel.
The memory address we choose to load the kernel at is 10000.
Note that we cannot assign 10000
to a word variable.
10000 in hexadecimal is larger than what a word or two bytes can represent.
We will get an overflow and result is not correct if we do it
.
Instead, we assign
1000 to segment part of the address
and leave offset 0. The physical address we get is 1000*16+0 equals 10000.
The boot file resides in the first sector.
The loader file occupies the next five sectors.
So we write our kernel from the seventh sector.
We write 6,
remember sector value is zero-based value.
Don’t forget to check carry flag. If carry flag is set after calling the read service,
we know that loading kernel failed, and we jump to read error and stop here.
we place the label read error at the end of the code.
We haven't defined the read packet, so we define the read packet here.
Remember the package is a structure which is 16 bytes
If everything goes as expected, we just print the message
kernel is loaded.
OK, we save the file and build the project in the terminal.
OK, the binary file is written into the boot image and also it's worth mentioning that we don't actually
load the kernel file into memory because we didn't create the kernel file at this point.
So the code in this example just reads whatever is in the image and load it into memory.
In the next section, we will load the real kernel.
So right now we only print the message on the screen.