]> git.dujemihanovic.xyz Git - nameless-os.git/blob - boot/x86/fat32.s
Fixes and improvements to FAT32 driver
[nameless-os.git] / boot / x86 / fat32.s
1 ; FAT32 driver
2 ; BOOT_DRIVE, si and bp must be set up by the code using this driver.
3 ; (Specifically, si must be a pointer to the partition's partition
4 ; table entry and bp must be a pointer to the BPB.)
5 ; Before reading any cluster chains, callers must call get_1st_data_sec
6 ; and must be careful not to trash ecx after calling it.
7
8 ; eax - start cluster number
9 ; es:di - where to load the cluster chain
10 ; NOTE: Cluster chain might be the root directory or a file.
11 read_cluster_chain:
12 push eax
13 push ebx
14 push ecx
15 push edx
16 push es
17 push di
18 .loop:
19 ; get the first sector of the cluster to read
20 push eax
21 sub eax, 2
22 xor ebx, ebx
23 mov bl, BPB_SecPerClus
24 mul ebx
25 add eax, ecx
26 mov ebx, eax
27 pop eax
28
29 ; read the cluster
30 push cx
31 movzx cx, BPB_SecPerClus
32 call read_sectors
33 pop cx
34
35 ; increment the load offset (and segment if needed)
36 push eax
37 xor eax, eax
38 movzx ax, BPB_SecPerClus
39 mul word BPB_BytsPerSec
40 add di, ax
41 jno .get_next_cluster
42 mov ax, es
43 add ax, 0x1000
44 mov es, ax
45
46 .get_next_cluster:
47 pop eax
48 ; get FAT sector number and offset containing the next cluster number
49 xor ebx, ebx
50 mov bl, 4 ; put 4 in EBX, doing this instead of "mov ebx, 4" saves us an entire byte
51 mul ebx
52 movzx ebx, word BPB_BytsPerSec
53 div ebx
54 movzx ebx, word BPB_RsvdSecCnt
55 add eax, ebx
56 add eax, [si]
57 mov ebx, edx
58 ; reminder for myself: EAX is FAT sector number, (E)BX is offset into FAT sector
59
60 ; load the FAT sector we're looking for
61
62 push cx
63 push di
64 push ebx ; offset
65 push es ; we want to read at 0:1000, not STAGE3_SEGMENT:1000
66 push eax ; desired LBA
67 xor ax, ax
68 mov es, ax
69 pop ebx ; pop LBA into EBX
70 mov di, 0x1000
71 mov cx, 1
72 call read_sectors
73
74 ; find the cluster we're looking for
75 pop es ; restore STAGE3_SEGMENT
76 pop ebx ; pop FAT offset back into EBX for cmp
77 mov eax, [di+bx]
78 pop di
79 pop cx
80 cmp eax, 0xffffff7
81 jl .loop ; if cluster number is lower than the defective cluster value, we're not done
82 ; TODO: perhaps check is it equal defective and error out in that case?
83 .done:
84 ; cleanup and return
85 pop di
86 pop es
87 pop edx
88 pop ecx
89 pop ebx
90 pop eax
91 ret
92
93 ; es:di - where to load the sector(s)
94 ; ebx - start LBA address
95 ; cx - how many sectors to read
96 read_sectors:
97 pusha
98 mov ah, 0x42
99 push dword 0
100 push dword ebx
101 push es
102 push di
103 push cx
104 push word 0x10
105 mov si, sp
106 mov dl, [BOOT_DRIVE]
107 int 0x13
108 jc .error
109 add sp, 16
110 popa
111 ret
112 .error:
113 mov si, read_error
114 call print
115 hlt
116 jmp $-1
117
118 ; ds:si - pointer to partition table entry
119 ; RETURN: ecx - first data sector
120 get_1st_data_sec:
121 push eax
122 push ebx
123 movzx ax, BPB_NumFats
124 mul dword BPB_FatSz32 ; space occupied by all FATs
125 movzx ebx, word BPB_RsvdSecCnt
126 add eax, ebx ; space occupied by the reserved area
127 add eax, [si] ; space before the partition
128 mov ecx, eax
129 pop ebx
130 pop eax
131 ret
132
133 read_error: db "Read error", 0
134
135 BOOT_DRIVE: db 0