; 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

;data
gdt4:
   .limit:  dw 0xffff
   .baselo: dw 0x0000
   .basehi: db 0x01
   .xs:     db 0x92
   .reserv: dw 0x0000

;data
gdt5:
   .limit:  dw 0xffff
   .baselo: dw 0x0000
   .basehi: db 0x02
   .xs:     db 0x92
   .reserv: dw 0x0000
gdtend:

iconfseg:
istruc confseg
   at .phybm,        db 0x07
                     times 31 db 0x00
   at .kernelmode,   db 0x00
   at .driverseg,    dw 0x0000
   at .kernelseg,    dw 0x0000
   at .gdtsz,        dw (gdtend-gdt-1)
   at .gdtlow,       dw 0x0000
   at .gdthi,        db 0x02
   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, 128)
    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"

    chseg(es,0x2000)
    mov ax,(gdtend-gdt)
    push ax
    mov ax,gdt
    push ax
    xor ax,ax
    push ax
    call Move
    add sp,0x06
    sret(es)
    pf "GDT 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 bx,0xfffe
    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 "Still alive"
   ;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
