HDD Bootloader for c++ kernel

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
Dhaann
Posts: 19
Joined: Fri Dec 19, 2008 1:37 pm

HDD Bootloader for c++ kernel

Post by Dhaann »

Hello everybody,
I've written a kernel in c++ and i have got a bootloader for a floppy.
However, I know that it wouldn't work on a hard drive, so does anybody know a good site or source for a hdd bootloader? And I use partcopy to write the bootloader to the floppy, but how do I use it for a hdd?
Hope someone can help me!

Daniel
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: HDD Bootloader for c++ kernel

Post by 01000101 »

If you're using INT 0x13/AH=0x02 for loading sectors, then just change the drive ID and compensate for the differences in cylinder/track/sector per track counts and re-use that same INT. Use INT 0x13/AH=0x08 to get the drive parameters, then use those values later for INT 0x13/AH=0x02.

This will allow you to boot of just about any normal media.
Dhaann
Posts: 19
Joined: Fri Dec 19, 2008 1:37 pm

Re: HDD Bootloader for c++ kernel

Post by Dhaann »

This is my bootloader:

Code: Select all

[BITS 16]
[ORG 0x0000]
jmp     START
     
     OEM_ID                db "QUASI-OS"
     BytesPerSector        dw 0x0200
     SectorsPerCluster     db 0x01
     ReservedSectors       dw 0x0001
     TotalFATs             db 0x02
     MaxRootEntries        dw 0x00E0
     TotalSectorsSmall     dw 0x0B40
     MediaDescriptor       db 0xF0
     SectorsPerFAT         dw 0x0009
     SectorsPerTrack       dw 0x0012
     NumHeads              dw 0x0002
     HiddenSectors         dd 0x00000000
     TotalSectorsLarge     dd 0x00000000
     DriveNumber           db 0x00
     Flags                 db 0x00
     Signature             db 0x29
     VolumeID              dd 0xFFFFFFFF
     VolumeLabel           db "QUASI  BOOT"
     SystemID              db "FAT12   "
     
     START:
          cli
          mov     ax, 0x07C0
          mov     ds, ax
          mov     es, ax
          mov     fs, ax
          mov     gs, ax
          mov     ax, 0x0000
          mov     ss, ax
          mov     sp, 0xFFFF
          sti
          mov     si, msgLoading
          call    DisplayMessage
     LOAD_ROOT:
          xor     cx, cx
          xor     dx, dx
          mov     ax, 0x0020
          mul     WORD [MaxRootEntries]
          div     WORD [BytesPerSector]
          xchg    ax, cx
          mov     al, BYTE [TotalFATs]
          mul     WORD [SectorsPerFAT]
          add     ax, WORD [ReservedSectors]
          mov     WORD [datasector], ax
          add     WORD [datasector], cx
          mov     bx, 0x0200
          call    ReadSectors
          mov     cx, WORD [MaxRootEntries]
          mov     di, 0x0200
     .LOOP:
          push    cx
          mov     cx, 0x000B
          mov     si, ImageName
          push    di
     rep  cmpsb
          pop     di
          je      LOAD_FAT
          pop     cx
          add     di, 0x0020
          loop    .LOOP
          jmp     FAILURE
     LOAD_FAT:
          mov     si, msgCRLF
          call    DisplayMessage
          mov     dx, WORD [di + 0x001A]
          mov     WORD [cluster], dx
          xor     ax, ax
          mov     al, BYTE [TotalFATs]
          mul     WORD [SectorsPerFAT]
          mov     cx, ax
          mov     ax, WORD [ReservedSectors]
          mov     bx, 0x0200
          call    ReadSectors
          mov     si, msgCRLF
          call    DisplayMessage
          mov     ax, 0x0100
          mov     es, ax
          mov     bx, 0x0000
          push    bx
     LOAD_IMAGE:
          mov     ax, WORD [cluster]
          pop     bx
          call    ClusterLBA
          xor     cx, cx
          mov     cl, BYTE [SectorsPerCluster]
          call    ReadSectors
          push    bx
          mov     ax, WORD [cluster]
          mov     cx, ax
          mov     dx, ax
          shr     dx, 0x0001
          add     cx, dx
          mov     bx, 0x0200
          add     bx, cx
          mov     dx, WORD [bx]
          test    ax, 0x0001
          jnz     .ODD_CLUSTER
     .EVEN_CLUSTER:
          and     dx, 0000111111111111b
         jmp     .DONE
     .ODD_CLUSTER:
          shr     dx, 0x0004
     .DONE:
          mov     WORD [cluster], dx
          cmp     dx, 0x0FF0
          jb      LOAD_IMAGE
     DONE:
          mov     si, msgCRLF
          call    DisplayMessage
          push    WORD 0x0100
          push    WORD 0x0000
          retf
     FAILURE:
          mov     si, msgFailure
          call    DisplayMessage
          mov     ah, 0x00
          int     0x16
          int     0x19
     DisplayMessage:
          lodsb
          or      al, al
          jz      .DONE
          mov     ah, 0x0E
          mov     bh, 0x00
          mov     bl, 0x07
          int     0x10
          jmp     DisplayMessage
     .DONE:
          ret
     ReadSectors:
     .MAIN
          mov     di, 0x0005
     .SECTORLOOP
          push    ax
          push    bx
          push    cx
          call    LBACHS
          mov     ah, 0x02
          mov     al, 0x01
          mov     ch, BYTE [absoluteTrack]
          mov     cl, BYTE [absoluteSector]
          mov     dh, BYTE [absoluteHead]
          mov     dl, BYTE [DriveNumber]
          int     0x13
          jnc     .SUCCESS
          xor     ax, ax
          int     0x13
          dec     di
          pop     cx
          pop     bx
          pop     ax
          jnz     .SECTORLOOP
          int     0x18
     .SUCCESS
          mov     si, msgProgress
          call    DisplayMessage
          pop     cx
          pop     bx
          pop     ax
          add     bx, WORD [BytesPerSector]
          inc     ax
          loop    .MAIN
          ret
     ClusterLBA:
          sub     ax, 0x0002
          xor     cx, cx
          mov     cl, BYTE [SectorsPerCluster]
          mul     cx
          add     ax, WORD [datasector]
          ret
     LBACHS:
          xor     dx, dx
          div     WORD [SectorsPerTrack]
          inc     dl
          mov     BYTE [absoluteSector], dl
          xor     dx, dx
          div     WORD [NumHeads]
          mov     BYTE [absoluteHead], dl
          mov     BYTE [absoluteTrack], al
          ret

     absoluteSector db 0x00
     absoluteHead   db 0x00
     absoluteTrack  db 0x00
     
     datasector  dw 0x0000
     cluster     dw 0x0000
     ImageName   db "KERNEL  BIN"
     msgLoading  db 0x0D, 0x0A, "Loading Boot Image ", 0x0D, 0x0A, 0x00
     msgCRLF     db 0x0D, 0x0A, 0x00
     msgProgress db ".", 0x00
     msgFailure  db 0x0D, 0x0A, "ERROR : Press Any Key to Reboot", 0x00
     
          TIMES 510-($-$$) DB 0
          DW 0xAA55
I'ts special for floppy's written, so I think I've to write a complete new bootloader..
User avatar
IanSeyler
Member
Member
Posts: 326
Joined: Mon Jul 28, 2008 9:46 am
Location: Ontario, Canada
Contact:

Re: HDD Bootloader for c++ kernel

Post by IanSeyler »

The FreeDOS project has some open source bootloaders that boot from the hard drive.

They can be found here: http://freedos.cvs.sourceforge.net/view ... rnel/boot/

I use a modified version of boot32lb.asm (Boot via HDD with FAT32) to load my second level loader.

-Ian
BareMetal OS - http://www.returninfinity.com/
Mono-tasking 64-bit OS for x86-64 based computers, written entirely in Assembly
Dhaann
Posts: 19
Joined: Fri Dec 19, 2008 1:37 pm

Re: HDD Bootloader for c++ kernel

Post by Dhaann »

Thanks for the link!
This is my hdd bootloader now:

Code: Select all

segment	.text

		org	0x7c00

Entry:		jmp	short real_start
			nop

; %define bsOemName	bp+0x03
%define bsBytesPerSec	bp+0x0b
%define bsSecPerClust	bp+0x0d
%define bsResSectors	bp+0x0e
%define bsFATs			bp+0x10
; %define bsRootDirEnts	bp+0x11
; %define bsSectors	bp+0x13
; %define bsMedia	bp+0x15
; %define sectPerFat	bp+0x16
%define sectPerTrack	bp+0x18
; %define nHeads	bp+0x1a
%define nHidden		bp+0x1c
; %define nSectorHuge	bp+0x20
%define xsectPerFat	bp+0x24
%define xrootClst	bp+0x2c
%define drive		bp+0x40
%define loadsegoff_60	bp+loadseg_off-Entry
%define LOADSEG		0x0060
%define FATSEG		0x2000
%define	fat_secshift	fat_afterss-1
%define fat_sector	bp+0x44
%define fat_start	bp+0x48
%define data_start	bp+0x4c
		times	0x5a-$+$$ db 0
real_start:	cld
		cli
		sub	ax, ax
		mov	ds, ax
		mov	bp, 0x7c00

		mov	ax, 0x1FE0
		mov	es, ax
		mov	si, bp
		mov	di, bp
		mov	cx, 0x0100
		rep	movsw
		jmp	word 0x1FE0:cont

loadseg_off	dw	0, LOADSEG

cont:	mov	ds, ax
		mov	ss, ax
        lea     sp, [bp-0x20]
		sti
		mov	[drive], dl

		mov	si, msg_LoadFreeDOS
		call	print
calc_params:	xor	eax, eax
		mov	[fat_sector], eax
		mov	ax, [bsResSectors]
		add	eax, [nHidden]
		mov 	[fat_start], eax
		mov	[data_start], eax
		mov	eax, [bsFATs]
		imul	dword [xsectPerFat]
		add	[data_start], eax
		mov	ax, 512
		; mov	cl, 9-2
fatss_scan:	cmp	ax, [bsBytesPerSec]
		jz	fatss_found
		add	ax,ax
		; inc	cx
		inc	word [fat_secshift]
		jmp 	short fatss_scan
fatss_found:
		mov	eax, [xrootClst]
ff_next_clust:	push	eax
		call	convert_cluster
		jc	boot_error				
ff_next_sector:	les	bx, [loadsegoff_60]
		call	readDisk
		; push	eax
		; xor	ax, ax
		xor	di, di
ff_next_entry:	mov	cx, 11
		mov	si, filename
		; mov	di, ax
		repe	cmpsb
		jz	ff_done
		; add	ax, 0x20
		;cmp 	ax, [bsBytesPerSec]
		add	di, byte 0x20
		and	di, byte -0x20
		cmp	di, [bsBytesPerSec]
		jnz	ff_next_entry
		; pop	eax
		dec 	dx
		jnz	ff_next_sector
ff_walk_fat:	pop	eax
		call	next_cluster
		jmp	ff_next_clust
ff_done:	push	word [es:di+0x14-11]
			push	word [es:di+0x1A-11]
			pop	eax
			sub	bx, bx
read_kernel:	push	eax
		call	convert_cluster
		jc	boot_success
rk_in_cluster:	call	readDisk
		dec	dx
		jnz	rk_in_cluster
rk_walk_fat:	pop	eax
		call	next_cluster
		jmp	read_kernel
boot_success:	mov	bl, [drive]
		jmp	far [loadsegoff_60]
boot_error:	mov	si, msg_BootError
		call	print
wait_key:	xor	ah,ah
			int	0x16
reboot:		int	0x19
next_cluster:	push	es
		push	di
		push	bx
		mov	di, ax
		shl	di, 2
		push	ax
		mov	ax, [bsBytesPerSec]
		dec	ax
		and	di, ax
		pop	ax
		shr	eax, 7
fat_afterss:
		add	eax, [fat_start]
		mov	bx, FATSEG
		mov	es, bx
		sub	bx, bx
		cmp	eax, [fat_sector]
		jz	cn_buffered
		mov	[fat_sector],eax
		call	readDisk
cn_buffered:	and	byte [es:di+3],0x0f
		mov	eax, [es:di]
		pop	bx
		pop 	di
		pop	es
		ret
convert_cluster:
		cmp	eax, 0x0ffffff8
		jnb	end_of_chain
		; sector = (cluster-2) * clustersize + data_start
		dec	eax
		dec	eax
		movzx	edx, byte [bsSecPerClust]
		push	edx
		mul	edx
		pop	edx
		add	eax, [data_start]
		ret
end_of_chain:	stc
		ret
printchar:	xor	bx, bx
		mov	ah, 0x0e
		int	0x10
print:		lodsb
		cmp	al, 0
		jne	printchar
		ret
readDisk:	push	dx
		push	si
		push	di
read_next:	push	eax
		mov	di, sp
		; db	0x66
		push	byte 0
		push	byte 0
		push	eax
		push	es
		push	bx
		push	byte 1
		push	byte 16
		mov	si, sp
		mov	dl, [drive]
		mov	ah, 42h
		int	0x13	
		mov	sp, di
		pop	eax
		jnc	read_ok
		push	ax
		xor	ah, ah
		int	0x13
		pop	ax
		jmp	read_next
read_ok:	inc 	eax
		add	bx, word [bsBytesPerSec]
		jnc	no_incr_es
		mov	dx, es
		add	dh, 0x10
		mov	es, dx
no_incr_es:	pop	di
		pop 	si
		pop	dx
		ret
msg_LoadFreeDOS db "Loading Thunder Core",0
       times 0x01ee-$+$$ db 0
msg_BootError	db "No "
filename	db "KERNEL  BIN"
sign		dw 0, 0xAA55
As I said, I use partcopy to write the bootloader. Usually, I write it into a floppy, but what about a hdd? What command do I use for that?
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: HDD Bootloader for c++ kernel

Post by Solar »

Wow. Two bootloader source dumps without a single comment line.
Every good solution is obvious once you've found it.
User avatar
Coty
Member
Member
Posts: 286
Joined: Thu Feb 12, 2009 5:12 pm

Re: HDD Bootloader for c++ kernel

Post by Coty »

with two you should have a good choice :)
My hero, is Mel.
Hyperdrive
Member
Member
Posts: 93
Joined: Mon Nov 24, 2008 9:13 am

Re: HDD Bootloader for c++ kernel

Post by Hyperdrive »

Solar wrote:Wow. Two bootloader source dumps without a single comment line.
That's not true, have a closer look:

Code: Select all

[...]
; %define bsRootDirEnts   bp+0x11
; %define bsSectors   bp+0x13
; %define bsMedia   bp+0x15
; %define sectPerFat   bp+0x16
[...]
:twisted:

Sorry, couldn't resist... ;)

--TS
Dhaann
Posts: 19
Joined: Fri Dec 19, 2008 1:37 pm

Re: HDD Bootloader for c++ kernel

Post by Dhaann »

Solar wrote:Wow. Two bootloader source dumps without a single comment line.
I've removed the comments, because if i didn't, it would be a VERY long code! And I wrote it in Notepad++ where u can see the difference in comment and normal color because of the colors. As u can see, it's all green what makes it obscure.

BTW, I'm testing my OS on my formatted laptop, so there's no single bootloader/MBR. I've been thinking: If I only put a single bootloader in the first partition, and there's no MBR, how can it boot??? Not. Can anyone help me with writing a MBR (or u have a good source)? It would be very nice! :D
Dhaann
Posts: 19
Joined: Fri Dec 19, 2008 1:37 pm

Re: HDD Bootloader for c++ kernel

Post by Dhaann »

I've got a MBR now and I use partcopy to write the bootloaders. I know how to do with floppies and normal partitions, but what about the MBR? How do I write it with partcopy? Or do I have to use another one?
Dhaann
Posts: 19
Joined: Fri Dec 19, 2008 1:37 pm

Re: HDD Bootloader for c++ kernel

Post by Dhaann »

How can I do it with dd? BTW: I put the floppy in my laptop and THEN I write everything (bootloader, kernel,etc.). Is it possible to use dd on a floppy?
Post Reply