Protected Mode - Bootloader

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
doug

Protected Mode - Bootloader

Post by doug »

First off - great site!!!!

I am an assembly beginner, I can seem to work out what's wrong with the bootloader listed below. I used to use just a simple call to int 0x13 to load in the sectors (ignoring track's etc..) until the kernel size got to about 50 sectors - it would no longer work :-)
Having looked at various bootloaders out there I have changed it to load in a track at a time - but this does not work - anyone any ideas??

%define KERNEL_SIZE 60

[BITS 16]
[ORG 0]
     jmp short start
     nop

driveSectors      db 18
driveHeads      db 1
           
start:  cli                      ; disable interrupts
     mov ax, 0x7c0            ; BIOS sticks us here
     mov ds, ax            ;
       mov ax, 0x9000            ; setup stack
     mov ss, ax
     sti                  ; enable interrupts

     mov [bootdrive], dl      ; save the bootdrive

       mov si, bootmsg            ; display bootmsg
     call writechars                          
     
     mov ah, 0
     int 0x13
     jc reseterror
     
startloadKernel:

         mov ax, KERNEL_SIZE
     div byte [ds:driveSectors]
     mov si, ax
     and si, 0xff
     inc si

     mov ax, 0x200 ; kernel load addr
     mov es, ax
     xor bx, bx
     mov al, [ds:driveSectors] ; number of sectors to read
       mov cx, 0x0002      

loadKernel:
     mov ah, 2            

     mov dl, [bootdrive]
     int 0x13
     jc loadKernel            
     
     dec si                  ; sectors to read --
     jz readDone            ; are we finished?

     mov bx, es            ;
     add bx, 9216
     mov es, bx
     
     mov al, [ds:driveSectors]
     xor bx, bx

readNextTrack:
     mov cl, 1            ; reset back to sector 1
     cmp dh, [ds:driveHeads]
     je resetHeads
     inc dh ; head++
     jmp loadKernel

resetHeads:
     xor dh, dh             ; back to head 0, inc track
     inc ch ; track++
     jmp loadKernel

readDone:      
     mov si, kernelmsg      ; display kernel loaded msg
     call writechars

     mov al, 0xff            ; disable all irq's
     out 0x21, al            ; write to PIC controller

     lgdt [gdt_ptr]
     
     mov eax, cr0            ; get into protected mode
     or al, 1
     mov cr0, eax                                                

       mov ax, datasel            ; setup segments to new selector
     mov ds, ax
     mov es, ax
     mov fs, ax
     mov ss, ax
     mov gs, ax

     jmp codesel:0x2000 ; jump into prot mode

     jmp $

reseterror:
     mov si, reseterrormsg
     call writechars
     jmp $
                 
writechars:
     lodsb
     or al, al
     jz .done
     mov ah, 0x0e
     mov bx, 7            ; write text
     int 0x10
     jmp writechars
.done:
     ret
           
; data section

bootmsg      db 0dh, 0ah, "Booting..", 00h
kernelmsg      db 0dh, 0ah, "Kernel loaded", 00h
resetfloppymsg      db 0dh, 0ah, "Reset Floppy", 00h
reseterrormsg      db 0dh, 0ah, "Reset error", 00h
loaderrormsg      db 0dh, 0ah,"Unable to load operating system kernel.", 0dh, 0ah, 00h
dotmsg            db "."
bootdrive      db 0

gdt_ptr
     dw end_gdt - start_gdt - 1
     dd start_gdt

start_gdt
     dd 0x00000000            ; dummy selector
     dd 0x00000000

codesel equ $-start_gdt      
code0
     dw 0xffff            ; segment limit
     dw 0x0000            ; base address
     db 0x00                  ;
     db 0x9a                  ; priv level 0, code
     db 0xcf                  ; granurlarity
     db 0x00                  ; base address

datasel equ $-start_gdt
data0

     dw 0xffff            ; segment limit
     dw 0x0000            ; base address
     db 0x00                  ;
     db 0x92                  ; priv level 0, data
     db 0xcf                  ; gran
     db 0x00                  ; base address

stacksel equ $-start_gdt
stack0
     dw 0xffff            ; segment limit
     dw 0x0000            ; base address
     db 0x00                  ;
     db 0x92                  ; 0, data
     db 0xcf                  ; gran
     db 0x00                  ; base address
end_gdt      

; pad out sector
outside: times (510-($-$$)) db 0
; boot signature (last 2 bytes)
dw 0x55AA
User avatar
df
Member
Member
Posts: 1076
Joined: Fri Oct 22, 2004 11:00 pm
Contact:

Re: Protected Mode - Bootloader

Post by df »

First off - great site!!!!

I am an assembly beginner, I can seem to work out what's wrong with the bootloader listed below. I used to use just a simple call to int 0x13 to load in the sectors (ignoring track's etc..) until the kernel size got to about 50 sectors - it would no longer work :-)
Having looked at various bootloaders out there I have changed it to load in a track at a time - but this does not work - anyone any ideas??
1st off you dont really need a stack selector.
you can just use the data selector.

at first glance the code looks fine to me. I'd really have to test it to make sure.

basically you just need to read, what, mm... 18 sectors, flip the head, 18 sectors, reset head, increment track/cylinder.

quite basic stuff.

erugh. your reading in at 0x2000, your boot sector is running at 0x7c00, so if your kernel is really big, your going to read code in over the top of your self and crash.

you can either relocate the boot sector code at runtime to down to like 0x600, or read your kernel in at say 0x8000 instead of 0x2000

i'm sure if there is an error in your code, someone else will spot it and post here for you!
-- Stu --
eVolve

Re: Protected Mode - Bootloader

Post by eVolve »

I think it would help a lot if you recalibrated your floppy disc drive before you execute a read operation (and that is everytime before you execute a read operation).
Alexei A. Frounze

Re: Protected Mode - Bootloader

Post by Alexei A. Frounze »

I think it would help a lot if you recalibrated your floppy disc drive before you execute a read operation (and that is everytime before you execute a read operation).
I don't think this is necessary. BIOS does calibration before it loads the bootsector. If it did not, you won't be able to boot up off the floppy disk sometimes.
BLoggins02

Re: Protected Mode - Bootloader

Post by BLoggins02 »

DF is right, let's do the math here:

- boot code at 0x7c00
- start of kernel code at 0x2000
- 50 sectors * 512 b/s = 25KB (~0x6000)

?0x2000
+0x6000
======
0x8000

Somewhere between sectors 49 and 50, you're overwriting your boot code. ?When the proc. jumps to the next instruction, WHAMMO! It's crash time. ?You could do this:

[tt]
mov ax, 0x07c0 ? ? ? ?; Source Segment
mov ds, ax
mov ax, 0x9000 ? ? ? ?; Dest segment
mov es, ax
xor si, si ? ? ? ? ? ? ? ? ?; Zero offset
xor di, di ? ? ? ? ? ? ? ? ?; Ditto
mov cx, 0x200 ? ? ? ? ?; 512 Bytes

cld ? ? ? ? ? ? ? ? ? ? ? ? ?; Clear the direction flag
rep movsb ? ? ? ? ? ? ? ?; move it!

; New segments for everything
mov es, ax
mov ds, ax

; JMP!
jmp 0x9000:there ; or JMP FAR 0x9000:there if you have to

there:

; Blah blah blah - Rest of Really New Nifty OS (TM) goes here
[/tt]

That was off the top of my head, but should be more or less correct

HTH (Even though you've probably fixed this by now),
Breckin
Post Reply