Page 1 of 1

problem with kernel / pmode / bootloader

Posted: Tue Jan 06, 2004 11:06 am
by guest
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:

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

Re:problem with kernel / pmode / bootloader

Posted: Tue Jan 06, 2004 11:07 am
by guest

Code: Select all

enter_pmode:
   cli
   lgdt [gdt_desc]
   mov eax, cr0      ; enable pmode
   or  eax, 1
   mov cr0, eax
   mov eax, DATA_SEL
   mov ds,   eax
   mov es, eax
   mov ss, eax
   jmp CODE_SEL:0x3000
   cli
   hlt
   jmp $-2
error:
   mov si, msg_failed
   call putstr
   cli
   hlt
   jmp $-2
start:
   cli
   mov [bootdrive], dl   ; save the bootdrive
   mov ax, 0x9000
   mov ss, ax      ; setup the stack at 0x9000
   mov esp, 0x8000      ; set the stack size
   sti

   mov ax,0x0000      ; ax = 0
   mov es,ax               ; korrigiert die Segment Register
   mov ds,ax
   call check_cpu
.386
   mov si, msg_enable_a20
   call putstr
   call enable_a20
   mov si, msg_ok
   call putstr

   mov si, msg_load_kernel
   call putstr
   call load_kernel   ; load the kernel
   mov si, msg_ok
   call putstr

   call enter_pmode
   cli
   hlt
   jmp $-2

times 510-($-$$) db 0
db 0x55 db 0xAA