; kernel
bits 16
%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

.jump:
jmp start

; 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

gdtr:
   sz:   dw 23
   addr: dw gdt
         db 0x00
         db 0xff
;    .phybm:         resb 64
;    .kernelmode:    resb 1
;    .driverseg:     resw 1
;    .kernelseg:     resw 1

iconfseg:
istruc confseg
   at .phybm,        times 32 db 0x0000
   at .kernelmode,   db 0x00
   at .driverseg,    dw 0x0000
   at .kernelseg,    dw 0x0000
iend
   .end:

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

start:
    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"

    ;setbit(0x9000,bmp,9,1)
    ;setbit(0x8000,bmp,9,0)
    ; ax =
      findbit(0x0000,bmp,7,0)
    mov bx,ax
    push bx
    pf "bx=%x",bx
    pop bx

    ; 01:0000
    ; seg=0x1000
    ; addr=0x0000

    pf "Loading the kernel"
    ; ax =
      readdisk(0x1000, 0x0000, 0x0082, 128)
    xor bx,bx
    mov bl,ah
    pf "Loaded kernel, ax=0x%x",bx

    pf "Activating GDT"
    mov bx,gdtr
    lgdt [bx]
    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

   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
 