I'm new to both OS development and these forums, but I've really enjoyed the learning experience so far. I have what I think is likely quite a simple implementation question, but I was interested as to how other people may have approached this, I get the feeling there is a better way but I've finally got something working and wanted to query the knowledgeable people on the forums about it.
So far, I've got a simple bootloader written that loads (via FAT12) a stage2 binary file, which sets up a GDT and jumps into protected mode. I've been testing via bochs and all seems OK up till this point. It dawned on me that I would now like to start writing in C as I'm much more comfortable in it than assembly, and I wanted to compile the kernel as ELF. Trouble was I didn't fancy an ELF loader in asm, so I wanted to transition from assembly into C code.
So now I have this:
Stage 1 Bootloader - 512 byte loader, parses FAT12 directory for stage2.bin, loads it at 0x0050:0x0000 and jumps to it
Stage 2 - File on FAT12 floppy, sets up GDT, enables A20 address line and protected mode.
Stage 3 - Desired to be written in C to do ELF loading of yet unwritten "kernel.bin".
It was the transition between Stage 2 and Stage 3 (please forgive my likely incorrect naming of the stages) that puzzled me. In the end what I've done is pad the stage 2 file up to a known mark, in my case 1024 bytes and then compile my C code as a flat binary and concatenate it with the stage2 file. Then, when stage2.bin is loaded from disk it includes the C portion at a known offset which I can jump to.
I tell via linker script that it's loaded at Stage2 load offset plus the 1024 byte offset (0x0500 + 1024 = 0x0900) and have stage2 jump to the end of it's section.
So stage 2 looks like:
Code: Select all
ORG 0x500
bits 16:
.
ProtectedMode, A20 and GDT setup
.
pmode:
jmp stage2_kernel_loader
.
times 1024 - ($-$$) db 0
stage2_kernel_loader:
Code: Select all
ENTRY(kernel_main)
OUTPUT_FORMAT(binary)
SECTIONS
{
/* Stage2 is loaded at 0x0000:0x0500 and is padded to be 1024 bytes. Therefore 0x0500 + 0x400 = 0x900 */
. = 0x00000900;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
Thanks for your time,
Jon.