; core.s
bits 16
%pragma once

_init:
    mov ax,0xfffe
    mov bx,0x0020
    mov ds,bx
    mov es,bx
    mov ss,bx
    mov sp,ax
    mov cx,ax
    Debug "We are inside the kernel!"
    call main

halt:
    pfln
    pfln "Shutdown."
    cli
 .loop:
    hlt
    jmp .loop

; main :: void -> void
main:
    enter 0,0

    mov cx,0x0040
 .cls:
    pfln
    loop .cls

    pf "rookery-kernel v%d.",VersionMajor
    pfln "%d",VersionMinor
    pfln
    pfln "loading modules..."
    pfln "  %s",ds:[name]

    mov ax,0x0005   ; addr of first module = byte 5
                    ;   [ sizeof(jmp _init) + sizeof(int8*) ]
    push ax
    call loadmods
    add sp,2

    pfln
    pfln "creating an idt:"
    call mkidt

    pf "Setting ring to 0..."
    setiopl(ring2iopl(0))
    jc .erriopl
    ; ax=
        getiopl()
    mov bx,ax
    push bx
    pf "iopl=%d ",bx
    ; ax=
        getring()
    mov bx,ax
    pfln "ring=%d",bx
    pop bx
    cmp byte bl,0
    jne .erriopl2

    pf "Generating stacks..."
    ; cf =
        genstacks()
    jc .errstax
    pfln "done"

    pf "Initializing interrupt controllers..."
    call picinit
    pfln "ok"

    pf "Initializing timer chip..."
    call pitinit
    pfln "ok"

    ; next up: tss

    sti
    jmp $

 .end:
    xor ax,ax
    clc
    leave
    ret

 .erriopl:
    pfln "failed"
 .erriopl2:
    mov ax,0x0001
    jmp .err
 .errstax:
    pfln "failed"
    mov ax,0x0002
    jmp .err
 .err:
    stc
    leave
    ret

; loadmods :: int8 size -> void
loadmods:
    enter 0,0
    push bx
    push cx
    push di
    push si

    mov cx,[bp+4]       ; cl=size of one module header
    and cx,0xff

    xor si,si            ; we start at 0x0000... 
 .loop:
    xor ch,ch
    add si,cx            ;   ...and jump past the first modhdr
    %define Init si
    %define Name si+3
    mov word bx,ds:[Name]   ; bx=addr of 1st byte of the name str
    %define Str bx
    lea word di,ds:[Init]   ; di=addr of the module's init fn
    %define Fun di

    cmp word ds:[Init],0x0000
    jz .end

    mov byte ch,ds:[Str]
    cmp ch,0x00
    jz .next
    pfln "  %s",ds:[Name]
 .next:
    call Fun
    jmp .loop

    %undef Fun
    %undef Str
    %undef Name
    %undef Init

 .end:
    pop si
    pop di
    pop cx
    pop bx

    xor ax,ax
    clc
    leave
    ret
