problem with kernel / pmode / bootloader
Posted: Tue Jan 06, 2004 11:06 am
When try to call a function with a C - pointer as parameter, the function receives a null pointer. This is only when I use my own bootloader. With the bootf02 it works fine. Where is the problem???
My Bootloader:
My Bootloader:
Code: Select all
[BITS 16]
[ORG 0x7C00]
jmp start ; jump to the code // if any other things a decleared after this
%include 'gdt.inc'
msg_ok db "OK",10,13,0
msg_failed db "Failed!!!",10,13,"Halt CPU",0
msg_check_cpu db "Check if CPU is >= 368...",0
msg_need_368 db "Failed",10,13,"Sorry your CPU must be a 368 or better",0
msg_enable_a20 db "Enable the A20 Gate...",0
msg_load_kernel db "Load the Kernel...",0
bootdrive db 0
kernel_addr dw 0x300
read_sectors db 0x04
putstr:
lodsb ; load the next character
or al,al ; if al = 0 (= character)
jz short putstrd ; return
mov ah, 0x0E ; function 0x0E (display character)
mov bh, 0x00 ; current page
mov bl, 0x07 ; color
int 0x10 ; call display interrupt
jmp putstr
putstrd:
ret
check_cpu:
mov si, msg_check_cpu ; tell the user what we're doing
call putstr
; test if 8088/8086 is present (flag bits 12-15 will be set)
pushf ; save the flags original value
xor ah,ah ; ah = 0
push ax ; copy ax into the flags
popf ; with bits 12-15 clear
pushf ; Read flags back into ax
pop ax
and ah,0f0h ; check if bits 12-15 are set
cmp ah,0f0h
je no386 ; no 386 detected (8088/8086 present)
; check for a 286 (bits 12-15 are clear)
mov ah,0f0h ; set bits 12-15
push ax ; copy ax onto the flags
popf
pushf ; copy the flags into ax
pop ax
and ah,0f0h ; check if bits 12-15 are clear
jz no386 ; no 386 detected (80286 present)
popf ; pop the original flags back
mov si, msg_ok
call putstr
ret ; no 8088/8086 or 286, so ateast 386
no386:
mov si,msg_need_368 ; tell the user the problem
call putstr
cli
hlt
jmp $-2
.386
enable_a20:
cli ; disable interrupts
call wait_key_buf ; wait for kbd buffer to clear
mov al,0xd1 ; tell it we want to write to output port
out 0x64,al
call wait_key_buf ; wait again for kbd to clear
mov al,0xdf ; set desired settings (A20 gate)
out 0x60,al ; send value to data reg
call wait_key_buf ; wait for kbd to clear
mov cx,0x10 ; loop count
kbdwait:
xor ax,ax ; do anything
out 0xe0,ax ; some mor nonsense
loop kbdwait ; loop to waste time
;-------------- check if a20 was enabled --------------
mov al,0xd0
out 0x64,al ; tell kbdc we want to read output port
call wait_key_buf_data ; wait for data to get in it
in al,0x60 ; get it
test al,2 ; test if A20 is on
jnz a20_on ; if it is clear, then it is off
jmp error
a20_on:
ret
wait_key_buf:
xor al,al ; al = 0
in al, 0x64 ; get kbd status
test al, 2 ; is bit 1 clear?
jnz wait_key_buf ; if not wait some more
ret
wait_key_buf_data:
xor cx,cx ; cx = 0
in al, 0x64 ; get kbd status
test al, 1 ; is bit 0 clear?
jz wait_key_buf_data ; if not wait some more
ret
load_kernel:
clc ; clear the carry flag
mov ecx, 5 ; try to reset the driver 5 times
reset_drive:
xor ax, ax ; ax = 0
mov dl, [bootdrive] ; dl = bootdrive
int 0x13 ; reset drive
jnc reset_ok ; if carry flag = 0
loop reset_drive ; else try it again if ecx != 0
jmp error ; if ecx = 0 and the reset always failed, halt
reset_ok:
mov ecx, 5 ; try to read the kernel 5 times
read_kernel:
mov ax, [kernel_addr]
mov es, ax ; address of the buffer
mov ah, 0x02 ; function number 2 (read from disk)
mov al, [read_sectors] ; number of sectors to read
mov dl, [bootdrive] ; set drive
mov dh, 0x00 ; read/write head number
mov ch, 0x00 ; number of the track or cylinder (0 = first)
mov cl, 0x02 ; number of the sector where to start (1 = first)
xor bx, bx ; offset of the buffer
int 0x13
jnc load_ok ; if all is ok return
loop read_kernel ; try once again if there is an error
jmp error ; if ecx = 0 and the read operation always failed, halt
load_ok:
ret