From 1e6e6253b9f7237528c4780c25de51480a6b0899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiesner=20Andr=C3=A1s?= Date: Tue, 3 Oct 2023 07:04:31 +0200 Subject: [PATCH] reading from a root-directory file basically works --- fs/fat32/fat32.c | 143 +++++++++++++++++++++++++++++++++++++---------- fs/fat32/fat32.h | 5 +- 2 files changed, 116 insertions(+), 32 deletions(-) diff --git a/fs/fat32/fat32.c b/fs/fat32/fat32.c index bb9756d..ff9f347 100644 --- a/fs/fat32/fat32.c +++ b/fs/fat32/fat32.c @@ -7,7 +7,7 @@ #include "fat32.h" #include "../../MassStorage.h" -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define SECTOR_SIZE (512) static uint8_t buffer[2 * SECTOR_SIZE]; // TODO access to this variable should be protected! @@ -16,18 +16,18 @@ static inline void fat32_copy_second_to_first_buffer() { memcpy(buffer, buffer + SECTOR_SIZE, SECTOR_SIZE); } -static inline uint32_t fat32_get_first_sector_of_cluster(const Fat32_CtrlBlock * ctrl, uint32_t cluster) { +static inline uint32_t fat32_get_first_sector_of_cluster(const Fat32_CtrlBlock *ctrl, uint32_t cluster) { return (cluster - 2) * ctrl->sectors_per_cluster + ctrl->data_s; } -int fat32_load(Fat32_CtrlBlock *ctrl, uint32_t bpb_s, const MassStorage * mstg) { +int fat32_load(Fat32_CtrlBlock *ctrl, uint32_t bpb_s, const MassStorage *mstg) { ctrl->mstg = mstg; ctrl->bpb_s = bpb_s; // load Boot Parameter Block mstg->read_sector(mstg, bpb_s, buffer); - const Bpb_Fat32 * bpb_obj = (Bpb_Fat32 *)buffer; + const Bpb_Fat32 *bpb_obj = (Bpb_Fat32 *) buffer; ctrl->bytes_per_sector = bpb_obj->bytes_per_sector; ctrl->sectors_per_cluster = bpb_obj->sectors_per_cluster; @@ -35,6 +35,7 @@ int fat32_load(Fat32_CtrlBlock *ctrl, uint32_t bpb_s, const MassStorage * mstg) memcpy(ctrl->volume_label, bpb_obj->volume_label, 11); ctrl->serial_number = bpb_obj->volume_serial_number; ctrl->fat_copies = bpb_obj->n_fats; + ctrl->fat_entries_per_sector = ctrl->bytes_per_sector / sizeof(Fat32_FatTableEntry); ctrl->fat_s = ctrl->bpb_s + bpb_obj->n_reserved_sectors; // FATs are stored on the hidden area right after the reserved sectors ctrl->data_s = ctrl->fat_s + ctrl->fat_copies * ctrl->sectors_per_fat; // data region begins right after the FAT copies @@ -52,7 +53,7 @@ static inline uint8_t fat32_unicode_to_utf8(uint16_t unicode) { return unicode & 0x00FF; } -uint32_t fat32_trim_str_right(char * str) { +uint32_t fat32_trim_str_right(char *str) { uint32_t len = 0; while (*str > ' ') { str++; @@ -63,16 +64,16 @@ uint32_t fat32_trim_str_right(char * str) { } // TODO loop unroll! -uint16_t fat32_extract_lfn_text(const Fat32_LongFileNameEntry * lfnEntry, char * str) { +uint16_t fat32_extract_lfn_text(const Fat32_LongFileNameEntry *lfnEntry, char *str) { uint16_t idx = 0; for (uint8_t i = 0; i < 5; i++) { // first block - str[idx++] = (char) fat32_unicode_to_utf8(((uint8_t *)lfnEntry->ustr04)[2 * i]); + str[idx++] = (char) fat32_unicode_to_utf8(((uint8_t *) lfnEntry->ustr04)[2 * i]); } for (uint8_t i = 0; i < 6; i++) { // second block - str[idx++] = (char) fat32_unicode_to_utf8(((uint8_t *)lfnEntry->ustr5A)[2 * i]); + str[idx++] = (char) fat32_unicode_to_utf8(((uint8_t *) lfnEntry->ustr5A)[2 * i]); } for (uint8_t i = 0; i < 2; i++) { // third block - str[idx++] = (char) fat32_unicode_to_utf8(((uint8_t *)lfnEntry->ustrBC)[2 * i]); + str[idx++] = (char) fat32_unicode_to_utf8(((uint8_t *) lfnEntry->ustrBC)[2 * i]); } return idx; } @@ -80,7 +81,7 @@ uint16_t fat32_extract_lfn_text(const Fat32_LongFileNameEntry * lfnEntry, char * #define LONG_FILE_NAME_ATTRIB_TEST(a) ((a) & (1 << 3)) && ((a) & (1 << 2)) && ((a) & (1 << 1)) && ((a) & (1)) #define LINELENGTH (32) -uint16_t fat32_get_file_entry(Fat32_FileEntry ** const entry, char * entry_name) { +uint16_t fat32_get_file_entry(Fat32_FileEntry **const entry, char *entry_name) { //static char entry_name[261]; bool done = false; bool reading_lfn = false; @@ -99,13 +100,13 @@ uint16_t fat32_get_file_entry(Fat32_FileEntry ** const entry, char * entry_name) } } - Fat32_FileEntry * const finalEntry = *(entry); // final, non-LFN entry + Fat32_FileEntry *const finalEntry = *(entry); // final, non-LFN entry attribs = finalEntry->attributes; uint16_t name_len = 0; // print the name of the entry if (reading_lfn) { // if the entry has a long name - const Fat32_LongFileNameEntry * lfnEntry = (const Fat32_LongFileNameEntry *)(finalEntry - 1); // by order first (by address last) LFN entry + const Fat32_LongFileNameEntry *lfnEntry = (const Fat32_LongFileNameEntry *) (finalEntry - 1); // by order first (by address last) LFN entry // fetch long name for (uint8_t i = 0; i < rewind; i++) { @@ -131,13 +132,13 @@ uint16_t fat32_get_file_entry(Fat32_FileEntry ** const entry, char * entry_name) return name_len; } -int fat32_print_file_entry(Fat32_FileEntry ** const entry) { +int fat32_print_file_entry(Fat32_FileEntry **const entry) { static char entry_name[261]; uint16_t name_len = fat32_get_file_entry(entry, entry_name); uint8_t attribs = (*entry)->attributes; // print entry type - char entry_type[5] = { 'F', ' ', ' ', ' ', '\0' }; // file, by default + char entry_type[5] = {'F', ' ', ' ', ' ', '\0'}; // file, by default if (attribs & FAT32_FATT_DIRECTORY) { entry_type[0] = 'D'; } else if (attribs & FAT32_FATT_VOLUME) { @@ -151,7 +152,7 @@ int fat32_print_file_entry(Fat32_FileEntry ** const entry) { } uint16_t padding = 1; - if (name_len < LINELENGTH){ + if (name_len < LINELENGTH) { padding = LINELENGTH - name_len; } @@ -164,13 +165,13 @@ int fat32_print_file_entry(Fat32_FileEntry ** const entry) { #define FAT32_DIRECTORY_SEPARATOR ('/') #define FAT32_MAX_BASENAME_LENGTH (47) -static inline uint16_t fat32_extract_next_basename_length(const char * path) { +static inline uint16_t fat32_extract_next_basename_length(const char *path) { uint16_t i; - for (i = 0; path[i] != FAT32_DIRECTORY_SEPARATOR && path[i] != '\0'; i++) {} + for (i = 0; (path[i] != FAT32_DIRECTORY_SEPARATOR) && (path[i] != '\0'); i++) {} return i; } -int fat32_locate_file(const Fat32_CtrlBlock *ctrl, const char *path) { +const Fat32_FileEntry *fat32_locate_file(const Fat32_CtrlBlock *ctrl, const char *path) { FETCH_MSTG; // start search in the root directory @@ -180,9 +181,11 @@ int fat32_locate_file(const Fat32_CtrlBlock *ctrl, const char *path) { bool file_found = false; // file is not found in the beginning bool no_such_file = false; // assume that there is such a file - const char * path_iter = path; // path is being fetched from its beginning + const char *path_iter = path; // path is being fetched from its beginning char basename[FAT32_MAX_BASENAME_LENGTH + 1]; // basename basename[FAT32_MAX_BASENAME_LENGTH] = '\0'; // NULL-termination + char entry_name[FAT32_MAX_BASENAME_LENGTH + 1]; // entry name + Fat32_FileEntry *entry = NULL; // entry iterator while ((!file_found) && (!no_such_file)) { // extract first basename @@ -190,10 +193,63 @@ int fat32_locate_file(const Fat32_CtrlBlock *ctrl, const char *path) { uint16_t copy_len = MIN(basename_len, FAT32_MAX_BASENAME_LENGTH); memcpy(basename, path_iter, copy_len); // extract basename basename[copy_len] = '\0'; // NULL-termination - path_iter += basename_len + 1; // advance basename + path_iter += basename_len; // advance basename + + // search for basename in the current directory + // acquire pointer to the beginning of the file entry table + entry = (Fat32_FileEntry *) buffer; + bool basename_entry_found = false; + while ((entry->short_fname[0] != 0x00) && (!basename_entry_found)) { + if (entry->short_fname[0] != FAT32_UNUSED_FILE_ENTRY) { + fat32_get_file_entry(&entry, entry_name); + + // compare entry name + if (!strncmp(entry_name, basename, basename_len)) { // if matches... + basename_entry_found = true; // ...then the entry is found + continue; + } + } + + entry++; + + // if we crossed the first buffer - second buffer border, then + // copy the second buffer to the first one and load the next sector + // to the second buffer + if ((void *) entry > (void *) (buffer + SECTOR_SIZE)) { + // copy the second buffer to the first one + fat32_copy_second_to_first_buffer(); + sector++; + READ_MSTG_TO_SECOND_BUFFER(sector + 1); + + // modify the entry pointer, since it's been moved + entry = (Fat32_FileEntry *) (((uint8_t *) (entry)) - SECTOR_SIZE); + } + } + + // if the basename entry is found... + if (basename_entry_found) { + if (path_iter[0] == '\0') { // ...and it's the end of the path + file_found = true; // ...then the file is found + } else { // ...if it's not the end of the path, then load the cluster corresponding to the entry + // determine sector number + uint32_t next_cluster = (entry->first_cluster_high << 16) | (entry->first_cluster_low); + uint32_t next_sector = fat32_get_first_sector_of_cluster(ctrl, next_cluster); + + // load sectors + READ_MSTG_TO_FIRST_BUFFER(next_sector); + READ_MSTG_TO_SECOND_BUFFER(next_sector + 1); + } + } else { // if not found... + no_such_file = true; // ...then the file could not be located + } } - return 0; + // return with appropriate value + if (!no_such_file) { + return entry; + } else { + return NULL; + } } int fat32_list_dir(const Fat32_CtrlBlock *ctrl, const char *dir) { @@ -206,7 +262,7 @@ int fat32_list_dir(const Fat32_CtrlBlock *ctrl, const char *dir) { READ_MSTG_TO_SECOND_BUFFER(sector + 1); // acquire pointer to the beginning of the file entry table - Fat32_FileEntry * entry = (Fat32_FileEntry *)buffer; + Fat32_FileEntry *entry = (Fat32_FileEntry *) buffer; while (entry->short_fname[0] != 0x00) { if (entry->short_fname[0] != FAT32_UNUSED_FILE_ENTRY) { fat32_print_file_entry(&entry); @@ -216,26 +272,53 @@ int fat32_list_dir(const Fat32_CtrlBlock *ctrl, const char *dir) { // if we crossed the first buffer - second buffer border, then // copy the second buffer to the first one and load the next sector // to the second buffer - if ((void *)entry > (void *)(buffer + SECTOR_SIZE)) { + if ((void *) entry > (void *) (buffer + SECTOR_SIZE)) { // copy the second buffer to the first one fat32_copy_second_to_first_buffer(); sector++; READ_MSTG_TO_SECOND_BUFFER(sector + 1); // modify the entry pointer, since it's been moved - entry = (Fat32_FileEntry *)(((uint8_t *)(entry)) - SECTOR_SIZE); + entry = (Fat32_FileEntry *) (((uint8_t *) (entry)) - SECTOR_SIZE); } } return 0; } -static inline uint32_t fat32_get_fat_entry_sector_by_cluster_index(const Fat32_CtrlBlock * ctrl, uint32_t cluster) { +static inline uint32_t fat32_get_fat_entry_sector_by_cluster_index(const Fat32_CtrlBlock *ctrl, uint32_t cluster) { return cluster * sizeof(Fat32_FatTableEntry) / ctrl->bytes_per_sector + ctrl->fat_s; } -//int fat32_read_file(const Fat32_CtrlBlock * ctrl, uint32_t pos, uint32_t len) { -// FETCH_MSTG; -// uint32_t fae_sec = -// Fat32_FatTableEntry fae = -//} \ No newline at end of file +static inline uint32_t fat32_get_cluster_from_pos(const Fat32_CtrlBlock * ctrl, uint32_t first_cluster, uint32_t pos) { + FETCH_MSTG; + uint32_t cluster_link_number = pos / (ctrl->sectors_per_cluster * ctrl->bytes_per_sector); // calculate the sequence number of the FAT entry containing the reference to the desired data cluster + uint32_t fat_iter_sector = 0; + uint32_t cluster = first_cluster; // linked cluster + Fat32_FatTableEntry * fat_iter = NULL; // iterator on FAT table + + for (uint32_t hop = 0; hop < cluster_link_number; hop++) { + uint32_t new_fat_iter_sector = fat32_get_fat_entry_sector_by_cluster_index(ctrl, cluster); // get the FAT sector containing the referred entry + if (new_fat_iter_sector != fat_iter_sector) { + READ_MSTG_TO_FIRST_BUFFER(new_fat_iter_sector); // read FAT sector containing the specific entry to the buffer + fat_iter_sector = new_fat_iter_sector; + } + fat_iter = ((Fat32_FatTableEntry *) buffer) + (cluster % ctrl->fat_entries_per_sector); // get FAT iter + uint32_t next_cluster = (*fat_iter) & ~(0xF << 28); + if (next_cluster >= 2 && next_cluster <= 0xFFFFFEF) { + cluster = next_cluster; + } + } + return cluster; +} + +int fat32_read_file(const Fat32_CtrlBlock * ctrl, const Fat32_FileEntry * entry, uint32_t pos, uint32_t len, uint8_t * p) { + FETCH_MSTG; + uint32_t first_cluster = (entry->first_cluster_high << 16) | (entry->first_cluster_low); + uint32_t cluster = fat32_get_cluster_from_pos(ctrl, first_cluster, pos); + uint32_t sector = fat32_get_first_sector_of_cluster(ctrl, cluster); + READ_MSTG_TO_FIRST_BUFFER(sector); + uint32_t pos_in_sector = pos % ctrl->bytes_per_sector; + memcpy(p, buffer + pos_in_sector, len); + return len; // TODO +} \ No newline at end of file diff --git a/fs/fat32/fat32.h b/fs/fat32/fat32.h index 0c32805..8e2a4d5 100644 --- a/fs/fat32/fat32.h +++ b/fs/fat32/fat32.h @@ -50,6 +50,7 @@ typedef struct { uint32_t sectors_per_fat; // sectors per FAT table uint16_t bytes_per_sector; // number of bytes creating a sector uint16_t sectors_per_cluster; // number of sectors creating a cluster + uint16_t fat_entries_per_sector; // number of FAT entries per sector uint8_t fat_copies; // number of FAT table copies uint8_t volume_label[11]; // pointer to volume label } Fat32_CtrlBlock; @@ -94,8 +95,8 @@ int fat32_load(Fat32_CtrlBlock *ctrl, uint32_t bpb_s, const MassStorage * mstg); int fat32_list_dir(const Fat32_CtrlBlock *ctrl, const char * dir); -int fat32_read_file(const Fat32_CtrlBlock * ctrl, uint32_t pos, uint32_t len); +int fat32_read_file(const Fat32_CtrlBlock * ctrl, const Fat32_FileEntry * entry, uint32_t pos, uint32_t len, uint8_t * p); -int fat32_locate_file(const Fat32_CtrlBlock *ctrl, const char *path); +const Fat32_FileEntry * fat32_locate_file(const Fat32_CtrlBlock *ctrl, const char *path); #endif //EMBPART_FAT32_H