Assembly bootloader FAT32

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
roban100
Posts: 9
Joined: Wed Aug 07, 2013 10:05 am

Assembly bootloader FAT32

Post by roban100 »

So I had already made my bootloader in Fat12, and started to program in C.
But lately I wanted to switch to FAT32 so... I have set up the FAT32 Extended BIOS Parameter Block and everything else. But my question is in FAT12/16 you knew where the root directory was so it was easy to load into memory. But in FAT32 you don't. You can specify where it shold begin but how do I know how big it is to load it to memory?

Hope It's not too stupid :) but I can't figure it out, but I could in FAT12.

And also is the root directory entry the same as in FAT12.. I think i read it isn't!
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: Assembly bootloader FAT32

Post by egos »

roban100 wrote:But my question is in FAT12/16 you knew where the root directory was so it was easy to load into memory. But in FAT32 you don't. You can specify where it shold begin but how do I know how big it is to load it to memory?
Bootloader - Read FAT
And also is the root directory entry the same as in FAT12.. I think i read it isn't!
ClusterHi field was added. Read the Spec.
If you have seen bad English in my words, tell me what's wrong, please.
azblue
Member
Member
Posts: 147
Joined: Sat Feb 27, 2010 8:55 pm

Re: Assembly bootloader FAT32

Post by azblue »

roban100 wrote:how do I know how big it is to load it to memory?
Unlike the fat12/16 RDEs, the Fat32 RDE is not a fixed size; it's a regular folder; it expands as needed. If you want to know how big it is you'll have to read through the cluster chain until you get an "End of File."

I believe it starts at Cluster "2" (the first "real" cluster); I don't recall whether or not you can specify a different cluster (you said you already set up your extended BPB; if you can specify where the cluster the RDE starts at I'm sure it'd be there).
HugeCode
Member
Member
Posts: 112
Joined: Mon Dec 17, 2012 9:12 am

Re: Assembly bootloader FAT32

Post by HugeCode »

I wanted to do some paging tests in different environment so I wrote small stage2 for loading from FAT. It isn't really useful, but it can be a good start:

Code: Select all

mov ebx, dword [0x7DC6] ;0x7C00 + 0x1BE(first partition entry) + 8(LBA start on disk)
	push ebx
	
%define FAT_BPB 0x9000       ;not only for BPB, but also for any temporary data
	mov edi, FAT_BPB
	mov si, 0x1 ;read BPB
	call ata_pio28_read
	
	;Getting some FAT info
	xor eax, eax
	mov ax, word [FAT_BPB+14]
	mov word [rsvd], ax
	add eax, dword [esp]	;Add reserved count to sector address
	mov dword [fat_start], eax	;save address of FAT in memory for future use (when loading)
	mov dword [esp], eax	;save address of FAT on stack
	
	xor ecx, ecx
	mov cl, byte [FAT_BPB+13]
	mov byte [sec_p_c], cl
	
	mov ax, word [FAT_BPB+11]	;bytes per sector
	mov word [b_p_s], ax
	mul cx
	mov dword [b_p_c], eax
	
	mov eax, dword [FAT_BPB+0x24]
	mov dword [sec_per_fat], eax
	
	xor ebx, ebx
	mov bl, byte [FAT_BPB+0x10]
	mov byte [n_of_fats], bl
	mul ebx						;Multiply sectors per fat by # of fats to get their complete size
	add dword [esp], eax		;Set sector pointer after FAT tables
	
	pop dword [root_sec]		;save calculated fsroot
	
	mov eax, dword [FAT_BPB+0x2C]	
	mov dword [actual_cluster], eax	;save for next loading
	
	mov edi, FAT_BPB			;temporary data address
	mov ebx, dword [actual_cluster]
	.load_cluster:
		call cluster_read
		xor ecx, ecx
	.search_cluster:
		cmp byte [FAT_BPB+ecx], 0x0
		jz .error
		cmp byte [FAT_BPB+ecx], 0xE5
		je .go
		
		;test first 11 characters here (SFN)
		
		.go:
		add ecx, 0x20	;32bytes for single directory entry
		cmp ecx, dword [b_p_c]
		jl .search_cluster
		
		.not_found:
		sub ebx, 2
		cmp ebx, 0xFFFFFF0-2
		jae .error
		add ebx, 2
		
		jmp .load_cluster
	
	.error:
	mov esi, kernel_not_found
	call prints
	jmp $
	
	.found:
		mov bx, word [FAT_BPB+ecx+20]
		shl ebx, 16
		mov bx, word [FAT_BPB+ecx+26]
		mov edi, 0x200000
		sub ebx, 2
		.file_load:
			add ebx, 2
			call cluster_read
			add edi, dword [b_p_c]
			sub ebx, 2
			cmp ebx, 0xFFFFFF0-2
			jb .file_load
	
	;mov edi, 0xb8000
	;mov byte [es:edi], 'A'
	;mov byte [es:edi+1], 0x0F
	;add edi, 2
	mov esi, kernel_found
	call prints
	mov esi, 0x200000
	
	
	
	jmp $
	
;IN: EBX = cluster to read
;OUT: EBX = next cluster (by FAT table)
cluster_read:
	xor ecx, ecx
	mov cx, word [b_p_s]
	shr cx, 2			;4bytes per FAT entry
	
	xor edx, edx
	mov eax, ebx
	div ecx
	
	add eax, dword [fat_start]
	push ebx
		mov ebx, eax
		mov si, 1
		call ata_pio28_read
	pop ebx
	
	push dword [edi+edx*4]	;save next cluster from FAT table, pop on the end of function
	
	xor eax, eax
	mov al, byte [sec_p_c]
	mov si, ax
	
	sub ebx, 2
	mul ebx
	add eax, dword [root_sec]
	mov ebx, eax
	
	call ata_pio28_read
	
	pop ebx
	ret
sec_p_c: db 0		;Sectors per Cluster
rsvd: dw 0			;Reserved sectors count from the start of volume
sec_per_fat: dd 0 	;sectors per FAT table
n_of_fats: db 0		;# of FAT tables
fat_start: dd 0		;LBA of first FAT table
root_sec: dd 0		;root sectors (calculated from FAT)
b_p_c: dd 0		;bytes per cluster (sec_p_c * b_p_s)
b_p_s: dw 0		;bytes per sector

actual_cluster: dd 0
kernel_not_found: db "Kernel not found!", 0
kernel_found: db "Kernel found!", 0

;EDI = read destination
;EBX = 	starting sector (LBA28)
;SI = # of sectors to read, value 0 means 256 sectors
ata_pio28_read:
	...
Post Reply