mov eax , cr0
or eax , 0x01
mov cr0 , eax



back to months list

Project : The "Microkernel" Operating System

Journal Entry Date : 2024.06.07

Because of my stupidity, I accidentally drenched my computer with water. I had to establish the compile environment in my sister's computer, which is 10x slower than my computer. It's all my fault, and there is nothing I can do.

I just focused on making a simple kernel loader that works in Windows(because there is no grub-mkrescue so I have to make new kernel loader to boot the os.)

#0           #1           #3              #N
+------------+------------+---------------+
|            |   32-bit   |               |
| Bootloader |   kernel   |  Kernel Image |
|            |   loader   |               |
+------------+------------+---------------+

I just made a basic bootloader that loads the 32bit kernel loader into a particular address from the disk. To minimize the unnecessary parts of bootloader, I also just put the 32bit-switching code into bootloader.

[BITS 16]

    jmp 0x07C0:start

boot_drive:              db 0x00
kernel_loader_location:  dw 0x4000
kernel_loader_size:      dd 4

start:
    mov ax , 0x07C0
    mov ds , ax

    xor ax , ax
    mov ss , ax
    mov sp , 0x9FF8
    mov bp , 0x9FF8

    mov [boot_drive] , dl

    ; read the disk content (sector #2)
    xor ax , ax
    mov es , ax
    mov bx , [kernel_loader_location]

    mov ah , 2
    mov al , [kernel_loader_size]
    mov ch , 0x00
    mov dh , 0x00
    mov cl , 2 ; sector location of kernel loader
    mov dl , [boot_drive]
    
    int 0x13
...

The code is self-explanatory. It calls the BIOS service for reading the disk content.

Here is some basic global descriptor table for 32-bit kernel and the 32-bit switching code.

The CPU switches itself to protect mode when the first bit of CR0(PE, Protection Enable) register is set. (You can also see this in my website)

...
    ; change to protect mode
    lgdt [pmode_gdtr]
    
    cli

    mov eax , cr0
    or eax , 0x01
    mov cr0 , eax

    jmp 0x08:0x4000

pmode_gdt:
    [omitted]

times (510-($-$$)) db 0x00
dw 0xAA55

Now we just need to concatenate the bootloader, kernel-loader and kernel. I just made a rudimentary C code that merges all the files and aligns the offset by unit of sector. (Because the implementation is so simple I won't write it here.)

The most important part here that I realized is that the loader is quite scattered and does not have the specific architecture-independent convention/interface. I have to somehow figure out the way to somewhat make an interface for architecture-dependent loaders. I am thinking of providing the base information in a form of C macro or a function declaration. For now, I'll just mindlessly implement this loader without any regards toward the interface.

What we have to consider for loader interface is the following...

What we need to do (for now) is just load the kernel from the disk, get the memory map, and construct the KernelArgument structure to pass it to the kernel.

Guess I'll do it later. Somehow always I'm not busy but I'm too busy.