reading from a root-directory file basically works
This commit is contained in:
		
							parent
							
								
									46f6fe7494
								
							
						
					
					
						commit
						1e6e6253b9
					
				
							
								
								
									
										143
									
								
								fs/fat32/fat32.c
									
									
									
									
									
								
							
							
						
						
									
										143
									
								
								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 =
 | 
			
		||||
//}
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user