summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGalen Sagarin <gps5307@rit.edu>2025-04-29 14:23:18 -0400
committerGalen Sagarin <gps5307@rit.edu>2025-04-29 14:23:18 -0400
commit6c6255fe6f52c95abb54e43c0614185951018b83 (patch)
treec471f22374455fd248e12fa1054363c87d5e83d5
parentMerge branch 'main' of https://github.com/kenshineto/kern into fat32 (diff)
downloadcomus-6c6255fe6f52c95abb54e43c0614185951018b83.tar.gz
comus-6c6255fe6f52c95abb54e43c0614185951018b83.tar.bz2
comus-6c6255fe6f52c95abb54e43c0614185951018b83.zip
Some stuff from fat32
-rw-r--r--kernel/fs/fat.c156
1 files changed, 154 insertions, 2 deletions
diff --git a/kernel/fs/fat.c b/kernel/fs/fat.c
index 9168301..c177e21 100644
--- a/kernel/fs/fat.c
+++ b/kernel/fs/fat.c
@@ -2,7 +2,10 @@
#include <stdbool.h>
#include <string.h>
+#include <comus/fs.h>
+// Attribution: Large amounts of code here were are taken (either as is or modified)
+// from strawberryhacker at strawberryhacker/flat32/blob/master
// various errors with fat32
enum
{
@@ -51,6 +54,39 @@ enum
FAT_SEEK_END,
};
+#define LIMIT(a, b) ((a) < (b) ? (a) : (b))
+
+#define FSINFO_HEAD_SIG 0x41615252
+#define FSINFO_STRUCT_SIG 0x61417272
+#define FSINFO_TAIL_SIG 0xaa550000
+
+#define MBR_PART_OFF 446
+
+#define EXT_FLAG_MIRROR (1 << 7)
+#define EXT_FLAG_ACT 0x000f
+#define EXT_FLAG_SECOND 0x0001
+
+#define LFN_HEAD_MSK 0x40
+#define LFN_SEQ_MSK 0x1f
+
+#define SFN_FREE 0xe5
+#define SFN_LAST 0x00
+#define SFN_PAD 0x20
+
+//------------------------------------------------------------------------------
+enum
+{
+ FAT_BUF_DIRTY = 0x01,
+ FAT_INFO_DIRTY = 0x02,
+};
+
+enum
+{
+ CLUST_FREE = 0x01,
+ CLUST_USED = 0x02,
+ CLUST_LAST = 0x04,
+ CLUST_BAD = 0x08,
+};
typedef struct
{
@@ -210,10 +246,22 @@ typedef struct
static Fat* g_fat_list;
+static uint8_t g_lfn_indices[13] = {1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30};
static uint8_t g_buf[512];
static uint16_t g_len;
static uint8_t g_crc;
+static Fat* find_fat_volume(const char* name, int len)
+{
+ for(Fat* it = g_fat_list; it; it = it->next)
+ {
+ if(len == it->name_len && !memcmp(name, it->name, len)) {
+ return it;
+ }
+ }
+ return NULL;
+}
+
static int sync_buf(Fat* fat) {
// checks whether the flag is active. If not, we
if(fat->flags & 0x01) {
@@ -236,12 +284,116 @@ static int sync_fs(Fat* fat)
if (error) {
return error;
}
- FsInfo* info = (FsInfo*)fat->buf;
- fat->flags |=
+ if(fat->flags & 0x02) {
+ error = update_buf(fat, fat->info_sect);
+ if(error) {
+ return error;
+ }
+ FsInfo* info = (FsInfo*)fat->buf;
+ fat->flags |= 0x01;
+ info->next_free = fat->last_used;
+ info->free_cnt = fat->free_cnt;
+ error = sync_buf(fat);
+ if(error) {
+ return error;
+ }
+ fat->flags &= ~0x01;
+ }
+ return FAT_ERR_NONE;
}
static int get_fat(Fat* fat, uint32_t clust, uint32_t* out_val, uint8_t* out_flags) {
}
+/// @brief
+/// @param ops (the operation that is being done)
+/// @param partition use 0 for the entire disk
+/// @param fat um
+/// @param name no clue lol
+/// @return
+int fat_mount(DiskOps* ops, int partition, Fat* fat, const char* name) {
+ uint32_t lba;
+ int err = probe(ops, partition, &lba);
+ if(err) {
+ return err;
+ }
+ Bpb* bpb = (Bpb*)g_buf;
+ bool mirror = (bpb->ext_flags & EXT_FLAG_MIRROR) != 0;
+ bool use_first = (bpb->ext_flags & EXT_FLAG_SECOND) == 0;
+
+ uint32_t fat_0 = lba + bpb->res_sect_cnt;
+ uint32_t fat_1 = lba + bpb->res_sect_cnt + bpb->sect_per_fat_32;
+ fat->clust_shift = __builtin_ctz(bpb->sect_per_clust);
+ fat->clust_msk = bpb->sect_per_clust - 1;
+ fat->clust_cnt = bpb->sect_per_fat_32 * 128;
+ fat->root_clust = bpb->root_cluster;
+ fat->fat_sect[0] = use_first ? fat_0 : fat_1;
+ fat->fat_sect[1] = mirror ? (use_first ? fat_1 : fat_0) : 0;
+ fat->info_sect = lba + bpb->info_sect;
+ fat->data_sect = lba + bpb->res_sect_cnt + bpb->fat_cnt * bpb->sect_per_fat_32;
+ if(!ops->read(g_buf, fat->info_sect)) {
+ return FAT_ERR_IO;
+ }
+ FsInfo* info = (FsInfo*)g_buf;
+ if (info->tail_sig != FSINFO_TAIL_SIG ||
+ info->head_sig != FSINFO_HEAD_SIG ||
+ info->struct_sig != FSINFO_STRUCT_SIG ||
+ info->next_free == 0xffffffff ||
+ info->free_cnt == 0xffffffff) {
+ return FAT_ERR_NOFAT;
+ }
+
+ fat->last_used = info->next_free;
+ fat->free_cnt = info->free_cnt;
+
+ int name_len = strlen(name);
+ if (name_len > sizeof(fat->name)) {
+ return FAT_ERR_PARAM;
+ }
+ memcpy(fat->name, name, name_len);
+ fat->name_len = name_len;
+
+ fat->ops = *ops;
+ fat->sect = 0; // Causes buffering on first call
+
+ fat->next = g_fat_list;
+ g_fat_list = fat;
+
+ return FAT_ERR_NONE;
+}
+
+int fat_unmount(Fat* fat) {
+ Fat** it = &g_fat_list;
+ while(*it && *it != fat) {
+ it = &(*it)->next;
+ }
+ if(*it == NULL) {
+ return FAT_ERR_PARAM;
+ }
+ *it = fat->next;
+ return sync_fs(fat);
+}
+
+int fat_sync(Fat* fat)
+{
+ return sync_fs(fat);
+}
+
+int fat_file_open(File* file, const char* path, uint8_t flags) {
+ Dir dir;
+ dir.fat = 0;
+
+ int err = follow_path(&dir, &path, NULL);
+ // if there is an error that isn't EOF
+ if(err && err != FAT_ERR_EOF) {
+ return err;
+ }
+ // if the error is EOF, which in this case checks if the file doesn't exist
+ if(err == FAT_ERR_EOF) {
+ if(0 == (flags & FAT_CREATE)) {
+ return FAT_ERR_DENIED;
+ }
+ }
+} \ No newline at end of file