; kernel
bits 16
times 2 nop
jmp start

%include "printf"
%include "confseg"
%include "bits"
%include "memory"
global Readdisk

%define readdisk(a,b,c,d)  _readdisk a,b,c,d
;  readdisk :: int8 *seg:addr -> int8 drive -> int8 sectors -> bool ret

%macro _readdisk 4
   mov ax,%4
   push ax
   mov ax,%3
   push ax
   mov ax,%2
   push ax
   mov ax,%1
   push ax

   call Readdisk
   add sp,0x0008
%endmacro

; 00:2000:0000

gdt:

;null
gdt0:
   .limit:  dw 0x0000
   .baselo: dw 0x0000
   .basehi: db 0x00
   .xs:     db 0x00
   .reserv: dw 0x0000

;code
gdt1:
   .limit:  dw 0xffff
   .baselo: dw 0x0000
   .basehi: db 0x00
   .xs:     db 0x9a
   .reserv: dw 0x0000

;data
gdt2:
   .limit:  dw 0xffff
   .baselo: dw 0x0000
   .basehi: db 0x00
   .xs:     db 0x92
   .reserv: dw 0x0000

;code
gdt3:
   .limit:  dw 0xffff
   .baselo: dw 0x0000
   .basehi: db 0x01
   .xs:     db 0x9a
   .reserv: dw 0x0000

iconfseg:
istruc confseg
   at .phybm,        times 32 db 0x0000
   at .kernelmode,   db 0x00
   at .driverseg,    dw 0x0000
   at .kernelseg,    dw 0x0000
   at .gdtsz,        dw 31
   at .gdtlow,       dw gdt
   at .gdthi,        db 0x00
   at .gdtres,       db 0xff
iend
   .end:

stillalive: db "Still alive",0x00
bmp:
   dw 0xffff,0x0000
   db 0x00,0x00
   db 0x80

start:
    pf "Reading in the kernel"
    ; ax =
      readdisk(0x1000, 0x0000, 0x0082, 3)
    xor bx,bx
    mov bl,ah
    pf "Kernel read in, ax=0x%x",bx

    cli
    mov ax,(iconfseg.end-iconfseg)
    push ax
    mov ax,iconfseg
    push ax
    xor ax,ax
    push ax
    call Move
    add sp,0x06
    pf "Config segment created"

    pf "Activating GDT"
   ;  chseg(ds,csselector)
    chseg(ds,0x0000)
    mov bx,(confseg+confseg.gdtr)
    lgdt ds:[bx]
    sret(ds)
    pf "Enabling protected mode"
    smsw ax
    or ax,0x0001
    lmsw ax
    jmp 0x0008:.next

 .next:
   nop
    mov bx,0x7bfe
    mov ax,0x0010
    mov ds,ax
    mov es,ax
    mov ss,ax
    mov sp,bx

   mov ax,stillalive
   push ax
   call Printf
   add sp,0x0002
   pf "Loading kernel..."
   call far [kernelmain]

   hlt
 .endless:
    nop
    jmp .endless

; Readdisk :: int8 *seg:addr -> int8 drive -> int8 sectors -> bool ret
Readdisk:
    enter 0,0
    push bx
    push cx
    push dx
    push di

    mov di,[bp+4]    ; di=seg
    mov bx,[bp+6]    ; bx=addr
    mov dx,[bp+8]    ; dx=drive
    mov cx,[bp+10]   ; cx=num sectors

    chseg(es,di)
    mov ah,0x02
    mov al,cl
    mov cx,0x0001
    clc
    int 0x13

    jc .err
    jmp .end

 .err:
    sret(es)
    xor bx,bx
    mov bl,ah
    ;pf "Error reading disk 0x%x",dx
    ;pf "  ax=0x%x",bx
    jmp start.endless

 .end:
   sret(es)
   pop di
   pop dx
   pop cx
   pop bx

   mov ax,0x0001
   clc
   leave
   ret
 
kernelmain:
   dw 0x0002
   dw 0x0018
