Hi. I have been working so hard to write this second stage loader but I cannot for the life of me figure out why it is not working. In my second stage loader it does not seem to load my kernel from disk. I have a view test points where some text should show on screen.
01: When it fails
02: When it finds the kernel
03: When it loads stage 2
I see the verbiage for when the stage 2 loader begins but not the fail or found kernel verbiage. It appears as if it starts to read my disk then stops and then halts for no reason. Here is my linker script where my goal is to load the kernel according to this script:
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;_end = .; __end = .;
}
and here is the full code of my non-working stage 2:
;******
;Stage 2
;******
[BITS 16]
org 0x1000
; jump to the code
boot: jmp start
nop
bpbOEM db 'WHITE OS'
bpbSectSize dw 512
bpbClustSize db 1
bpbReservedSec dw 1
bpbFats db 2
bpbRootSize dw 224
bpbTotalSect dw 2880
bpbMedia db 240
bpbFatSize dw 9
bpbTrackSect dw 18
bpbHeads dw 2
bpbHiddenSect dd 0
bpbLargeSect dd 0
bpbDriveNo db 0
bpbReserved db 0
bpbSignature db 0
strings:
.mesg: db "Insert disk 02, then hit any key to continue . . .",0x0
.filename: db "KERNEL ",0x0
.failure: db "Read error!",0x0
.found: db "kernel found!",0x0
; here begins data
; static-build gdt
gdt:
; selector 0 is reserved and is the null selector
gdt_null:
dd 0x00000000
dd 0x00000000
; selector 8 is the big code selector
gdt_code:
dw 0xFFFF
dw 0x0000
db 0x00
db 10011010b
db 11001111b
db 0x00
; selector 10 is the big data selector
gdt_data:
dw 0xFFFF
dw 0x0000
db 0x00
db 10010010b
db 11001111b
db 0x00
; used to calculate the size of gdt
gdt_end:
; the gdt descriptor
gdt_desc:
dw gdt_end - gdt - 1
dd gdt
; the true start of the code
start:
mov ax, 0x0000
mov ds, ax
mov si, strings.mesg
mov ah, 0x0e
.loop:
mov al, [ds:si]
cmp al, 0x00
jz load_kernel
int 0x10
inc si
jmp .loop
load_kernel:
mov ah, 0
int 16h ;Wait for keypress
;finish loading the kernel
cli ;disable interrupts
xor ax, ax ; initialize all the necessary
mov ds, ax ; registers.
mov es, ax
mov ss, ax
mov sp, 0xFFFF ; Stack..
mov [bpbDriveNo], dl
sti
mov di, 0x0050 ; Load the root to
mov ax, 19 ; 0x0000:0x0500 (0x500/0x10)
mov cx, 14
call read_sectors
mov di, 0x0210 ; Load the fat to
mov ax, 1 ; 0x0000:0x2100
mov cx, 9
call read_sectors
read_sectors:
pusha
mov bl, byte [bpbTrackSect] ; bl = number of sectors per track
div bl ; al = ax / bl
mov cl, ah ; cl = real sector number
add cl, 1
xor ah, ah ; del the rest of the div before
mov bl, byte [bpbHeads] ; bl = number of heads
div bl ; ah = rest of ( ax / bx ), al = ax / bx
mov ch, al ; ch = number of track
mov dh, ah ; dh = the head number
mov ax, cx ; save cx in ax
mov cx, 6 ; try it 6 times
.next_try:
push es
push cx
mov cx, ax ; restore cx
push cx
xor ax, ax
mov dl, [bpbDriveNo] ; reset drive
push dx
int 0x13
jc .failed
pop dx
pop cx
xor bx, bx
mov es, di
mov ax, 0x0201 ; function 2, 1 sector
int 0x13
jnc .ok ; if it was ok, check next..
.failed:
pop dx
pop ax
pop cx
pop es
loop .next_try ; else try once again if there is an error
jmp error ; if cx = 0 and the read operation always failed, halt
.ok:
pop cx ; from the next_try loop
pop es
popa
add di, 32 ; add 32 (512/16) to segment
inc ax ; add sector counter
loop read_sectors
ret
error:
mov ax, 0x0000
mov ds, ax
mov si, strings.failure
mov ah, 0x0e
.loop:
mov al, [ds:si]
cmp al, 0x00
jz waitn
int 0x10
inc si
jmp .loop
waitn:
mov ah, 0
int 0x16
int 0x19
;------------------------;
; search for the file ;
;------------------------;
mov dx, [bpbRootSize]
mov bx, 0x0500
filesearch:
cld
mov si, strings.filename
mov cx, 11
mov di, bx
repe cmpsb
je found
add bx, 32
dec dx
jz error
jmp filesearch
;-----------------------------------;
; the file is found, load it. ;
;-----------------------------------;
found:
mov ax, 0x0000
mov ds, ax
mov si, strings.found
mov ah, 0x0e
.loop:
mov al, [ds:si]
cmp al, 0x00
jz donext
int 0x10
inc si
jmp .loop
mov bp, [bx+26] ; bp=cluster number from directory entry
mov di, 0x1000 ; 1000 (segment)
donext:
.next_block:
xor cx, cx
mov cl, [bpbClustSize] ; reset sector count to 1 cluster
mov si, bp ; si=next should-be cluster for
; contiguous reads
.next_contiguous:
mov ax, 3 ; 3
mul si ; multiply cluster number by 3
; dx assumed to be 0, it's a floppy!
shr ax, 1 ; divide by two
push bp
xchg bp, ax ; bp=ax
mov ax, word [0x2100+bp] ; ax=FAT element with junk
; (addressing with bp)
pop bp
jc .odd_cluster ; jump if the value was odd
.even_cluster:
and ax, 0x0FFF ; leave only lower 12 bits
jmp .got_cluster ; got it
.odd_cluster:
push cx ; preserve sector count
mov cl, 4 ; shift four bits right
shr ax, cl ; (leave only bits 4-15)
pop cx ; restore sector count
.got_cluster:
inc si ; si=current cluster+1
cmp ax, si ; next cluster=current cluster+1?
jne .force_read ; is it still contiguous?
add cl, [bpbClustSize] ; increase sector count by 1 cluster
adc ch, 0
jmp .next_contiguous
.force_read:
xchg bp, ax ; ax=bp (base cluster), bp=new cluster
dec ax ; decrease by 2 to get the actual... (1)
dec ax ; ...cluster number (2)
xor dx, dx
mov dl, [bpbClustSize]
mul dx ; multiply by sectors per cluster
; (dx ignored)
add ax, 33 ; assume data-area start at sector 33
call read_sectors ; read cx sectors at ax to es:0 :)
cmp bp, 0x0FF8 ; the new cluster is EOF (FF8-FFF)?
jb .next_block ; if not in this range, read next block
;load a20
xor cx, cx ;clear the CX register
clear_buf:
in al, 64h ; Get input from keyboard status port
test al, 02h ; Test the buffer full flag
loopnz clear_buf ; Loop until buffer is empty
mov al, 0D1h ; Keyboard: write to output port
out 64h, al ; Output command to keyboard
clear_buf2:
in al, 64h ; Wait 'till buffer is empty again
test al, 02h
loopnz clear_buf2
mov al, 0dfh ; Keyboard: set A20
out 60h, al ; Send it to the keyboard controller
mov cx, 14h
wait_kbc: ; This is approx. a 25uS delay to wait
out 0edh, ax ; for the kb controler to execute our
loop wait_kbc ; Command.
xor ax, ax
mov ds, ax ; Set DS-register to 0 - used by lgdt
lgdt [gdt_desc] ; Load the GDT descriptor
; set cr0.1 to 1 to switch to protected mode
mov eax, cr0
or eax, 1
mov cr0, eax
; jump to new code zone to really switch to protected mode
jmp 0x08: pmode
; here we are in 32-bit protected mode
[BITS 32]
pmode:
; cs is already set. we set ds to data zone and es to vdeo zone. we also setup
; ss for c layer
mov ax, 10h ; Save data segment identifyer
mov ds, ax ; Move a valid data segment into the data segment register
mov ss, ax ; Move a valid data segment into the stack segment register
mov esp, 0xfffc ; Move the stack pointer
;jmp $
jmp 0x08:0x100000 ; Jump to section 08h (code)
times ( 1024 - ( $ - $$ ) ) db 0x00
please any help is greatly appreciated.