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