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