Loading Kernel from real mode or protected mode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
bbqribs
Posts: 5
Joined: Sat Aug 23, 2025 8:37 pm

Loading Kernel from real mode or protected mode

Post by bbqribs »

Wondering what the best practice is regarding loading a kernel.
I figure I'll eventually have to write a protected mode disk-reading driver at some point, so I might as well get it out of the way now. Is this a headache that I don't need to endure right now? Am I better off loading my whole kernel in a20 enabled real mode and then copying it in place once I'm in protected mode?
Octocontrabass
Member
Member
Posts: 6248
Joined: Mon Mar 25, 2013 7:01 pm

Re: Loading Kernel from real mode or protected mode

Post by Octocontrabass »

bbqribs wrote: Mon Sep 15, 2025 9:25 amWondering what the best practice is regarding loading a kernel.
Best practice is to use an existing bootloader. Existing bootloaders have already been debugged, and you can get UEFI support for free. :wink:

But if you're going to write your own bootloader, best practice is to rely on the firmware to read the disk.
bbqribs wrote: Mon Sep 15, 2025 9:25 amI figure I'll eventually have to write a protected mode disk-reading driver at some point, so I might as well get it out of the way now.
You'd need more than one driver, since the firmware knows how to boot from more than one type of disk. And you wouldn't want to reuse those drivers for your kernel, since good drivers tend to rely on kernel APIs that are difficult to implement in a bootloader, so you either end up completely rewriting those drivers for your kernel and maintaining two sets of drivers, or you end up turning your bootloader into an entire OS by itself (which will then need its own bootloader).
bbqribs wrote: Mon Sep 15, 2025 9:25 amAm I better off loading my whole kernel in a20 enabled real mode and then copying it in place once I'm in protected mode?
The BIOS has INT 0x15 AH=0x87 for copying stuff above 1MB in real mode.
User avatar
BenLunt
Member
Member
Posts: 1029
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: Loading Kernel from real mode or protected mode

Post by BenLunt »

As always, Octocontrabass has some good points.

One thing to remember, the legacy firmware has only read a single 512-byte sector into memory. Without using this legacy firmware, there is no other way to load additional sectors without writing some kind of driver. Therefore, your driver would have to be written in less than 512 bytes, almost impossible to do, and extremely impossible to do correctly.

The UEFI firmware has the ability to read from (FAT) volumes, as opposed to sectors only, like the Legacy firmware does.

Some may disagree, but I believe, as a hobby builder, you should write your own bootloader code, for the learning experience. You learn very little using an existing loader. However, as stated, using an existing loader gets you to the kernel development from the start.

Ben
- https://www.fysnet.net/osdesign_book_series.htm
bbqribs
Posts: 5
Joined: Sat Aug 23, 2025 8:37 pm

Re: Loading Kernel from real mode or protected mode

Post by bbqribs »

BenLunt wrote: Mon Sep 15, 2025 11:04 am
Your driver would have to be written in less than 512 bytes, almost impossible to do, and extremely impossible to do correctly.
I just used the first sector to write BPB headers and read stage 2 off reserved sectors, no driver. Stage 2 is where I'm planning to enter protected mode and read the kernel as that has a 31 sector limit, which should be enough to get me up and running at least.

Also I am writing my own bootloader as this is a hobby project originally as a way of teaching myself x86 assembly, using GRUB or something would skip all that.
For now I'm just targeting legacy BIOS i386.
User avatar
BenLunt
Member
Member
Posts: 1029
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: Loading Kernel from real mode or protected mode

Post by BenLunt »

bbqribs wrote: Mon Sep 15, 2025 11:23 am I just used the first sector to write BPB headers and read stage 2 off reserved sectors, no driver. Stage 2 is where I'm planning to enter protected mode and read the kernel as that has a 31 sector limit, which should be enough to get me up and running at least.
Without sounding like I am discouraging you from doing that, here are two advantages to do it slightly different.

First, since you state you will have a BPB, you are using FAT, correct? There are some systems (though very few today) that assume the reserved area of a FAT volume is a single sector. Not much a big deal today, but was in the past.

Second, I suggest that you create your 2nd stage loader as a file in the root directory. If you can assume the root directory and the file name, with a little bit of effort, you can write a FAT loader within the almost 475 bytes remaining in the first sector of the volume that will find and load the file. This gives the advantage that when you update the code, you can simply write to the media as a file. No need to write as sectors, and you don't have the 31-sector limit you mention.

To contradict my first comment, I did this in three sectors, but by doing so, I had plenty of space for error handling, checked for a 32-bit machine, checked for BIOS Extended Disk services, allowed fragmented files, as well as the code first looked for the loader file in the root directory. If not found, it tried the \BOOT directory, and finally if not found, it tried the \SYSTEM\BOOT directory. Not really a big deal since your first stage loader should know where your second stage loader is, right? But as an example, it shows that it can be done within the first few sectors of the volume and in assembly.

I won't point you to that code, because it would be too easy to "steal" it, not saying that you would, but it is quite easy to copy, paste, and modify to fit your needs, am I wrong? :-)

There is another advantage to this technique. If your compiler is capable of making a (somewhat) flat executable, the second stage can be written in a higher-level language. Even a simple DOS .EXE file can be easily loaded and "jumped to".

Ben
User avatar
bellezzasolo
Member
Member
Posts: 163
Joined: Sun Feb 20, 2011 2:01 pm

Re: Loading Kernel from real mode or protected mode

Post by bellezzasolo »

BenLunt wrote: Mon Sep 15, 2025 11:04 am As always, Octocontrabass has some good points.

One thing to remember, the legacy firmware has only read a single 512-byte sector into memory. Without using this legacy firmware, there is no other way to load additional sectors without writing some kind of driver. Therefore, your driver would have to be written in less than 512 bytes, almost impossible to do, and extremely impossible to do correctly.

The UEFI firmware has the ability to read from (FAT) volumes, as opposed to sectors only, like the Legacy firmware does.

Some may disagree, but I believe, as a hobby builder, you should write your own bootloader code, for the learning experience. You learn very little using an existing loader. However, as stated, using an existing loader gets you to the kernel development from the start.

Ben
- https://www.fysnet.net/osdesign_book_series.htm

My most recent iteration I just went straight to UEFI, but I still had an OS Loader component... The primary thing it did was load the kernel to the intended high addresses (UEFI loads low), load the configuration file, set video mode, and dynamically link some kernel modules in. The config file could specify boot drivers to include in this.
Whoever said you can't do OS development on Windows?
https://github.com/ChaiSoft/ChaiOS
rdos
Member
Member
Posts: 3396
Joined: Wed Oct 01, 2008 1:55 pm

Re: Loading Kernel from real mode or protected mode

Post by rdos »

UEFI is almost always 64-bit, and so will transfer control in long mode. If your OS is 64-bit, this would be fine, but for a protected mode OS, you will need an additional layer that switches the processor to protected mode. For BIOS, you always know the processor is in real-mode, so the initialization is always the same.
User avatar
BenLunt
Member
Member
Posts: 1029
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: Loading Kernel from real mode or protected mode

Post by BenLunt »

bellezzasolo wrote: Tue Sep 16, 2025 9:56 amMy most recent iteration I just went straight to UEFI, but I still had an OS Loader component... The primary thing it did was load the kernel to the intended high addresses (UEFI loads low), load the configuration file, set video mode, and dynamically link some kernel modules in. The config file could specify boot drivers to include in this.
I do something very similar, one difference being that I don't load into high memory. The way I manage memory, there is no need. I have three "segments" of memory. One is below 1Meg, just in case. One is below 16Meg for legacy hardware, and then the last is the remaining up to 32-gig, whether the memory is physically present or not. Except for those three exceptions, nothing relies on where it is in memory.
rdos wrote: Fri Sep 19, 2025 1:40 amUEFI is almost always 64-bit, and so will transfer control in long mode.
When it comes to real hardware, I agree that it will almost always be 64-bit. However, with emulators, it can be either 64- or 32-bit. Therefore, my code requires 64-bit UEFI, but I have written a small stub for 32-bit UEFI which states a 64-bit system is required, then draws and allows the user to play increasingly challenging levels of Tetris. Very similar to what I did in case a Legacy BIOS is used.
Post Reply