diff options
author | Galen Sagarin <gps5307@rit.edu> | 2025-04-29 14:23:18 -0400 |
---|---|---|
committer | Galen Sagarin <gps5307@rit.edu> | 2025-04-29 14:23:18 -0400 |
commit | 6c6255fe6f52c95abb54e43c0614185951018b83 (patch) | |
tree | c471f22374455fd248e12fa1054363c87d5e83d5 | |
parent | Merge branch 'main' of https://github.com/kenshineto/kern into fat32 (diff) | |
download | comus-6c6255fe6f52c95abb54e43c0614185951018b83.tar.gz comus-6c6255fe6f52c95abb54e43c0614185951018b83.tar.bz2 comus-6c6255fe6f52c95abb54e43c0614185951018b83.zip |
Some stuff from fat32
-rw-r--r-- | kernel/fs/fat.c | 156 |
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 |