Author Topic: 2 Stage Bootloader  (Read 91824 times)

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
2 Stage Bootloader
« on: July 21, 2014, 08:27:35 PM »
I have been following this tutorial in programming your own OS but for now I wanna just focus on the bootloader how it works what tools I need to create one etc.. So Now I have created the first part of the bootloader and I have modified it from the tutorial by adding my own itoa and atoi functions and creating my own version of the print string function here is my code for stage 1 and the link to the tutorial : Link: http://www.brokenthorn.com/Resources Code :
Code: [Select]
[BITS 16]
[ORG 0x7c00]

jmp Start


Start:
;set up the stack
xor ax, ax;set ax to zero remember that the when both value are the same in the exclusive or operation the both cancel out to zero
mov ds, ax
mov ss, ax

mov sp, 0x9c00
mov es, ax

;pass in the message into si Register
mov si, MSG
;then call the String print function
call sPrint

xor ax, ax;clear out ax for use
int 0x12;returns amount of ram in ax

call itoa


.Reset:
mov ah, 0 ; reset floppy disk function
mov dl, 0 ; drive 0 is floppy drive
int 0x13 ; call BIOS
jc .Reset ; If Carry Flag (CF) is set, there was an error. Try resetting again
 .Read:
mov ax, 0x1000 ; we are going to read sector to into address 0x1000:0
mov es, ax
xor bx, bx
 
mov ah, 0x02 ; read floppy sector function
mov al, 1 ; read 1 sector
mov ch, 1 ; we are reading the second sector past us, so its still on track 1
mov cl, 2 ; sector to read (The second sector)
mov dh, 0 ; head number
mov dl, 0 ; drive number. Remember Drive 0 is floppy drive.
int 0x13 ; call BIOS - Read the sector

 
jmp 0x1000:0x0 ; jump to execute the sector!



cli;clear interrupts
hlt;halt the system






%include "itoa_atoi.asm"
Input db 0
BootDrive dw 0
MSG: db "This is my OS! The number is : ",13,10,0

;vars

bpbOEM db "My OS   "

bpbBytesPerSector:  DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs:     DB 2
bpbRootEntries:     DW 224
bpbTotalSectors:     DW 2880
bpbMedia:             DB 0xF0
bpbSectorsPerFAT:     DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors:     DD 0
bpbTotalSectorsBig:     DD 0
bsDriveNumber:         DB 0
bsUnused:             DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber:         DD 0xa0a1a2a3
bsVolumeLabel:         DB "MOS FLOPPY "
bsFileSystem:         DB "FAT12   "


;vars

times 510 - ($-$$) db 0
dw 0xAA55




Stage 2 boot loader :
Code: [Select]
; Note: Here, we are executed like a normal
; COM program, but we are still in Ring 0.
; We will use this loader to set up 32 bit
; mode and basic exception handling
 
; This loaded program will be our 32 bit Kernel.
 
; We do not have the limitation of 512 bytes here,
; so we can add anything we want here!
 
org 0x0 ; offset to 0, we will set segments later
 
bits 16 ; we are still in real mode
 
; we are loaded at linear address 0x10000
 
jmp main ; jump to main
 
 
;*************************************************;
; Second Stage Loader Entry Point
;************************************************;
 
main:
cli ; clear interrupts
push cs ; Insure DS=CS
pop ds
 
mov si, Msg
call sPrint
 
cli ; clear interrupts to prevent triple faults
hlt ; hault the system
 
;*************************************************;
; Data Section
;************************************************;
%include "itoa_atoi.asm"
Msg db "Preparing to load operating system...",13,10,0

Here is the include file don't know why I didn't put it here in the first place
Code: [Select]

itoa:;number is passed into ax
jmp .beggining
.negate:

neg ax
push ax

mov al, '-'
mov ah, 0xe
int 0x10
pop ax
jmp .top
.beggining:
xor bx , bx
mov cx, 10;mov into cx 10
cmp ax, 0
jl .negate


.top:
;divide by 10 and push remainder onto stack
xor dx, dx;clear out remainder
div cx ;divide ax by 10
push dx;push the remainder onto the stack for later
inc bx;count the number of digits
test ax,ax;if ax = 0 then stop
jne .top

.loop:
pop ax;restore the remainder
add ax, '0';convert to ASCII
mov ah, 0xe;print
int 0x10
dec bx;get ready for the next digit
cmp bx, 0;if not zero then jump to .loop
jne .loop
ret



atoi:

xor ax, ax;clear out ax for the result
mov cx, 10;mov into cx 10
add bx, 80
mov byte[bx], 0;null terminate the number
sub bx, 80
xor dx, dx;clear out dx for use

.top:
mov dl, byte[bx]
cmp dl, 0;if end of string then out
je .done

sub dl, '0';convert to number
push dx;save the number

xor dx, dx
mul cx;multiply by ten

pop dx;restore the number

add ax, dx;add to the result


inc bx;get ready for the next digit


jmp .top
.done:;finished
ret

sPrint:
.loop:
lodsb;move to the next letter in the string
mov ah, 0xe;print it
int 0x10
test al, al;if the register al is not equal to zero then jump back to the top
jne .loop


ret; return back to after where you where called


Where I run into a problem is I have no idea how to run the second stage, Also I am using Virtual box instead of bochs and VFD and I assemble the file as a .img for floppy disks
« Last Edit: July 21, 2014, 11:31:42 PM by Anonymous »
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: 2 Stage Bootloader
« Reply #1 on: July 21, 2014, 10:56:09 PM »
Well... first, your link to BrokenThorn doesn't work because of the semicolon. I could edit that for you, but I'll leave it for you. (that cryptic icon just above "report to moderator" if you haven't figured that out)

What's the problem? You jump to stage2 at the end of stage1 - it should just run. Contrary to the comment in stage2, you only load 1 sector in stage1, so you're limited to 512 bytes. I don't think that's a problem. I don't know why your BPB is in stage2 - shouldn't that be in stage1?

While I do have a real floppy in my current machine, I can't easily test this - no include file. I could probably write my own - I think I see what it needs to do, but not in the mood right now. I have no experience with emulators, so can't help you with that part...

Best,
Frank


Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #2 on: July 21, 2014, 11:23:47 PM »
Sorry about that I changed the icon I thought that icon just ment' question and I am trying to copy the file to the floppy image without overwriting the image in the tutorial it says to do this
Code: [Select]
nasm -f bin Stage2.asm -o STAGE2.SYS
copy STAGE2.SYS  A:\STAGE2.SYS
The problem with that is that I only have the .img file not a Drive at all and I am not using Bochs or VFD and I wan't to avoid using them unless There is no other way to do so, Instead I do this :
Code: [Select]
nasm -f bin Stage2.asm -o STAGE2.SYS
copy STAGE2.SYS  Boot.img
And then it asks me if I wan't to overwrite it and I say no because if I do it won't boot it will just try to run at 0x0 and it will give me a fatal error.(I edited the code to have the BPB in Stage 1)
« Last Edit: July 21, 2014, 11:28:21 PM by Anonymous »
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: 2 Stage Bootloader
« Reply #3 on: July 22, 2014, 12:06:44 AM »
I think copying stage2 to "A:stage2.bin" would require a filesystem to load it - that's where the BPB would come in. Your stage1 seems to assume stage2 is in the second sector. I think what I used to do is something like "copy /b stage1.bin + stage2.bin img.bin" and then write "img.bin" to floppy with... "rawrite" or John Fine's "partcopy" or DEBUG will do it, or it's easy to write your own. ASSuming that stage1 is exactly 512 bytes, that should put stage2 in the second sector, where stage1 expects it. Your stage1 loads the second sector to segment 1000 offset 0 and jumps to it. Your "push cs / pop ds" in stage2 should fix up ds so it can find your message. I don't know how all this would work out in an emulator.

Best,
Frank


Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #4 on: July 22, 2014, 02:32:59 AM »
I try to copy both onto the image file but for some reason it only copies one of the files. This is what I have tried.
Code: [Select]
copy /b Boot.bin + Boot2.bin BootLoader.bin
copy /b BootLoader.bin BootLoader.img
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: 2 Stage Bootloader
« Reply #5 on: July 22, 2014, 03:24:36 AM »
Perhaps I misremember. What's the size of the presumed combined file look like? Maybe, with the include file now, I'll give it a shot. Not right this minute...

Best,
Frank


Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #6 on: July 22, 2014, 03:28:26 AM »
Well Boot.asm which is the first stage is 2kb and Stage2.asm is 2kb so 4kb
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: 2 Stage Bootloader
« Reply #7 on: July 22, 2014, 03:35:47 AM »
That seems way too big. Oh, wait - size of the binary, not the source.

Best,
Frank


Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #8 on: July 22, 2014, 04:12:24 AM »
1kb each so 2kb
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: 2 Stage Bootloader
« Reply #9 on: July 22, 2014, 04:59:45 AM »
If stage1 doesn't assemble to 512 bytes exactly, something is dreadfully wrong! Lemee download your files and see what I can see. After I eat. Maybe before I sleep, but no promises...

Best,
Frank


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: 2 Stage Bootloader
« Reply #10 on: July 22, 2014, 06:55:34 AM »
Okay...
Code: [Select]
[BITS 16]
[ORG 0x7c00]

jmp Start


Start:
;set up the stack
xor ax, ax;set ax to zero remember that the when both value are the same in the exclusive or operation the both cancel out to zero
mov ds, ax
mov ss, ax

mov sp, 0x9c00
mov es, ax

;pass in the message into si Register
mov si, MSG
;then call the String print function
call sPrint

xor ax, ax;clear out ax for use
int 0x12;returns amount of ram in ax

call itoa


.Reset:
mov ah, 0 ; reset floppy disk function
mov dl, 0 ; drive 0 is floppy drive
int 0x13 ; call BIOS
jc .Reset ; If Carry Flag (CF) is set, there was an error. Try resetting again
 .Read:
mov ax, 0x1000 ; we are going to read sector to into address 0x1000:0
mov es, ax
xor bx, bx
 
mov ah, 0x02 ; read floppy sector function
mov al, 1 ; read 1 sector
; mov ch, 1 ; we are reading the second sector past us, so its still on track 1
        mov ch, 0 ; sectors start with 1, tracks start with 0!
mov cl, 2 ; sector to read (The second sector)
mov dh, 0 ; head number
mov dl, 0 ; drive number. Remember Drive 0 is floppy drive.
int 0x13 ; call BIOS - Read the sector

 
jmp 0x1000:0x0 ; jump to execute the sector!



cli;clear interrupts
hlt;halt the system






%include "itoa_atoi.asm"
Input db 0
BootDrive dw 0
MSG: db "This is my OS! The number is : ",13,10,0

;vars

bpbOEM db "My OS   "

bpbBytesPerSector:  DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs:     DB 2
bpbRootEntries:     DW 224
bpbTotalSectors:     DW 2880
bpbMedia:             DB 0xF0
bpbSectorsPerFAT:     DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors:     DD 0
bpbTotalSectorsBig:     DD 0
bsDriveNumber:         DB 0
bsUnused:             DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber:         DD 0xa0a1a2a3
bsVolumeLabel:         DB "MOS FLOPPY "
bsFileSystem:         DB "FAT12   "


;vars

times 510 - ($-$$) db 0
dw 0xAA55

I think that's your main problem. Confusing that cylinders and heads start with 0 but sectors start with 1!

Initially, I was getting your message (from stage1) and the number three times(!) so I fiddled with your include file, too (wrongly, the first two times!). You were/are checking for zero (end of string) after the interrupt - I'm not sure al will still be zero after the interrupt, so I put the test first (and then forgot to jump back to ".loop"!). That may or may not have been the problem there. I think the main thing was the wrong cylinder/track number.

What I did, for the record, was:
Code: [Select]
nasm -f bin stage1.asm -o stage1.bin
nasm -f bin stage2.asm -o stage2.bin
cat stage1.bin stage2.bin>img.bin
dd if=img.bin of=/dev/fd0
"copy /b" ought to work the same as "cat". Dunno what you do then to get it to work with VirtualBox instead of a real floppy. I should check out that or some emulator - all that rebootin' gets old quick!

Best,
Frank


Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #11 on: July 22, 2014, 09:06:34 AM »
Well What I tried to do was to cat in Linux in virtual box email it to myself then copying the img.bin to my Boot.img and then try and run but still no luck will keep trying though I know I am close
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: 2 Stage Bootloader
« Reply #12 on: July 22, 2014, 09:14:32 AM »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: 2 Stage Bootloader
« Reply #13 on: July 22, 2014, 09:51:40 AM »
Here's a crazy thought:

Code: [Select]
; nasm -f bin fakeflop.asm -o fakeflop.img

bits 16 ; just for clarity
incbin "stage1.bin"
incbin "stage2.bin"
times (512 * 2880) - ($ - $$) db 0

Makes a big file - 1474560 - is that right? - that you might be able to persuade VirtualBox is a bootable floppy?

Best,
Frank


Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #14 on: July 22, 2014, 06:08:21 PM »
Wow It worked How does that work exactly It looks like a file with just two includes but it works like copy or cat
Thanks in advance, Anonymous