Page 1 of 1

Loading the second stage bootloader

Posted: Sun Nov 25, 2007 8:25 pm
by osdf_1
Hi, I'm a beginner at OS development so forgive my ignorance. What I want to do is write a bootloader that loads a second stage bootloader. Here's what I have so far:

Code: Select all

;----------[boot_loader.asm]----------;
; Author: Ricardo Diaz                ;
; Description: A simple first stage   ;
; bootloader.                         ;
;-------------------------------------;

org		0x7C00
bits	16

start:
	.reset:
		mov		ah, 0
		mov		dl, 0
		int		0x13
		jc		.reset
		
		mov		ax, 0x1000
		mov		es, ax
		xor		bx, bx
		
		call	print_msg
		
		mov		ah, 0x02
		mov		al, 1
		mov		ch, 1
		mov		cl, 2
		mov		dh, 0
		mov		dl, 0
		int		0x13
		
		jmp		0x1000:0x0

print_msg:
	mov		si, msg
	mov		ah, 0x0E
	mov		bx, 0x00
	.print_loop:
		lodsb
		cmp		al, 0
		je		.print_done
		int		0x10
		jmp		.print_loop
	.print_done:
		ret

msg db "Loading second stage bootloader.", 13, 10, 0

times 510 - ($-$$) db 0
dw		0xAA55
I'm using Q (Mac OS X's version of Qemu) and I'm using an ISO disk image to boot. My problem is that nothing happens once it boots, it doesn't even print the message. My first guess is that I used the line:

Code: Select all

mov    dl, 0
Which is the Floppy Drive, I think this is the problem because (as far as I know) I'm not using a floppy drive.

Also, the second stage bootloader doesn't exist. I don't know how to add it to the image. Here's how I'm adding the bootloader to the image:

Code: Select all

dd if=bootloader.bin of=bootable_image.iso
How can I add stuff to the image after I add the bootloader?

ANY help WILL be appreciated, thanks in advanced.

Posted: Sun Nov 25, 2007 9:32 pm
by Dandee Yuyo
Hi Ricardo, I suggest you to first get a stack and not trust the one given to you by the BIOS. You are the OS designer so put it wherever you want in conventional RAM, but be sure it won't be overwritten by the second stage loader...

As for the msg, my first guess is that you are not initializing ds (which is used by lodsb).

Do:

Code: Select all

push cs
pop  ds 
right after the start label so you are sure you'll have ds pointing to the right place. (Same segment as code)

Hope it helps.

As for Qemu on Mac OS, I have no idea how it deals with ISO images, but I would work with floppy images before going to hd images.

Suerte! :D

Posted: Sun Nov 25, 2007 10:06 pm
by osdf_1
I found the problem, the bootloader never really got to the 'call print_msg' instruction because it kept looping in the .reset label. This is because it couldn't reset the drive. I think this is because I'm trying to reset the Floppy Drive. Anyway here's the code:

Code: Select all

;----------[boot_loader.asm]----------;
; Author: Ricardo Diaz                ;
; Description: A simple first stage   ;
; bootloader.                         ;
;-------------------------------------;

org		0x7C00
bits	16

start:
	.reset:
		mov		ah, 0
		mov		dl, 0
		call	print_msg
		int		0x13
		jc		error
		
	mov		ax, 0x1000
	mov		es, ax
	xor		bx, bx
	
	mov		ah, 0x02
	mov		al, 1
	mov		ch, 1
	mov		cl, 2
	mov		dh, 0
	mov		dl, 0
	int		0x13
	
	jmp		0x1000:0x0

error:
	call	print_error
	cli
	hlt

print_msg:
	push	cs
	pop		ds
	mov		si, msg
	mov		ah, 0x0E
	mov		bx, 0x00
	.print_loop:
		lodsb
		cmp		al, 0
		je		.print_done
		int		0x10
		jmp		.print_loop
	.print_done:
		ret

print_error:
	push	cs
	pop		ds
	mov		si, errormsg
	mov		ah, 0x0E
	mov		bx, 0x00
	.print_loop:
		lodsb
		cmp		al, 0
		je		.print_done
		int		0x10
		jmp		.print_loop
	.print_done:
		ret

msg		db "Loading second stage bootloader...", 13, 10, 0
errormsg	db "Could not reset drive. System halted.", 13, 10, 0

times 510 - ($-$$) db 0
dw		0xAA55
Thanks for the help.

Posted: Mon Nov 26, 2007 1:40 am
by osdf_1
Ok, a newer version. I finally got to successfuly reset the drive and to read the second sector (at least I think). Here's the code:

Code: Select all

;----------[boot_loader.asm]----------;
; Author: Ricardo Diaz                ;
; Description: A simple first stage   ;
; bootloader.                         ;
;-------------------------------------;

org		0x7C00
bits	16

start:
	call	print_reset_attempt
	.reset:
		mov		ah, 0
		int		0x13
		jc		.reset
	
	call	print_successful
	
	mov		ax, 0x1000
	mov		es, ax
	xor		bx, bx
	
	call	print_read_attempt
	.read:
		mov		ah, 0x02
		mov		al, 1
		mov		ch, 1
		mov		cl, 2
		mov		dh, 0
		int		0x13
		jc		.read
		
	call	print_successful
		
	jmp		0x1000:0x0
	
;------------------------------;
; All prints go here.          ;
;------------------------------;
	
print_successful:
	push	cs
	pop		ds
	mov		si, succeeded_msg
	mov		bh, 0x00
	mov		bl, 0x00
	mov		ah, 0x0E
	.print_loop:
		lodsb
		cmp		al, 0
		je		.print_done
		int		0x10
		jmp		.print_loop
	.print_done:
		ret
		
print_reset_attempt:
	push	cs
	pop		ds
	mov		si, attempting_reset_msg
	mov		bh, 0x00
	mov		bl, 0x00
	mov		ah, 0x0E
	.print_loop:
		lodsb
		cmp		al, 0
		je		.print_done
		int		0x10
		jmp		.print_loop
	.print_done:
		ret
		
print_read_attempt:
	push	cs
	pop		ds
	mov		si, attempting_read_msg
	mov		bh, 0x00
	mov		bl, 0x00
	mov		ah, 0x0E
	.print_loop:
		lodsb
		cmp		al, 0
		je		.print_done
		int		0x10
		jmp		.print_loop
	.print_done:
		ret

;------------------------------;
;                              ;
;------------------------------;

succeeded_msg		db "Succeeded!", 13, 10, 0
attempting_reset_msg	db "Attempting to reset the drive...", 13, 10, 0
attempting_read_msg		db "Attempting to read sector 2...", 13, 10, 0

times 510 - ($-$$) db 0
dw		0xAA55
"Succeeded!" is displayed both times, so everything is correct except for the 'jmp 0x1000:0x0'. What I think is that the system halts because there's nothing in the second sector (I haven't added the second stage to the image). How can I add it?

Posted: Mon Nov 26, 2007 3:01 pm
by osdf_1
I know nobody is answering these questions but I'm posting this to help out beginners that are on the same place I am.

Anyway I finally got to load the second stage and got it to display a simple '>'. Here's the code for the first stage:

Code: Select all

;-------------[stage1.asm]-------------;
; Author: Ricardo Diaz                 ;
; Description: A simple first stage    ;
; bootloader.                          ;
;--------------------------------------;

org		0x7C00							; We were loded at 0x7C00
bits	16								; We're in real mode

start:
	call	print_reset_attempt			; Print "Attempting to reset..."
	.reset:
		mov		ah, 0x0					; Reset drive function
		int		0x13					; BIOS 'Low level disk services' interrupt
		jc		.reset					; Try again if carry flag was set
	
	call	print_successful			; Print "Succeeded"
	
	mov		ax, 0x1000					; We'll load the second stage at 0x1000
	mov		es, ax
	xor		bx, bx
	
	call	print_read_attempt			; Print "Attempting to read..."
	.read:
		mov		ah, 0x02				; Read sector function
		mov		al, 1					; Read one sector
		mov		ch, 0					; Read from track one
		mov		cl, 2					; Read sector two
		mov		dh, 0					; Read from head zero
		int		0x13					; BIOS 'Low level disk services' interrupt
		jc		.read					; Try again if carry flag was set
		
	call	print_successful			; Print "Succeeded"
		
	jmp		0x1000:0x0					; Jump to the second stage
	
;------------------------------;
; All prints go here.          ;
;------------------------------;
	
print_successful:
	push	cs
	pop		ds
	mov		si, succeeded_msg
	mov		bh, 0x00
	mov		bl, 0x00
	mov		ah, 0x0E
	.print_loop:
		lodsb
		cmp		al, 0
		je		.print_done
		int		0x10
		jmp		.print_loop
	.print_done:
		ret
		
print_reset_attempt:
	push	cs
	pop		ds
	mov		si, attempting_reset_msg
	mov		bh, 0x00
	mov		bl, 0x00
	mov		ah, 0x0E
	.print_loop:
		lodsb
		cmp		al, 0
		je		.print_done
		int		0x10
		jmp		.print_loop
	.print_done:
		ret
		
print_read_attempt:
	push	cs
	pop		ds
	mov		si, attempting_read_msg
	mov		bh, 0x00
	mov		bl, 0x00
	mov		ah, 0x0E
	.print_loop:
		lodsb
		cmp		al, 0
		je		.print_done
		int		0x10
		jmp		.print_loop
	.print_done:
		ret

;------------------------------;
;                              ;
;------------------------------;

succeeded_msg			db "Succeeded!", 13, 10, 0
attempting_reset_msg	db "Attempting to reset the drive...", 13, 10, 0
attempting_read_msg		db "Attempting to read sector 2...", 13, 10, 0

times 510 - ($-$$) db 0						; Fill up with zeros
dw		0xAA55								; Boot signature
And here's the code for the second stage:

Code: Select all

org		0x1000
bits	16

start:
	mov		ah, 0x0E
	mov		al, 13
	xor		bx, bx
	int		0x10
	mov		al, 10
	int		0x10
	mov		al, 62
	int		0x10
	
	jmp		$
The way I added the files to the image was like this:

cat stage1.bin stage2.bin > bootloader

Then:

dd if=bootloader of=bootable_image.iso

Everything worked fine. I don't even know if this is the right way to do this but it did load it and that's pretty much what I want.

BTW I'm using a mac.

Posted: Mon Dec 17, 2007 7:36 am
by Red Shaya
Here are a few points to notice:

1. Resetting the FD in an endless loop:
I would suggest to use a counter for the retries, I'm using five retries, but you can decide on your own preference. Just try a few times and if you don't succeed, just stop trying and show an error message

Code: Select all

    PUSH CS
    POP DS
    MOV CX,5
    XOR AH,AH
.Reset_disk
    INT 13
    JNC .Read_disk
    LOOP .Reset_disk   ; retry for 5 times
    ; Print a reset error message
    MOV SI, ResetErrorMsg
    CALL PrintStr         ; print the error message
    JMP .Stop
.Read_disk
    MOV AH,02
    MOV AL,SectNumber
    MOV BX,Stage2Address
    MOV CX,0001     ; read from cylinder #1
    XOR DX,DX        ; Read from floppy (Disk 0)
    INT 13
    JNC .RunStage2
    MOV SI,ReadFailMsg
    CALL PrintStr     ; Print the read error message
.Stop
    HLT
.RunStage2
    JMP Stage2Address
.PrintStr
    PUSH BX
    PUSH AX
    MOV AH,0E
    MOV BX,0007
    LODSB
.RdChr
    JZ .EndStr
    INT 10
    JMP .RdChr
.EndStr
    POP AX
    POP BX
    RET
2. Every new OS developer tries to write a boot loader. It's a nice practice but try not to waste too much time on it. Use a boot loader like GRUB.
(If you look at the link in my signature it may sound funny hearing it from me, but trust me. If you are into writing an OS, focus on writing the OS instead of writing and struggling with a boot loader. If you are into challenges ... then that's a different story)