summaryrefslogtreecommitdiff
path: root/src/kernel/fat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/fat.c')
-rw-r--r--src/kernel/fat.c70
1 files changed, 42 insertions, 28 deletions
diff --git a/src/kernel/fat.c b/src/kernel/fat.c
index 087d79e..807af00 100644
--- a/src/kernel/fat.c
+++ b/src/kernel/fat.c
@@ -1,9 +1,9 @@
-#include "fat.h"
-#include "ata.h"
-#include "panic.h"
#include "drive.h"
-#include "mem.h"
+#include "panic.h"
#include "util.h"
+#include "ata.h"
+#include "fat.h"
+#include "mem.h"
#define MAX_FAT_DRIVES 16
#define MAX_OPEN_FILES_PER_DRIVE 32
@@ -57,20 +57,19 @@ struct fat_info {
uint8_t fs_type[8];
} __attribute__ ((packed));
-#define CTOS(c, fi) ((fi)->reserved_sectors + (fi)->sectors_per_fat * (fi)->fats + ((fi)->root_entries >> 4) + (c) - 2)
+#define CTOS(c, fdi) ((fdi)->data_start + (c) - 2)
struct fat_drive_info {
- struct fat_info *fi;
+ const struct fat_info *fi;
uint16_t *fat;
+ uint16_t root_start;
+ uint16_t data_start;
struct directory_entry open_files[MAX_OPEN_FILES_PER_DRIVE];
};
struct fat_drive_info infos[MAX_FAT_DRIVES];
uint8_t next_id = 0;
-#define FI(n) ((struct fat_info *)(infos[n].fi + 3))
-#define FN(n, f) (infos[n].open_files[f - 1])
-
uint8_t fat_driver_buffer[512];
struct fat_info *next_fi;
@@ -80,8 +79,9 @@ void alloc_next_fi() {
panic("Out of memory in FAT driver.");
}
-struct drive *cur_drive;
+const struct drive *cur_drive;
fs_id_t cur_id;
+const struct fat_drive_info *cur_fdi;
struct directory_entry *cur_dir;
//loads cluster `c`
@@ -91,7 +91,7 @@ void load_cluster(uint16_t c, void *to) {
return;
}
- uint32_t s = CTOS(c, FI(cur_id));
+ uint32_t s = CTOS(c, cur_fdi);
cur_drive->read_sectors(cur_drive, s, 1, to);
}
@@ -99,7 +99,7 @@ uint16_t next_cluster(uint16_t c) {
panic("TODO: compute next sector (or 0 for none)");
}
-static inline bool check_fat_names(uint8_t *a, uint8_t *b) {
+static inline bool check_fat_names(const uint8_t *a, const uint8_t *b) {
return (((uint32_t *)a)[0] == ((uint32_t *)b)[0]) &&
(((uint32_t *)a)[1] == ((uint32_t *)b)[1]) &&
(((uint16_t *)a)[8] == ((uint16_t *)b)[8]) &&
@@ -107,8 +107,8 @@ static inline bool check_fat_names(uint8_t *a, uint8_t *b) {
}
//after: cur_dir -> specified entry in root
-bool try_locate_root_entry(uint8_t *fat_name) {
- uint32_t cur_dir_sect = FI(cur_id)->reserved_sectors + FI(cur_id)->sectors_per_fat * FI(cur_id)->fats - 1;
+bool try_locate_root_entry(const uint8_t *fat_name) {
+ uint32_t cur_dir_sect = cur_fdi->root_start - 1;
cur_dir = (struct directory_entry *)(fat_driver_buffer + 512);
while (true) {
if (cur_dir == (struct directory_entry *)(fat_driver_buffer + 512)) {
@@ -127,7 +127,7 @@ bool try_locate_root_entry(uint8_t *fat_name) {
//before: cur_dir -> entry of dir to search
//after: cur_dir -> specified entry in dir
-bool try_locate_entry(uint8_t *fat_name) {
+bool try_locate_entry(const uint8_t *fat_name) {
uint16_t cur_dir_cluster = cur_dir->first_cluster;
load_cluster(cur_dir_cluster, fat_driver_buffer);
cur_dir = (struct directory_entry *)fat_driver_buffer;
@@ -146,32 +146,41 @@ bool try_locate_entry(uint8_t *fat_name) {
}
}
-drive_file_id_t fat_get_file(struct drive *d, char *path) {
+drive_file_id_t fat_get_file(const struct drive *d, const char *path) {
cur_drive = d;
cur_id = d->drive_id;
+ cur_fdi = &infos[cur_id];
+ const struct directory_entry *open_files = cur_fdi->open_files - 1;
for (drive_file_id_t n = 1; n != MAX_OPEN_FILES_PER_DRIVE + 1; ++n)
- if (!*(uint8_t *)(&FN(d->drive_id, n))) {
- panic("TODO: open path at FN(id, n)");
+ if (!*(uint8_t *)(&open_files[n])) {
+ panic("TODO: open path into open_files[n]");
return n;
}
panic("Maximum number of files open reached for FAT drive.");
}
-void fat_free_file(struct drive *d, drive_file_id_t fid) {
- *(uint8_t *)(&FN(d->drive_id, fid)) = 0;
+void fat_free_file(const struct drive *d, drive_file_id_t fid) {
+ *(uint8_t *)(&infos[d->drive_id].open_files[fid - 1]) = 0;
}
-void fat_load_sector(struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) {
+void fat_load_sector(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) {
cur_drive = d;
cur_id = d->drive_id;
- uint16_t c = FN(d->drive_id, fid).first_cluster;
+ cur_fdi = &infos[cur_id];
+ uint16_t c = cur_fdi->open_files[fid - 1].first_cluster;
for (uint32_t i = 0; i < sector; ++i)
c = next_cluster(c);
load_cluster(c, at);
}
-uint32_t fat_get_free_sectors(struct drive *d) {
- panic("TODO: get free sectors of drive");
+__attribute__ ((pure)) uint32_t fat_get_free_sectors(const struct drive *d) {
+ uint16_t *start = infos[d->fs_id].fat + 2;
+ uint16_t *end = start + d->n_sectors - infos[d->fs_id].data_start;
+ uint32_t count = 0;
+ for (uint16_t *i = start; i < end; ++i)
+ if (!*i)
+ ++count;
+ return count;
}
void init_fat() {
@@ -186,8 +195,8 @@ bool try_fat_init_drive(struct drive *d) {
return false;
memcpy(next_fi, fat_driver_buffer + 3, sizeof(struct fat_info));
uint32_t *fs_type_32 = (uint32_t *)next_fi->fs_type;
- if ((fs_type_32[0] != ('F' + 'A' * 256 + 'T' + 65536 + '1' * 16777216)) ||
- (fs_type_32[1] != ('6' + ' ' * 256 + ' ' + 65536 + ' ' * 16777216)))
+ if ((fs_type_32[0] != ('F' + 'A' * 256 + 'T' * 65536 + '1' * 16777216)) ||
+ (fs_type_32[1] != ('6' + ' ' * 256 + ' ' * 65536 + ' ' * 16777216)))
return false;
d->fs_type = "FAT16";
@@ -199,10 +208,15 @@ bool try_fat_init_drive(struct drive *d) {
d->fs_id = next_id;
infos[next_id].fi = next_fi;
infos[next_id].fat = allocate_pages(((next_fi->sectors_per_fat - 1) >> 3) + 1);
- for (drive_file_id_t i = 0; i < MAX_OPEN_FILES_PER_DRIVE; ++i)
- *(uint8_t *)&FN(next_id, i) = 0;
+ infos[next_id].root_start = next_fi->reserved_sectors +
+ next_fi->sectors_per_fat * next_fi->fats;
+ infos[next_id].data_start = infos[next_id].root_start +
+ ((next_fi->root_entries - 1) >> 4) + 1;
d->read_sectors(d, next_fi->reserved_sectors, next_fi->sectors_per_fat, infos[next_id].fat);
+ struct directory_entry *open_files = infos[next_id].open_files - 1;
+ for (drive_file_id_t i = 0; i < MAX_OPEN_FILES_PER_DRIVE; ++i)
+ *(uint8_t *)&open_files[i] = 0;
alloc_next_fi();
++next_id;