Directory listing works, initial steps on interpreting paths
This commit is contained in:
		
							parent
							
								
									ae3e1e07cf
								
							
						
					
					
						commit
						46f6fe7494
					
				@ -8,4 +8,6 @@ add_library(embpart embpart.c
 | 
				
			|||||||
        mbr/mbr.h
 | 
					        mbr/mbr.h
 | 
				
			||||||
        ../test/main.c
 | 
					        ../test/main.c
 | 
				
			||||||
        fs/fat32/fat32.c
 | 
					        fs/fat32/fat32.c
 | 
				
			||||||
        fs/fat32/fat32.h)
 | 
					        fs/fat32/fat32.h
 | 
				
			||||||
 | 
					        MassStorage.c
 | 
				
			||||||
 | 
					        MassStorage.h)
 | 
				
			||||||
							
								
								
									
										5
									
								
								MassStorage.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								MassStorage.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by epagris on 2023.10.01..
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "MassStorage.h"
 | 
				
			||||||
							
								
								
									
										16
									
								
								MassStorage.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								MassStorage.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					#ifndef EMBPART_MASSSTORAGE_H
 | 
				
			||||||
 | 
					#define EMBPART_MASSSTORAGE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct _MassStorage{
 | 
				
			||||||
 | 
					    uint32_t sectorSize; // sector size
 | 
				
			||||||
 | 
					    void * data; // some arbitrary data
 | 
				
			||||||
 | 
					    int (*read_sector)(const struct _MassStorage * mstg, uint32_t idx, uint8_t * data); // read specific sector
 | 
				
			||||||
 | 
					    int (*write_sector)(const struct _MassStorage * mstg, uint32_t idx, const uint8_t * data); // read specific sector
 | 
				
			||||||
 | 
					} MassStorage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MSTG_READ(mstg, idx, buffer) (mstg)->read_sector((mstg), (idx), (buffer))
 | 
				
			||||||
 | 
					#define MSTG_WRITE(mstg, idx, buffer) (mstg)->write_sector((mstg), (idx), (buffer))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif //EMBPART_MASSSTORAGE_H
 | 
				
			||||||
							
								
								
									
										222
									
								
								fs/fat32/fat32.c
									
									
									
									
									
								
							
							
						
						
									
										222
									
								
								fs/fat32/fat32.c
									
									
									
									
									
								
							@ -3,12 +3,31 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <memory.h>
 | 
					#include <memory.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include "fat32.h"
 | 
					#include "fat32.h"
 | 
				
			||||||
 | 
					#include "../../MassStorage.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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) {
 | 
				
			||||||
 | 
					    return (cluster - 2) * ctrl->sectors_per_cluster + ctrl->data_s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int fat32_load(Fat32_CtrlBlock *ctrl, uint32_t bpb_s, const MassStorage * mstg) {
 | 
				
			||||||
 | 
					    ctrl->mstg = mstg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int fat32_load(Fat32_CtrlBlock *ctrl, const uint8_t *bpb, uint32_t bpb_s) {
 | 
					 | 
				
			||||||
    ctrl->bpb_s = bpb_s;
 | 
					    ctrl->bpb_s = bpb_s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const Bpb_Fat32 * bpb_obj = (Bpb_Fat32 *)bpb;
 | 
					    // load Boot Parameter Block
 | 
				
			||||||
 | 
					    mstg->read_sector(mstg, bpb_s, buffer);
 | 
				
			||||||
 | 
					    const Bpb_Fat32 * bpb_obj = (Bpb_Fat32 *)buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ctrl->bytes_per_sector = bpb_obj->bytes_per_sector;
 | 
					    ctrl->bytes_per_sector = bpb_obj->bytes_per_sector;
 | 
				
			||||||
    ctrl->sectors_per_cluster = bpb_obj->sectors_per_cluster;
 | 
					    ctrl->sectors_per_cluster = bpb_obj->sectors_per_cluster;
 | 
				
			||||||
@ -19,7 +38,204 @@ int fat32_load(Fat32_CtrlBlock *ctrl, const uint8_t *bpb, uint32_t bpb_s) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ctrl->fat_s = ctrl->bpb_s + bpb_obj->n_reserved_sectors; // FATs are stored on the hidden area right after the reserved sectors
 | 
					    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
 | 
					    ctrl->data_s = ctrl->fat_s + ctrl->fat_copies * ctrl->sectors_per_fat; // data region begins right after the FAT copies
 | 
				
			||||||
    ctrl->root_s = bpb_obj->root_first_cluster * ctrl->sectors_per_cluster + ctrl->data_s; // first sector of root directory is determined using the cluster number as an offset
 | 
					    ctrl->root_s = fat32_get_first_sector_of_cluster(ctrl, bpb_obj->root_first_cluster); // first sector of root directory is determined using the cluster number as an offset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FETCH_MSTG const MassStorage * mstg = ctrl->mstg
 | 
				
			||||||
 | 
					#define READ_MSTG_TO_FIRST_BUFFER(idx) MSTG_READ(mstg, (idx), buffer)
 | 
				
			||||||
 | 
					#define READ_MSTG_TO_SECOND_BUFFER(idx) MSTG_READ(mstg, (idx), buffer + SECTOR_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO some dirty function to chop the high byte from the unicode charcode...
 | 
				
			||||||
 | 
					static inline uint8_t fat32_unicode_to_utf8(uint16_t unicode) {
 | 
				
			||||||
 | 
					    return unicode & 0x00FF;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t fat32_trim_str_right(char * str) {
 | 
				
			||||||
 | 
					    uint32_t len = 0;
 | 
				
			||||||
 | 
					    while (*str > ' ') {
 | 
				
			||||||
 | 
					        str++;
 | 
				
			||||||
 | 
					        len++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    *str = '\0';
 | 
				
			||||||
 | 
					    return len;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO loop unroll!
 | 
				
			||||||
 | 
					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]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    for (uint8_t i = 0; i < 6; i++) { // second block
 | 
				
			||||||
 | 
					        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]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return idx;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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) {
 | 
				
			||||||
 | 
					    //static char entry_name[261];
 | 
				
			||||||
 | 
					    bool done = false;
 | 
				
			||||||
 | 
					    bool reading_lfn = false;
 | 
				
			||||||
 | 
					    uint8_t rewind = 0;
 | 
				
			||||||
 | 
					    uint8_t attribs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // look for the first non-LFN entry and count the LFNs
 | 
				
			||||||
 | 
					    while (!done) {
 | 
				
			||||||
 | 
					        attribs = (*entry)->attributes;
 | 
				
			||||||
 | 
					        if (LONG_FILE_NAME_ATTRIB_TEST(attribs)) { // if this is an LFN-entry
 | 
				
			||||||
 | 
					            rewind++;
 | 
				
			||||||
 | 
					            reading_lfn = true;
 | 
				
			||||||
 | 
					            (*entry)++; // advance in the table
 | 
				
			||||||
 | 
					        } else { // if this is NOT an LFN-entry
 | 
				
			||||||
 | 
					            done = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // fetch long name
 | 
				
			||||||
 | 
					        for (uint8_t i = 0; i < rewind; i++) {
 | 
				
			||||||
 | 
					            name_len += fat32_extract_lfn_text(lfnEntry, entry_name + name_len);
 | 
				
			||||||
 | 
					            lfnEntry--; // retreat entry
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        entry_name[name_len] = '\0'; // terminate string
 | 
				
			||||||
 | 
					        name_len = fat32_trim_str_right(entry_name); // trim residual whitespaces
 | 
				
			||||||
 | 
					    } else { // if the entry has only a short name
 | 
				
			||||||
 | 
					        memcpy(entry_name, finalEntry->short_fname, 8); // copy basename
 | 
				
			||||||
 | 
					        name_len = fat32_trim_str_right(entry_name); // trim whitespaces
 | 
				
			||||||
 | 
					        if (!((attribs & FAT32_FATT_VOLUME) || (attribs & FAT32_FATT_DIRECTORY))) { // omit dot if volume label or directory
 | 
				
			||||||
 | 
					            entry_name[name_len++] = '.'; // insert dot
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        memcpy(entry_name + name_len, finalEntry->extension, 3); // copy extension
 | 
				
			||||||
 | 
					        name_len = fat32_trim_str_right(entry_name); // trim whitespaces
 | 
				
			||||||
 | 
					        if (entry_name[name_len - 1] == '.') { // chop dot if no extension
 | 
				
			||||||
 | 
					            name_len--;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        entry_name[name_len] = '\0'; // terminate string
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return name_len;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					    if (attribs & FAT32_FATT_DIRECTORY) {
 | 
				
			||||||
 | 
					        entry_type[0] = 'D';
 | 
				
			||||||
 | 
					    } else if (attribs & FAT32_FATT_VOLUME) {
 | 
				
			||||||
 | 
					        entry_type[0] = 'V';
 | 
				
			||||||
 | 
					    } else if (attribs & FAT32_FATT_HIDDEN) {
 | 
				
			||||||
 | 
					        entry_type[1] = 'H';
 | 
				
			||||||
 | 
					    } else if (attribs & FAT32_FATT_READ_ONLY) {
 | 
				
			||||||
 | 
					        entry_type[2] = 'R';
 | 
				
			||||||
 | 
					    } else if (attribs & FAT32_FATT_SYSTEM) {
 | 
				
			||||||
 | 
					        entry_type[3] = 'S';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint16_t padding = 1;
 | 
				
			||||||
 | 
					    if (name_len < LINELENGTH){
 | 
				
			||||||
 | 
					        padding = LINELENGTH - name_len;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    MSG("%s%*c%s %u\n", entry_name, padding, ' ', entry_type, (*entry)->size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FAT32_UNUSED_FILE_ENTRY (0xE5)
 | 
				
			||||||
 | 
					#define FAT32_DIRECTORY_SEPARATOR ('/')
 | 
				
			||||||
 | 
					#define FAT32_MAX_BASENAME_LENGTH (47)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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++) {}
 | 
				
			||||||
 | 
					    return i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int fat32_locate_file(const Fat32_CtrlBlock *ctrl, const char *path) {
 | 
				
			||||||
 | 
					    FETCH_MSTG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // start search in the root directory
 | 
				
			||||||
 | 
					    uint32_t sector = ctrl->root_s;
 | 
				
			||||||
 | 
					    READ_MSTG_TO_FIRST_BUFFER(sector);
 | 
				
			||||||
 | 
					    READ_MSTG_TO_SECOND_BUFFER(sector + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
 | 
					    char basename[FAT32_MAX_BASENAME_LENGTH + 1]; // basename
 | 
				
			||||||
 | 
					    basename[FAT32_MAX_BASENAME_LENGTH] = '\0'; // NULL-termination
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while ((!file_found) && (!no_such_file)) {
 | 
				
			||||||
 | 
					        // extract first basename
 | 
				
			||||||
 | 
					        uint16_t basename_len = fat32_extract_next_basename_length(path_iter); // get basename length
 | 
				
			||||||
 | 
					        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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int fat32_list_dir(const Fat32_CtrlBlock *ctrl, const char *dir) {
 | 
				
			||||||
 | 
					    // TODO find directory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // read root directory
 | 
				
			||||||
 | 
					    FETCH_MSTG;
 | 
				
			||||||
 | 
					    uint32_t sector = ctrl->root_s;
 | 
				
			||||||
 | 
					    READ_MSTG_TO_FIRST_BUFFER(sector);
 | 
				
			||||||
 | 
					    READ_MSTG_TO_SECOND_BUFFER(sector + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // acquire pointer to the beginning of the file entry table
 | 
				
			||||||
 | 
					    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);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        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);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 =
 | 
				
			||||||
 | 
					//}
 | 
				
			||||||
@ -3,6 +3,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __linux
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include "../../MassStorage.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MSG(...) printf(__VA_ARGS__)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    uint8_t boot_jump[3]; // jump instruction used for bootable volume
 | 
					    uint8_t boot_jump[3]; // jump instruction used for bootable volume
 | 
				
			||||||
    uint8_t formatter_name[8]; // identification of application or OS formatted this device
 | 
					    uint8_t formatter_name[8]; // identification of application or OS formatted this device
 | 
				
			||||||
@ -34,6 +41,7 @@ typedef struct {
 | 
				
			|||||||
} __attribute__((packed)) Bpb_Fat32;
 | 
					} __attribute__((packed)) Bpb_Fat32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    const MassStorage * mstg; // mass storage holding the partition
 | 
				
			||||||
    uint32_t bpb_s; // sector of bios parameter block
 | 
					    uint32_t bpb_s; // sector of bios parameter block
 | 
				
			||||||
    uint32_t fat_s; // first sector of the FAT area
 | 
					    uint32_t fat_s; // first sector of the FAT area
 | 
				
			||||||
    uint32_t root_s; // first sector of root directory
 | 
					    uint32_t root_s; // first sector of root directory
 | 
				
			||||||
@ -46,6 +54,48 @@ typedef struct {
 | 
				
			|||||||
    uint8_t volume_label[11]; // pointer to volume label
 | 
					    uint8_t volume_label[11]; // pointer to volume label
 | 
				
			||||||
} Fat32_CtrlBlock;
 | 
					} Fat32_CtrlBlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int fat32_load(Fat32_CtrlBlock *ctrl, const uint8_t *bpb, uint32_t bpb_s);
 | 
					typedef uint32_t Fat32_FatTableEntry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FAT32_FATT_READ_ONLY (1)
 | 
				
			||||||
 | 
					#define FAT32_FATT_HIDDEN (1 << 1)
 | 
				
			||||||
 | 
					#define FAT32_FATT_SYSTEM (1 << 2)
 | 
				
			||||||
 | 
					#define FAT32_FATT_VOLUME (1 << 3)
 | 
				
			||||||
 | 
					#define FAT32_FATT_DIRECTORY (1 << 4)
 | 
				
			||||||
 | 
					#define FAT32_FATT_ARCHIVE (1 << 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    uint8_t short_fname[8]; // short filename
 | 
				
			||||||
 | 
					    uint8_t extension[3]; // file extension
 | 
				
			||||||
 | 
					    uint8_t attributes; // entry attributes
 | 
				
			||||||
 | 
					    uint8_t _reserved0;
 | 
				
			||||||
 | 
					    uint8_t creat_time_hs; // file creation time, hundredth of a second (0-199)
 | 
				
			||||||
 | 
					    uint16_t creat_time_hms; // file creation time, hour, minute, second
 | 
				
			||||||
 | 
					    uint16_t create_date_ymd; // file creation date year, month, day
 | 
				
			||||||
 | 
					    uint16_t lastacc_data_ymd; // ...
 | 
				
			||||||
 | 
					    uint16_t first_cluster_high; // high word of first cluster
 | 
				
			||||||
 | 
					    uint16_t lastmod_time_hms; // ...
 | 
				
			||||||
 | 
					    uint16_t lastmod_date_ymd; // ...
 | 
				
			||||||
 | 
					    uint16_t first_cluster_low; // high word of first cluster
 | 
				
			||||||
 | 
					    uint32_t size; // file size in bytes
 | 
				
			||||||
 | 
					} __attribute__((packed)) Fat32_FileEntry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    uint8_t index; // order of this entry in the series of LFN entries
 | 
				
			||||||
 | 
					    uint16_t ustr04[5]; // characters 0-4
 | 
				
			||||||
 | 
					    uint8_t attributes; // must have bits 0-3 set
 | 
				
			||||||
 | 
					    uint8_t type; // should be zero
 | 
				
			||||||
 | 
					    uint8_t checksum; // string checksum
 | 
				
			||||||
 | 
					    uint16_t ustr5A[6]; // characters 5-10
 | 
				
			||||||
 | 
					    uint16_t cluster; // should be zero
 | 
				
			||||||
 | 
					    uint16_t ustrBC[2]; // characters 11-12
 | 
				
			||||||
 | 
					} __attribute__((packed)) Fat32_LongFileNameEntry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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_locate_file(const Fat32_CtrlBlock *ctrl, const char *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif //EMBPART_FAT32_H
 | 
					#endif //EMBPART_FAT32_H
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user