Page 1 of 1
Boot Loader Troubles (again, sorry)
Posted: Thu Oct 06, 2005 7:15 pm
by Peradox
Hey guys, sorry for bothering you again...
I've been working busily on a bootloader, that loads a program from a floppy. However whenever I run it, I get the BIOS screen followed by my program running (the floppy drive becomes active) and then it just stops, reboots the computer and i see the BIOS screen again and the cycle continues...
Any help?
Thanks in advance.
Code: Select all
[BITS 16]
[ORG 0X7C00]
; enable a20
cli
call kbd_wait
mov al, 0xD1
out 0x64, al
call kbd_wait
mov al, 0xDF
out 0x60, al
call kbd_wait
sti
; load kernel
rstdrive:
mov ax, 0x00
int 0x13
or ah, ah
jnz rstdrive
mov ax, 0xFFFF
mov es, ax
mov bx, 0x10
mov ah, 0x02
mov al, 0x02
mov ch, 0x00
mov cl, 0x02
mov dh, 0x00
int 0x13
or ah, ah
jnz rstdrive
;enter pmode and load gdt
cli
xor ax, ax
mov ds, ax
lgdt [GDT_DESC]
mov eax, cr0
or eax, 1
mov cr0 eax
jmp GDT_CODE:bit32_clearpipe
[BITS 32]
bit32_clearpipe:
; setup stack and regs
mov ax, 0x1D00
mov ds, ax
mov ss, ax
mov esp, 0x200
; jmp to kernel code
jmp GDT_CODE:0x100000
hlt
GDT:
GDT_NULL equ $-GDT
dd 0x00
dd 0x00
GDT_CODE equ $-GDT
dw 0x0FFFF
dw 0x00
db 0x00
db 10011010b
db 11001111b
db 0x00
GDT_DATA equ $-GDT
dw 0x0FFFF
dw 0x00
db 0x00
db 10010010b
db 11001111b
db 0x00
GDT_END:
GDT_DESC:
dw GDT_END - GDT - 1
dw GDT
kbd_wait:
kdb_clr:
in al, 0x64
test al, 2
jnz kbd_clr
ret
TIMES 510-($-$$) db 0
SIGNATURE dw 0xAA55
Re:Boot Loader Troubles (again, sorry)
Posted: Thu Oct 06, 2005 7:35 pm
by Cjmovie
Unless I'm mistaken, which I may well be, you can't load above 1mb (or at it) unless you enter protected BEFORE you read from the floppy. But BIOS functions don't work in 32-bits, so you have two choices:
Look up UnrealMode (more complex)
Load your kernel below 1mb (less complex)
Change these lines:
Code: Select all
mov ax, 0xFFFF
mov es, ax
mov bx, 0x10
to
Code: Select all
xor ax, ax
mov es, ax
mov bx, 0x1000
also, change:
to:
Re:Boot Loader Troubles (again, sorry)
Posted: Thu Oct 06, 2005 7:49 pm
by Peradox
hmm, still doesn't work. And i checked, i don't load anywhere close to 1MB into memory. Thank you anyway. Anymore help??
Re:Boot Loader Troubles (again, sorry)
Posted: Thu Oct 06, 2005 8:36 pm
by beyondsociety
Unless I'm mistaken, which I may well be, you can't load above 1mb (or at it) unless you enter protected BEFORE you read from the floppy. But BIOS functions don't work in 32-bits, so you have two choices:
You may be as Ive never had a problem with loading to 1mb before protected mode and reading from the floppy.
Code: Select all
mov ax, 0xFFFF
mov es, ax
mov bx, 0x10
0xFFFF:0x0010 (1mb) will only work if the a20 gate is enabled. If not, it will cause the addresses to wraparound and you would get 0x0000:0x0000. Your setting it, so that shouldnt be a problem.
It may be a problem with setting up the segment registers and not having a 16bit stack. This should be set before the a20 gate stuff.
Re:Boot Loader Troubles (again, sorry)
Posted: Thu Oct 06, 2005 10:41 pm
by Peradox
Well, here's the updated code, (with comments, this time). However its still not working.
???
Code: Select all
;; loader.asm is loaded into 0x7C00 and jumped to by the
;; BIOS after the POST. Loader then enters at boot: and
;; enables the A20 line to enable addressing over 1MB by
;; means of the KBD controller ports 64h and 60h, then it
;; uses BIOS interrupts to load the kernel code into
;; 0xFFFF:0x0010. Now we setup a GDT and stack.
;; Protected Mode is entered and interrupts are
;; disabled until kernel code decides to re-enable them.
;; Then we jump to the kernel code at 0xFFFF:0x0010,
;; or 0x100000 (1 MB) Linear
[BITS 16] ;; Real mode requires 16 bit instructions
[ORG 0x7C00] ;; BIOS loads us at Linear 0x7C00
jmp boot ;; Skip all the data, and enter at boot:
;; This is the GDT
;; http://www.osdever.net/tutorials/brunmar/tutorial_02.php
;; The link above gives a good explanation of the GDT
;; It is too lengthy for a comment
GDT:
;; 64 0 bits: intel reserved, but we need to define them
GDT_NULL equ $-GDT
dd 0x00
dd 0x00
;; Code segment, our kernel goes here
GDT_CODE equ $-GDT
dw 0x0FFFF
dw 0x00
db 0x00
db 10011010b
db 11001111b
db 0x00
;; data segment/OS Stack
GDT_DATA equ $-GDT
dw 0x0FFFF
dw 0x00
db 0x00
db10010010b
db 11001111b
db 0x00
GDT_END:
GDT_DESC:
dw GDT_END - GDT -1
dd GDT
;; This routine loops until the KBD
;; controller is ready by reading from
;; port 0x64 and checking if bit 1
;; of the KBD buffer is 0
kbd_wait:
kbd_clr:
in al, 0x64 ;; Read input from port 0x64 into al
test al, 2 ;; test the fist bit (which is zero if ready)
jnz kbd_clr ;; if not zero try again, else return
ret
boot: ;; entry point
;; TEMPORARY STACK SETUP
cli ;; Disable Interrupts
mov ax, 0x9000 ;; This is where everyone puts their stack...
mov ss, ax ;; We can't modify ss directly, so we do it here with ax
mov sp, 0xFFFE ;; Use the whole segement - 1
sti ;; re-enable interrupts
;; ENABLE A20 ADDRESSING LINE
;; First we write the wanted operation (0xD1 = write) into
;; port 0x64, then we write the data to port 0x60
;; 0xDF indicates we would like to enable the A20 line
;; kbd_wait just loops until the KBD buffer is free
cli ;; disable interrupts
call kbd_wait ;; Wait until KBD controller is ready
mov al, 0xD1 ;; writing 0xD1 to port 0x64 lets we us write data to port 0x60
out 0x64, al ;; actually write it
call kbd_wait ;; Wait until KBD controller is ready
mov al, 0xDF ;; writing 0xDF to port 0x60 enables A20
out 0x60, al ;; actually write it
call kbd_wait ;; Wait until KBD controller is ready
sti ;; re-enable interrupts
;; LOAD KERNEL INTO 0xFFFF:0x0010 (Linear 1 MB (0x100000))
;; This loop just loops around until resetting
;; the disk succeeds
rstdrive:
mov ax, 0x00 ;; Reset Drive Function
int 0x13 ;; Call BIOS
or ah, ah ;; check ah for errors
jnz rstdrive ;; if it didn't work jump back to rstdrive:
;; The address is represented by es:bx
;; We want to load into 0xFFFF:0x0010
mov ax, 0xFFFF ;; we can't modify es directly
mov es, ax ;; es -> ax -> 0xFFFF
mov bx, 0x0010 ; set bx to 0x0010
;; Set up BIOS interrupt 13h, function 2h
;; ah = function (2h)
;; al = total sectors to read
;; ch = track #
;; cl = starting sector (starts at 1)
;; dh | dl = head | drive
mov ah, 0x02 ;; Function 2h (read from floppy)
mov al, 0x02 ;; we want to read 2 sectors (one KB)
mov ch, 0x00 ;; track 0
mov cl, 0x02 ;; start at sector 2 (sector 1 = boot sector)
mov dh, 0x00 ;; head and drive are 0 (floppy)
int 0x13 ;; Call BIOS
or ah, ah ;; check ah for errors
jnz rstdrive ;; if error, try again
;; we disable interrupts here until the kernel
;; re-enables them, once we have an IDT
cli ;; Disable interrupts
;; LOAD GDT
xor ax, ax ;; Zero out ax
mov ds, ax ;; Set ds to 0 (lgdt uses ds)
lgdt [GDT_DESC] ;; load the gdt
;; ENTER 32-BIT PROTECTED MODE
;; seting cr0 to one sets the processor into protected mode;
mov eax, cr0 ;; Load cr0 into eax
or eax, 0x01 ;; set it to 1, even if it already is 1
mov cr0, eax ;; mov it back into cr0
;; SWITCH TO 32 BIT INSTRUCTION SET
;; flush all 16 bit insturction out of the pipe
;; by issueing a long jump
jmp dword GDT_CODE:bit32_clearpipe
[BITS 32] ;; Switch to 32 bit instructions
bit32_clearpipe:
;; REFRESH SEGMENT REGISTERS & SETUP STACK
mov ax, GDT_DATA
mov ds, eax
mov ss, eax
mov es, eax
mov fs, eax
mov gs, eax
;; JMP TO KERNEL CODE
;; Here we just give control to the kernel
;; I kick @$$ :=)
jmp dword GDT_CODE:0x100000
hlt
;; Fill the rest of the file up with 0s,
;; then mark bytes 511 & 512 as 0xAA55
;; So the BIOS knows we are bootable
TIMES 510-($-$$) DB 0
SIGNATURE DW 0xAA55
Re:Boot Loader Troubles (again, sorry)
Posted: Fri Oct 07, 2005 3:48 pm
by Cjmovie
Peradox wrote:
hmm, still doesn't work. And i checked, i don't load anywhere close to 1MB into memory. Thank you anyway. Anymore help??
You misunderstood me. In real mode, even with the A20 gate enabled, you cannot load ANY amount of memory at the 1mb mark. So your offset:
0xFFFF:0x10 will ALWAYS wrap around to 0x0000
You cannot place your kernel at the 1mb barrier unless you use unreal mode or write a floppy driver. So you must load it below 1mb or enable unreal mode. I recommend unreal mode if you know how to go about it - otherwords, change the offset to:
0x0000:0x1000
To load it at a location in memory that is below the 1mb barrier.
By looking at where you jump to your kernel:
You are trying to jump to the 1mb location in memory (actually, it's the very first byte of the 2nd MB, but I digress)
At the point you enter protected mode, nothing with an offset >= to 0x100000 will have anything in it (except some random values. In BOCHS, it will all be 0's).
Re:Boot Loader Troubles (again, sorry)
Posted: Fri Oct 07, 2005 5:59 pm
by Peradox
EDIT: I tryed loading to a lower address, and people said they haven't had problems with loading into 1MB, and it till didn't work. it just reboots afterwards...
are there any other problems? Is the problem in the program that I'm using to test this one?
Code: Select all
[BITS 32]
mov dword [0xb8000], 0x07690748
loop1: jmp loop1
Re:Boot Loader Troubles (again, sorry)
Posted: Fri Oct 07, 2005 11:51 pm
by AR
Did you use "BITS 32"? Otherwise the CPU will misinterpret and throw an "invalid opcode exception"
Re:Boot Loader Troubles (again, sorry)
Posted: Sat Oct 08, 2005 12:51 am
by Peradox
Yes, I did...
I left out some stuff in my haste, it's edited now.
Re:Boot Loader Troubles (again, sorry)
Posted: Sat Oct 08, 2005 12:59 am
by AR
There's a typo:
Code: Select all
;; data segment/OS Stack
GDT_DATA equ $-GDT
dw 0x0FFFF
dw 0x00
db 0x00
db10010010b ;here, this would be a label not a value without the space
db 11001111b
db 0x00
I haven't checked the bits in the GDT entry, but other than this there doesn't appear to be anything else that is obviously wrong.
Re:Boot Loader Troubles (again, sorry)
Posted: Sat Oct 08, 2005 1:24 am
by Peradox
Hey, thanks for going through all the trouble...
It's still not working though... ...bochs does the same thing my BIOS does, so it's not the BIOS's fault.
And some bochs debugging tells me that the problem in execution happens at:
Code: Select all
;; JMP TO KERNEL CODE
;; Here we just give control to the kernel
;; I kick @$$ :=)
jmp dword GDT_CODE:0x10000
this doesn't mean that's where the error is though...
EDIT: It works! Thanks so much for your help guys!