Skip to content

Commit 2adb6bc

Browse files
Optimized and cleaned up FAT16 source.
1 parent 13b2bc5 commit 2adb6bc

2 files changed

Lines changed: 51 additions & 38 deletions

File tree

source/includes/filesystems/fat16.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @file fat16.h
33
* @author Pradosh (pradoshgame@gmail.com)
4-
* @brief The header file for reading in FAT16 file system
4+
* @brief The header file for reading using FAT16 file system.
55
* @version 0.1
66
* @date 2025-12-28
77
*
@@ -15,6 +15,10 @@
1515
#include <basics.h>
1616
#include <graphics.h>
1717

18+
#define FAT16_EOC 0xFFF8
19+
#define DIR_ENTRIES_PER_SECTOR 16
20+
#define BYTES_PER_DIR_ENTRY 32
21+
1822
typedef struct {
1923
uint8_t jmp[3];
2024
uint8_t oem[8];

source/kernel/C/filesystems/fat16.c

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,28 @@ int fat16_mount(int portno, uint32_t partition_lba, fat16_fs_t* fs) {
5858
}
5959

6060
uint16_t fat16_read_fat_fs(fat16_fs_t* fs, uint16_t cluster) {
61-
uint32_t fat_offset = cluster * 2;
62-
uint32_t fat_sector = fs->fat_start + (fat_offset / fs->bs.bytes_per_sector);
63-
uint32_t ent_offset = fat_offset % fs->bs.bytes_per_sector;
64-
6561
uint8_t buf[512];
66-
ahci_read_sector(fs->portno, fat_sector, buf, 1);
62+
uint32_t offset = cluster * 2;
63+
uint32_t sector = fs->fat_start + offset / fs->bs.bytes_per_sector;
64+
65+
ahci_read_sector(fs->portno, sector, buf, 1);
66+
return *(uint16_t*)(buf + (offset % fs->bs.bytes_per_sector));
67+
}
6768

68-
return *(uint16_t*)&buf[ent_offset];
69+
// HELPERS ============
70+
static inline uint32_t fat16_cluster_lba(fat16_fs_t* fs, uint16_t cluster) {
71+
return fs->data_start + (cluster - 2) * fs->bs.sectors_per_cluster;
6972
}
7073

74+
static inline int fat16_dir_valid(fat16_dir_entry_t* e) {
75+
if (e->name[0] == 0x00) return 0; // end
76+
if (e->name[0] == 0xE5) return -1; // deleted
77+
if (e->attr == 0x0F) return -1; // LFN
78+
if (e->attr & 0x08) return -1; // volume label
79+
return 1;
80+
}
81+
// END =========
82+
7183
void fat16_list_root(fat16_fs_t* fs) {
7284
uint8_t buf[512];
7385

@@ -159,24 +171,18 @@ int fat16_find_in_dir(
159171
) {
160172
uint8_t buf[512];
161173
char fatname[11];
162-
163174
fat16_format_name(name, fatname);
164175

165-
// ---------------- ROOT DIRECTORY ----------------
176+
// ---------- ROOT DIRECTORY ----------
166177
if (current_cluster == 0) {
167178
for (uint32_t i = 0; i < fs->root_dir_sectors; i++) {
168179
ahci_read_sector(fs->portno, fs->root_dir_start + i, buf, 1);
169180
fat16_dir_entry_t* e = (fat16_dir_entry_t*)buf;
170181

171-
for (int j = 0; j < 16; j++) {
172-
if (e[j].name[0] == 0x00)
173-
return -1; // end of directory
174-
if (e[j].name[0] == 0xE5)
175-
continue; // deleted
176-
if (e[j].attr & 0x08)
177-
continue; // volume label
178-
if (e[j].attr == 0x0F)
179-
continue; // LFN
182+
for (int j = 0; j < DIR_ENTRIES_PER_SECTOR; j++) {
183+
int v = fat16_dir_valid(&e[j]);
184+
if (v == 0) return -1;
185+
if (v < 0) continue;
180186

181187
if (memcmp(e[j].name, fatname, 11) == 0) {
182188
*out = e[j];
@@ -187,27 +193,20 @@ int fat16_find_in_dir(
187193
return -1;
188194
}
189195

190-
// ---------------- SUBDIRECTORY ----------------
196+
// ---------- SUBDIRECTORY ----------
191197
uint16_t cluster = current_cluster;
192198

193-
while (cluster < 0xFFF8) {
194-
uint32_t lba =
195-
fs->data_start +
196-
(cluster - 2) * fs->bs.sectors_per_cluster;
199+
while (cluster < FAT16_EOC) {
200+
uint32_t lba = fat16_cluster_lba(fs, cluster);
197201

198202
for (uint32_t s = 0; s < fs->bs.sectors_per_cluster; s++) {
199203
ahci_read_sector(fs->portno, lba + s, buf, 1);
200204
fat16_dir_entry_t* e = (fat16_dir_entry_t*)buf;
201205

202-
for (int j = 0; j < 16; j++) {
203-
if (e[j].name[0] == 0x00)
204-
return -1;
205-
if (e[j].name[0] == 0xE5)
206-
continue;
207-
if (e[j].attr & 0x08)
208-
continue;
209-
if (e[j].attr == 0x0F)
210-
continue;
206+
for (int j = 0; j < DIR_ENTRIES_PER_SECTOR; j++) {
207+
int v = fat16_dir_valid(&e[j]);
208+
if (v == 0) return -1;
209+
if (v < 0) continue;
211210

212211
if (memcmp(e[j].name, fatname, 11) == 0) {
213212
*out = e[j];
@@ -345,28 +344,38 @@ int fat16_read(fat16_file_t* f, uint8_t* out, uint32_t size) {
345344
uint8_t sector[512];
346345

347346
while (read < size && f->pos < f->entry.filesize) {
348-
uint32_t cluster_offset =
349-
f->pos / (f->fs->bs.sectors_per_cluster * 512);
347+
uint32_t cluster_size =
348+
f->fs->bs.sectors_per_cluster * 512;
350349

351-
uint16_t cluster = f->entry.first_cluster;
352-
for (uint32_t i = 0; i < cluster_offset; i++)
350+
uint32_t cluster_index = f->pos / cluster_size;
351+
uint32_t sector_in_cluster =
352+
(f->pos / 512) % f->fs->bs.sectors_per_cluster;
353+
354+
uint16_t cluster = f->cluster;
355+
356+
// Advance cluster only when needed
357+
while (cluster_index--) {
353358
cluster = fat16_read_fat_fs(f->fs, cluster);
359+
}
354360

355361
uint32_t lba =
356-
f->fs->data_start +
357-
(cluster - 2) * f->fs->bs.sectors_per_cluster;
362+
fat16_cluster_lba(f->fs, cluster) + sector_in_cluster;
358363

359364
ahci_read_sector(f->fs->portno, lba, sector, 1);
360365

361366
uint32_t off = f->pos % 512;
362367
uint32_t to_copy = 512 - off;
368+
363369
if (to_copy > size - read)
364370
to_copy = size - read;
371+
if (to_copy > f->entry.filesize - f->pos)
372+
to_copy = f->entry.filesize - f->pos;
365373

366374
memcpy(out + read, sector + off, to_copy);
367375

368376
f->pos += to_copy;
369377
read += to_copy;
378+
f->cluster = cluster;
370379
}
371380

372381
return read;

0 commit comments

Comments
 (0)