1#include <block/block.h>
2#include <console/printf.h>
3#include <fs/fat.h>
4#include <fs/mbr.h>
5#include <mem/alloc.h>
6#include <stdbool.h>
7#include <stdint.h>
8#include <string.h>
9
10void fat_write_fsinfo(struct fat_fs *fs) { // making fsck happy
11 if (fs->type != FAT_32)
12 return; // no-op
13
14 uint8_t *buf = kmalloc(fs->disk->sector_size);
15 if (!buf)
16 return;
17
18 if (!fs->disk->read_sector(fs->disk, fs->fsinfo_sector, buf, 1))
19 return;
20
21 *(uint32_t *) (buf + 0x1e8) = fs->free_clusters;
22 *(uint32_t *) (buf + 0x1ec) = fs->last_alloc_cluster;
23
24 fs->disk->write_sector(fs->disk, fs->fsinfo_sector, buf, 1);
25 kfree(buf);
26}
27
28uint32_t fat_first_data_sector(const struct fat_fs *fs) {
29 const struct fat_bpb *bpb = fs->bpb;
30
31 uint32_t root_dir_sectors =
32 ((bpb->root_entry_count * sizeof(struct fat_dirent)) +
33 (bpb->bytes_per_sector - 1)) /
34 bpb->bytes_per_sector;
35
36 return bpb->reserved_sector_count + (bpb->num_fats * fs->fat_size) +
37 ((fs->type != FAT_32) ? root_dir_sectors : 0);
38}
39
40uint32_t fat_cluster_to_lba(const struct fat_fs *fs, uint32_t cluster) {
41 const struct fat_bpb *bpb = fs->bpb;
42
43 if (cluster == FAT_DIR_CLUSTER_ROOT) {
44 return fs->volume_base_lba + bpb->reserved_sector_count +
45 (bpb->num_fats * fs->fat_size);
46 }
47
48 return (fat_first_data_sector(fs) +
49 (cluster - 2) * bpb->sectors_per_cluster) +
50 fs->volume_base_lba;
51}
52
53struct fat_bpb *fat_read_bpb(struct block_device *drive,
54 enum fat_fstype *out_type, uint32_t *out_lba,
55 uint32_t base_lba) {
56 uint8_t *sector = kmalloc(drive->sector_size);
57 if (!sector)
58 return NULL;
59
60 uint32_t fat_lba = 0;
61
62 if (base_lba != 0) {
63 fat_lba = base_lba;
64 } else {
65 if (drive->read_sector(drive, 0, sector, 1)) {
66 struct mbr *mbr = (struct mbr *) sector;
67 if (mbr->signature == 0xAA55) {
68 for (int i = 0; i < 4; i++) {
69 uint8_t type = mbr->partitions[i].type;
70 if (type == FAT32_PARTITION_TYPE1 ||
71 type == FAT32_PARTITION_TYPE2 ||
72 type == FAT16_PARTITION_TYPE ||
73 type == FAT12_PARTITION_TYPE) {
74 fat_lba = mbr->partitions[i].lba_start;
75 break;
76 }
77 }
78 }
79 }
80 }
81
82 for (uint32_t lba = fat_lba; lba < fat_lba + 32; ++lba) {
83 if (!drive->read_sector(drive, lba, sector, 1))
84 continue;
85
86 uint8_t jmp = sector[0];
87 if (!((jmp == 0xEB && sector[2] == 0x90) || jmp == 0xE9))
88 continue;
89
90 struct fat_bpb *bpb = (struct fat_bpb *) sector;
91
92 if (bpb->bytes_per_sector != 512 || bpb->num_fats == 0)
93 continue;
94
95 enum fat_fstype type = 0xFF;
96
97 if (bpb->ext_32.boot_signature == 0x29 &&
98 memcmp(bpb->ext_32.fs_type, "FAT32 ", 8) == 0) {
99 type = FAT_32;
100 } else if (bpb->ext_12_16.boot_signature == 0x29 &&
101 memcmp(bpb->ext_12_16.fs_type, "FAT16 ", 8) == 0) {
102 type = FAT_16;
103 } else if (bpb->ext_12_16.boot_signature == 0x29 &&
104 memcmp(bpb->ext_12_16.fs_type, "FAT12 ", 8) == 0) {
105 type = FAT_12;
106 }
107
108 if (type == 0xFF)
109 continue;
110
111 struct fat_bpb *out_bpb = kmalloc(sizeof(struct fat_bpb));
112 if (!out_bpb)
113 return NULL;
114
115 if (out_bpb) {
116 memcpy(out_bpb, bpb, sizeof(struct fat_bpb));
117 *out_type = type;
118 *out_lba = lba;
119 kfree(sector);
120 return out_bpb;
121 }
122
123 break;
124 }
125
126 kfree(sector);
127 return NULL;
128}
129
130struct vfs_node *fat_g_mount(struct partition *p) {
131 if (!p || !p->disk)
132 return NULL;
133
134 struct fat_fs *fs = kmalloc(sizeof(struct fat_fs));
135 if (!fs)
136 return NULL;
137
138 enum fat_fstype type;
139 uint32_t lba;
140 struct block_device *d = p->disk;
141 struct fat_bpb *bpb = fat_read_bpb(drive: d, out_type: &type, out_lba: &lba, base_lba: p->start_lba);
142 if (!bpb) {
143 kfree(fs);
144 return NULL;
145 }
146
147 fs->partition = p;
148 fs->bpb = bpb;
149 fs->type = type;
150 fs->volume_base_lba = lba;
151 fs->disk = d;
152
153 struct fat32_ext_bpb f32_ext = bpb->ext_32;
154 struct fat12_16_ext_bpb f16_ext = bpb->ext_12_16;
155
156 bool f32 = type == FAT_32;
157
158 fs->root_cluster = f32 ? f32_ext.root_cluster : FAT_DIR_CLUSTER_ROOT;
159 fs->fat_size = f32 ? f32_ext.fat_size_32 : bpb->fat_size_16;
160 fs->boot_signature = f32 ? f32_ext.boot_signature : f16_ext.boot_signature;
161 fs->drive_number = f32 ? f32_ext.drive_number : f16_ext.drive_number;
162 fs->volume_id = f32 ? f32_ext.volume_id : f16_ext.volume_id;
163 fs->cluster_size = fs->bpb->sectors_per_cluster * fs->bpb->bytes_per_sector;
164 fs->entries_per_cluster = fs->cluster_size / sizeof(struct fat_dirent);
165
166 uint32_t total_sectors =
167 f32 ? bpb->total_sectors_32 : bpb->total_sectors_16;
168
169 uint32_t data_sectors = total_sectors - fat_first_data_sector(fs);
170 fs->total_clusters = data_sectors / bpb->sectors_per_cluster;
171
172 memcpy(fs->fs_type, f32 ? f32_ext.fs_type : f16_ext.fs_type, 8);
173 memcpy(fs->volume_label, f32 ? f32_ext.volume_label : f16_ext.volume_label,
174 11);
175
176 if (f32) {
177 uint16_t fsinfo_rel_sector = f32_ext.fs_info;
178 uint8_t *buf = kmalloc(fs->disk->sector_size);
179 if (!buf)
180 return NULL;
181
182 if (!d->read_sector(d, fs->volume_base_lba + fsinfo_rel_sector, buf,
183 1)) {
184 kfree(fs);
185 return NULL;
186 }
187
188 // TODO: #define these :boom:
189 uint32_t lead_sig = *(uint32_t *) (buf + 0x00);
190 uint32_t struc_sig = *(uint32_t *) (buf + 0x1fc);
191 if (lead_sig != 0x41615252 || struc_sig != 0xAA550000) {
192 kfree(fs);
193 return NULL;
194 }
195
196 fs->fsinfo_sector = fsinfo_rel_sector;
197 fs->free_clusters = *(uint32_t *) (buf + 0x1e8);
198 fs->last_alloc_cluster = *(uint32_t *) (buf + 0x1ec);
199
200 if (fs->free_clusters == 0xFFFFFFFF)
201 fs->free_clusters = 0; // unknown
202 if (fs->last_alloc_cluster == 0xFFFFFFFF)
203 fs->last_alloc_cluster = 2;
204 } else {
205 fs->fsinfo_sector = 0;
206 fs->free_clusters = 0;
207 fs->last_alloc_cluster = 0;
208 }
209
210 d->fs_data = fs;
211 p->fs_data = fs;
212 return NULL; // TODO: implement vfs here
213}
214
215void fat_g_print(struct partition *d) {
216 if (!d || !d->fs_data)
217 return;
218
219 struct fat_fs *fs = d->fs_data;
220
221 switch (fs->type) {
222 case FAT_12:
223 case FAT_16: fat12_16_print_bpb(bpb: fs->bpb); break;
224 case FAT_32: fat32_print_bpb(bpb: fs->bpb); break;
225 }
226
227 struct fat_dirent new_file_ent;
228
229 bool success;
230
231 fat_list_root(fs);
232
233 success = fat_create(fs, dir_cluster: fs->root_cluster, filename: "Whimsy", out_dirent: &new_file_ent,
234 attr: FAT_ARCHIVE, NULL);
235
236 success = fat_delete(fs, dir_cluster: fs->root_cluster, filename: "Whimsy");
237
238 success = fat_create(fs, dir_cluster: fs->root_cluster, filename: "Booh", out_dirent: &new_file_ent,
239 attr: FAT_ARCHIVE, NULL);
240
241 success = fat_create(fs, dir_cluster: fs->root_cluster, filename: "Cooh", out_dirent: &new_file_ent,
242 attr: FAT_ARCHIVE, NULL);
243
244 success = fat_create(fs, dir_cluster: fs->root_cluster, filename: "Dooh", out_dirent: &new_file_ent,
245 attr: FAT_ARCHIVE, NULL);
246
247 fat_list_root(fs);
248 uint32_t ind;
249
250 struct fat_dirent *f = fat_lookup(fs, cluster: fs->root_cluster, f: "Dooh", out_index: &ind);
251
252 new_file_ent = f ? *f : new_file_ent;
253
254 success = fat_write_file(fs, ent: &new_file_ent, offset: 0, data: (uint8_t *) "Doober\n", size: 8);
255
256 success = fat_write_dirent(fs, dir_cluster: fs->root_cluster, dirent_to_write: &new_file_ent, entry_index: ind);
257
258 if (success) {
259 printf(format: "yay\n");
260 } else {
261 printf(format: "that not right...\n");
262 }
263 fat_list_root(fs);
264}
265