fat_io_lib port WIP
All checks were successful
Build documentation / build-and-deploy (push) Successful in 3m12s
All checks were successful
Build documentation / build-and-deploy (push) Successful in 3m12s
This commit is contained in:
@@ -9,6 +9,12 @@
|
||||
#include <sync/spin_lock.h>
|
||||
#include <sys/smp.h>
|
||||
|
||||
#define device_op1(d, op, proc, rctx, a1, a2, a3, a4, ...) \
|
||||
(d)->ops[(op)]((d), (proc), (rctx), (void*)(a1), (void*)(a2), (void*)(a3), (void*)(a4))
|
||||
|
||||
#define device_op(d, op, proc, rctx, ...) \
|
||||
device_op1 (d, op, proc, rctx, __VA_ARGS__, NULL, NULL, NULL, NULL)
|
||||
|
||||
struct device;
|
||||
|
||||
typedef int (*device_op_func_t) (struct device* device, struct proc*, struct reschedule_ctx* rctx,
|
||||
|
||||
@@ -91,16 +91,18 @@ int ramdrv_get_sector_size (struct device* device, struct proc* proc, struct res
|
||||
|
||||
int ramdrv_read (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, void* a1,
|
||||
void* a2, void* a3, void* a4) {
|
||||
if (a1 == NULL || a2 == NULL || a3 == NULL || a4 == NULL)
|
||||
(void)proc, (void)rctx, (void)a4;
|
||||
|
||||
if (a1 == NULL || a2 == NULL || a3 == NULL)
|
||||
return -ST_BAD_ADDRESS_SPACE;
|
||||
|
||||
size_t sector = *(size_t*)a1;
|
||||
size_t off = *(size_t*)a2;
|
||||
size_t size = *(size_t*)a3;
|
||||
uint8_t* buffer = a4;
|
||||
size_t sector_count = *(size_t*)a2;
|
||||
uint8_t* buffer = a3;
|
||||
|
||||
struct ramdrv* ramdrv = device->udata;
|
||||
size_t pos = sector * ramdrv->sector_size + off;
|
||||
size_t pos = sector * ramdrv->sector_size;
|
||||
size_t size = sector_count * ramdrv->sector_size;
|
||||
|
||||
memcpy (buffer, (void*)(((uintptr_t)ramdrv->buffer) + pos), size);
|
||||
|
||||
|
||||
2899
kernel/fs/fat1.c
Normal file
2899
kernel/fs/fat1.c
Normal file
File diff suppressed because it is too large
Load Diff
451
kernel/fs/fat1.h
Normal file
451
kernel/fs/fat1.h
Normal file
@@ -0,0 +1,451 @@
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-function"
|
||||
struct fatfs_ctx;
|
||||
#define __FAT_ACCESS_H__
|
||||
|
||||
#define __FAT_DEFS_H__
|
||||
|
||||
#define __FAT_OPTS_H__
|
||||
#define FATFS_IS_LITTLE_ENDIAN 1
|
||||
#define FATFS_MAX_LONG_FILENAME 260
|
||||
#define FATFS_MAX_OPEN_FILES 2
|
||||
#define FAT_BUFFER_SECTORS 1
|
||||
#define FAT_BUFFERS 1
|
||||
#define FATFS_INC_WRITE_SUPPORT 1
|
||||
#define FATFS_INC_LFN_SUPPORT 1
|
||||
#define FATFS_DIR_LIST_SUPPORT 1
|
||||
#define FATFS_INC_TIME_DATE_SUPPORT 0
|
||||
#define FATFS_INC_FORMAT_SUPPORT 1
|
||||
#define FAT_SECTOR_SIZE 512
|
||||
|
||||
#define __FAT_TYPES_H__
|
||||
#define FATFS_DEF_UINT32_AS_INT
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint32;
|
||||
#define NULL 0
|
||||
#define FAT_HTONS(n) (n)
|
||||
#define FAT_HTONL(n) (n)
|
||||
#define STRUCT_PACK
|
||||
#define STRUCT_PACK_BEGIN
|
||||
#define STRUCT_PACK_END
|
||||
#define STRUCT_PACKED __attribute__ ((packed))
|
||||
#define BS_JMPBOOT 0
|
||||
#define BS_OEMNAME 3
|
||||
#define BPB_BYTSPERSEC 11
|
||||
#define BPB_SECPERCLUS 13
|
||||
#define BPB_RSVDSECCNT 14
|
||||
#define BPB_NUMFATS 16
|
||||
#define BPB_ROOTENTCNT 17
|
||||
#define BPB_TOTSEC16 19
|
||||
#define BPB_MEDIA 21
|
||||
#define BPB_FATSZ16 22
|
||||
#define BPB_SECPERTRK 24
|
||||
#define BPB_NUMHEADS 26
|
||||
#define BPB_HIDDSEC 28
|
||||
#define BPB_TOTSEC32 32
|
||||
#define BS_FAT_DRVNUM 36
|
||||
#define BS_FAT_BOOTSIG 38
|
||||
#define BS_FAT_VOLID 39
|
||||
#define BS_FAT_VOLLAB 43
|
||||
#define BS_FAT_FILSYSTYPE 54
|
||||
#define BPB_FAT32_FATSZ32 36
|
||||
#define BPB_FAT32_EXTFLAGS 40
|
||||
#define BPB_FAT32_FSVER 42
|
||||
#define BPB_FAT32_ROOTCLUS 44
|
||||
#define BPB_FAT32_FSINFO 48
|
||||
#define BPB_FAT32_BKBOOTSEC 50
|
||||
#define BS_FAT32_DRVNUM 64
|
||||
#define BS_FAT32_BOOTSIG 66
|
||||
#define BS_FAT32_VOLID 67
|
||||
#define BS_FAT32_VOLLAB 71
|
||||
#define BS_FAT32_FILSYSTYPE 82
|
||||
#define FAT_TYPE_FAT12 1
|
||||
#define FAT_TYPE_FAT16 2
|
||||
#define FAT_TYPE_FAT32 3
|
||||
#define SIGNATURE_POSITION 510
|
||||
#define SIGNATURE_VALUE 0xAA55
|
||||
#define PARTITION1_TYPECODE_LOCATION 450
|
||||
#define FAT32_TYPECODE1 0x0B
|
||||
#define FAT32_TYPECODE2 0x0C
|
||||
#define PARTITION1_LBA_BEGIN_LOCATION 454
|
||||
#define PARTITION1_SIZE_LOCATION 458
|
||||
#define FAT_DIR_ENTRY_SIZE 32
|
||||
#define FAT_SFN_SIZE_FULL 11
|
||||
#define FAT_SFN_SIZE_PARTIAL 8
|
||||
#define FILE_ATTR_READ_ONLY 0x01
|
||||
#define FILE_ATTR_HIDDEN 0x02
|
||||
#define FILE_ATTR_SYSTEM 0x04
|
||||
#define FILE_ATTR_SYSHID 0x06
|
||||
#define FILE_ATTR_VOLUME_ID 0x08
|
||||
#define FILE_ATTR_DIRECTORY 0x10
|
||||
#define FILE_ATTR_ARCHIVE 0x20
|
||||
#define FILE_ATTR_LFN_TEXT 0x0F
|
||||
#define FILE_HEADER_BLANK 0x00
|
||||
#define FILE_HEADER_DELETED 0xE5
|
||||
#define FILE_TYPE_DIR 0x10
|
||||
#define FILE_TYPE_FILE 0x20
|
||||
#define FAT_TIME_HOURS_SHIFT 11
|
||||
#define FAT_TIME_HOURS_MASK 0x1F
|
||||
#define FAT_TIME_MINUTES_SHIFT 5
|
||||
#define FAT_TIME_MINUTES_MASK 0x3F
|
||||
#define FAT_TIME_SECONDS_SHIFT 0
|
||||
#define FAT_TIME_SECONDS_MASK 0x1F
|
||||
#define FAT_TIME_SECONDS_SCALE 2
|
||||
#define FAT_DATE_YEAR_SHIFT 9
|
||||
#define FAT_DATE_YEAR_MASK 0x7F
|
||||
#define FAT_DATE_MONTH_SHIFT 5
|
||||
#define FAT_DATE_MONTH_MASK 0xF
|
||||
#define FAT_DATE_DAY_SHIFT 0
|
||||
#define FAT_DATE_DAY_MASK 0x1F
|
||||
#define FAT_DATE_YEAR_OFFSET 1980
|
||||
#define FAT32_LAST_CLUSTER 0xFFFFFFFF
|
||||
#define FAT32_INVALID_CLUSTER 0xFFFFFFFF
|
||||
STRUCT_PACK_BEGIN
|
||||
struct fat_dir_entry STRUCT_PACK {
|
||||
uint8 Name[11];
|
||||
uint8 Attr;
|
||||
uint8 NTRes;
|
||||
uint8 CrtTimeTenth;
|
||||
uint8 CrtTime[2];
|
||||
uint8 CrtDate[2];
|
||||
uint8 LstAccDate[2];
|
||||
uint16 FstClusHI;
|
||||
uint8 WrtTime[2];
|
||||
uint8 WrtDate[2];
|
||||
uint16 FstClusLO;
|
||||
uint32 FileSize;
|
||||
} STRUCT_PACKED;
|
||||
STRUCT_PACK_END
|
||||
#define FAT_INIT_OK 0
|
||||
#define FAT_INIT_MEDIA_ACCESS_ERROR (-1)
|
||||
#define FAT_INIT_INVALID_SECTOR_SIZE (-2)
|
||||
#define FAT_INIT_INVALID_SIGNATURE (-3)
|
||||
#define FAT_INIT_ENDIAN_ERROR (-4)
|
||||
#define FAT_INIT_WRONG_FILESYS_TYPE (-5)
|
||||
#define FAT_INIT_WRONG_PARTITION_TYPE (-6)
|
||||
#define FAT_INIT_STRUCT_PACKING (-7)
|
||||
#define FAT_DIR_ENTRIES_PER_SECTOR (FAT_SECTOR_SIZE / FAT_DIR_ENTRY_SIZE)
|
||||
typedef int (*fn_diskio_read) (struct fatfs_ctx* ctx, uint32 sector, uint8* buffer,
|
||||
uint32 sector_count);
|
||||
typedef int (*fn_diskio_write) (struct fatfs_ctx* ctx, uint32 sector, uint8* buffer,
|
||||
uint32 sector_count);
|
||||
struct disk_if {
|
||||
fn_diskio_read read_media;
|
||||
fn_diskio_write write_media;
|
||||
};
|
||||
struct fat_buffer;
|
||||
struct fat_buffer {
|
||||
uint8 sector[FAT_SECTOR_SIZE * FAT_BUFFER_SECTORS];
|
||||
uint32 address;
|
||||
int dirty;
|
||||
uint8* ptr;
|
||||
struct fat_buffer* next;
|
||||
};
|
||||
typedef enum eFatType { FAT_TYPE_16, FAT_TYPE_32 } tFatType;
|
||||
struct fatfs {
|
||||
uint8 sectors_per_cluster;
|
||||
uint32 cluster_begin_lba;
|
||||
uint32 rootdir_first_cluster;
|
||||
uint32 rootdir_first_sector;
|
||||
uint32 rootdir_sectors;
|
||||
uint32 fat_begin_lba;
|
||||
uint16 fs_info_sector;
|
||||
uint32 lba_begin;
|
||||
uint32 fat_sectors;
|
||||
uint32 next_free_cluster;
|
||||
uint16 root_entry_count;
|
||||
uint16 reserved_sectors;
|
||||
uint8 num_of_fats;
|
||||
tFatType fat_type;
|
||||
struct disk_if disk_io;
|
||||
void (*fl_lock) (void);
|
||||
void (*fl_unlock) (void);
|
||||
struct fat_buffer currentsector;
|
||||
struct fat_buffer* fat_buffer_head;
|
||||
struct fat_buffer fat_buffers[FAT_BUFFERS];
|
||||
};
|
||||
struct fs_dir_list_status {
|
||||
uint32 sector;
|
||||
uint32 cluster;
|
||||
uint8 offset;
|
||||
};
|
||||
struct fs_dir_ent {
|
||||
char filename[FATFS_MAX_LONG_FILENAME];
|
||||
uint8 is_dir;
|
||||
uint32 cluster;
|
||||
uint32 size;
|
||||
};
|
||||
int fatfs_init (struct fatfs_ctx* ctx, struct fatfs* fs);
|
||||
uint32 fatfs_lba_of_cluster (struct fatfs* fs, uint32 Cluster_Number);
|
||||
int fatfs_sector_reader (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 Startcluster,
|
||||
uint32 offset, uint8* target);
|
||||
int fatfs_sector_read (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 lba, uint8* target,
|
||||
uint32 count);
|
||||
int fatfs_sector_write (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 lba, uint8* target,
|
||||
uint32 count);
|
||||
int fatfs_read_sector (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 cluster, uint32 sector,
|
||||
uint8* target);
|
||||
int fatfs_write_sector (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 cluster, uint32 sector,
|
||||
uint8* target);
|
||||
void fatfs_show_details (struct fatfs* fs);
|
||||
uint32 fatfs_get_root_cluster (struct fatfs* fs);
|
||||
uint32 fatfs_get_file_entry (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 Cluster,
|
||||
char* nametofind, struct fat_dir_entry* sfEntry);
|
||||
int fatfs_sfn_exists (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 Cluster, char* shortname);
|
||||
int fatfs_update_file_length (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 Cluster,
|
||||
char* shortname, uint32 fileLength);
|
||||
int fatfs_mark_file_deleted (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 Cluster,
|
||||
char* shortname);
|
||||
void fatfs_list_directory_start (struct fatfs* fs, struct fs_dir_list_status* dirls,
|
||||
uint32 StartCluster);
|
||||
int fatfs_list_directory_next (struct fatfs_ctx* ctx, struct fatfs* fs,
|
||||
struct fs_dir_list_status* dirls, struct fs_dir_ent* entry);
|
||||
int fatfs_update_timestamps (struct fat_dir_entry* directoryEntry, int create, int modify,
|
||||
int access);
|
||||
|
||||
#define __FAT_FORMAT_H__
|
||||
int fatfs_format (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 volume_sectors, const char* name);
|
||||
int fatfs_format_fat16 (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 volume_sectors,
|
||||
const char* name);
|
||||
int fatfs_format_fat32 (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 volume_sectors,
|
||||
const char* name);
|
||||
|
||||
#define __FAT_MISC_H__
|
||||
#define MAX_LONGFILENAME_ENTRIES 20
|
||||
#define MAX_LFN_ENTRY_LENGTH 13
|
||||
#define GET_32BIT_WORD(buffer, location) \
|
||||
(((uint32)buffer[location + 3] << 24) + ((uint32)buffer[location + 2] << 16) + \
|
||||
((uint32)buffer[location + 1] << 8) + (uint32)buffer[location + 0])
|
||||
#define GET_16BIT_WORD(buffer, location) \
|
||||
(((uint16)buffer[location + 1] << 8) + (uint16)buffer[location + 0])
|
||||
#define SET_32BIT_WORD(buffer, location, value) \
|
||||
{ \
|
||||
buffer[location + 0] = (uint8)((value) & 0xFF); \
|
||||
buffer[location + 1] = (uint8)((value >> 8) & 0xFF); \
|
||||
buffer[location + 2] = (uint8)((value >> 16) & 0xFF); \
|
||||
buffer[location + 3] = (uint8)((value >> 24) & 0xFF); \
|
||||
}
|
||||
#define SET_16BIT_WORD(buffer, location, value) \
|
||||
{ \
|
||||
buffer[location + 0] = (uint8)((value) & 0xFF); \
|
||||
buffer[location + 1] = (uint8)((value >> 8) & 0xFF); \
|
||||
}
|
||||
struct lfn_cache {
|
||||
uint8 String[MAX_LONGFILENAME_ENTRIES][MAX_LFN_ENTRY_LENGTH];
|
||||
uint8 Null;
|
||||
uint8 no_of_strings;
|
||||
};
|
||||
void fatfs_lfn_cache_init (struct lfn_cache* lfn, int wipeTable);
|
||||
void fatfs_lfn_cache_entry (struct lfn_cache* lfn, uint8* entryBuffer);
|
||||
char* fatfs_lfn_cache_get (struct lfn_cache* lfn);
|
||||
int fatfs_entry_lfn_text (struct fat_dir_entry* entry);
|
||||
int fatfs_entry_lfn_invalid (struct fat_dir_entry* entry);
|
||||
int fatfs_entry_lfn_exists (struct lfn_cache* lfn, struct fat_dir_entry* entry);
|
||||
int fatfs_entry_sfn_only (struct fat_dir_entry* entry);
|
||||
int fatfs_entry_is_dir (struct fat_dir_entry* entry);
|
||||
int fatfs_entry_is_file (struct fat_dir_entry* entry);
|
||||
int fatfs_lfn_entries_required (char* filename);
|
||||
void fatfs_filename_to_lfn (char* filename, uint8* buffer, int entry, uint8 sfnChk);
|
||||
void fatfs_sfn_create_entry (char* shortfilename, uint32 size, uint32 startCluster,
|
||||
struct fat_dir_entry* entry, int dir);
|
||||
int fatfs_lfn_create_sfn (char* sfn_output, char* filename);
|
||||
int fatfs_lfn_generate_tail (char* sfn_output, char* sfn_input, uint32 tailNum);
|
||||
void fatfs_convert_from_fat_time (uint16 fat_time, int* hours, int* minutes, int* seconds);
|
||||
void fatfs_convert_from_fat_date (uint16 fat_date, int* day, int* month, int* year);
|
||||
uint16 fatfs_convert_to_fat_time (int hours, int minutes, int seconds);
|
||||
uint16 fatfs_convert_to_fat_date (int day, int month, int year);
|
||||
void fatfs_print_sector (uint32 sector, uint8* data);
|
||||
|
||||
#define __FILESTRING_H__
|
||||
int fatfs_total_path_levels (char* path);
|
||||
int fatfs_get_substring (char* Path, int levelreq, char* output, int max_len);
|
||||
int fatfs_split_path (char* FullPath, char* Path, int max_path, char* FileName, int max_filename);
|
||||
int fatfs_compare_names (char* strA, char* strB);
|
||||
int fatfs_string_ends_with_slash (char* path);
|
||||
int fatfs_get_sfn_display_name (char* out, char* in);
|
||||
int fatfs_get_extension (char* filename, char* out, int maxlen);
|
||||
int fatfs_create_path_string (char* path, char* filename, char* out, int maxlen);
|
||||
|
||||
#define __FAT_CACHE_H__
|
||||
|
||||
#define __FAT_FILELIB_H__
|
||||
|
||||
#define __FAT_LIST_H__
|
||||
#define FAT_ASSERT(x)
|
||||
#define FAT_INLINE
|
||||
struct fat_list;
|
||||
struct fat_node {
|
||||
struct fat_node* previous;
|
||||
struct fat_node* next;
|
||||
};
|
||||
struct fat_list {
|
||||
struct fat_node* head;
|
||||
struct fat_node* tail;
|
||||
};
|
||||
#define fat_list_entry(p, t, m) p ? ((t*)((char*)(p) - (char*)(&((t*)0)->m))) : 0
|
||||
#define fat_list_next(l, p) (p)->next
|
||||
#define fat_list_prev(l, p) (p)->previous
|
||||
#define fat_list_first(l) (l)->head
|
||||
#define fat_list_last(l) (l)->tail
|
||||
#define fat_list_for_each(l, p) for ((p) = (l)->head; (p); (p) = (p)->next)
|
||||
static FAT_INLINE void fat_list_init (struct fat_list* list) {
|
||||
FAT_ASSERT (list);
|
||||
list->head = list->tail = 0;
|
||||
}
|
||||
static FAT_INLINE void fat_list_remove (struct fat_list* list, struct fat_node* node) {
|
||||
FAT_ASSERT (list);
|
||||
FAT_ASSERT (node);
|
||||
if (!node->previous)
|
||||
list->head = node->next;
|
||||
else
|
||||
node->previous->next = node->next;
|
||||
if (!node->next)
|
||||
list->tail = node->previous;
|
||||
else
|
||||
node->next->previous = node->previous;
|
||||
}
|
||||
static FAT_INLINE void fat_list_insert_after (struct fat_list* list, struct fat_node* node,
|
||||
struct fat_node* new_node) {
|
||||
FAT_ASSERT (list);
|
||||
FAT_ASSERT (node);
|
||||
FAT_ASSERT (new_node);
|
||||
new_node->previous = node;
|
||||
new_node->next = node->next;
|
||||
if (!node->next)
|
||||
list->tail = new_node;
|
||||
else
|
||||
node->next->previous = new_node;
|
||||
node->next = new_node;
|
||||
}
|
||||
static FAT_INLINE void fat_list_insert_before (struct fat_list* list, struct fat_node* node,
|
||||
struct fat_node* new_node) {
|
||||
FAT_ASSERT (list);
|
||||
FAT_ASSERT (node);
|
||||
FAT_ASSERT (new_node);
|
||||
new_node->previous = node->previous;
|
||||
new_node->next = node;
|
||||
if (!node->previous)
|
||||
list->head = new_node;
|
||||
else
|
||||
node->previous->next = new_node;
|
||||
node->previous = new_node;
|
||||
}
|
||||
static FAT_INLINE void fat_list_insert_first (struct fat_list* list, struct fat_node* node) {
|
||||
FAT_ASSERT (list);
|
||||
FAT_ASSERT (node);
|
||||
if (!list->head) {
|
||||
list->head = node;
|
||||
list->tail = node;
|
||||
node->previous = 0;
|
||||
node->next = 0;
|
||||
} else
|
||||
fat_list_insert_before (list, list->head, node);
|
||||
}
|
||||
static FAT_INLINE void fat_list_insert_last (struct fat_list* list, struct fat_node* node) {
|
||||
FAT_ASSERT (list);
|
||||
FAT_ASSERT (node);
|
||||
if (!list->tail)
|
||||
fat_list_insert_first (list, node);
|
||||
else
|
||||
fat_list_insert_after (list, list->tail, node);
|
||||
}
|
||||
static FAT_INLINE int fat_list_is_empty (struct fat_list* list) {
|
||||
FAT_ASSERT (list);
|
||||
return !list->head;
|
||||
}
|
||||
static FAT_INLINE struct fat_node* fat_list_pop_head (struct fat_list* list) {
|
||||
struct fat_node* node;
|
||||
FAT_ASSERT (list);
|
||||
node = fat_list_first (list);
|
||||
if (node)
|
||||
fat_list_remove (list, node);
|
||||
return node;
|
||||
}
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
#define SEEK_SET 0
|
||||
#define EOF (-1)
|
||||
struct sFL_FILE;
|
||||
struct cluster_lookup {
|
||||
uint32 ClusterIdx;
|
||||
uint32 CurrentCluster;
|
||||
};
|
||||
typedef struct sFL_FILE {
|
||||
uint32 parentcluster;
|
||||
uint32 startcluster;
|
||||
uint32 bytenum;
|
||||
uint32 filelength;
|
||||
int filelength_changed;
|
||||
char path[FATFS_MAX_LONG_FILENAME];
|
||||
char filename[FATFS_MAX_LONG_FILENAME];
|
||||
uint8 shortfilename[11];
|
||||
struct cluster_lookup last_fat_lookup;
|
||||
uint8 file_data_sector[FAT_SECTOR_SIZE];
|
||||
uint32 file_data_address;
|
||||
int file_data_dirty;
|
||||
uint8 flags;
|
||||
#define FILE_READ (1 << 0)
|
||||
#define FILE_WRITE (1 << 1)
|
||||
#define FILE_APPEND (1 << 2)
|
||||
#define FILE_BINARY (1 << 3)
|
||||
#define FILE_ERASE (1 << 4)
|
||||
#define FILE_CREATE (1 << 5)
|
||||
struct fat_node list_node;
|
||||
} FL_FILE;
|
||||
void fl_init (struct fatfs_ctx* ctx);
|
||||
void fl_attach_locks (struct fatfs_ctx* ctx, void (*lock) (void), void (*unlock) (void));
|
||||
int fl_attach_media (struct fatfs_ctx* ctx, fn_diskio_read rd, fn_diskio_write wr);
|
||||
void fl_shutdown (struct fatfs_ctx* ctx);
|
||||
void* fl_fopen (struct fatfs_ctx* ctx, const char* path, const char* modifiers);
|
||||
void fl_fclose (struct fatfs_ctx* ctx, void* file);
|
||||
int fl_fflush (struct fatfs_ctx* ctx, void* file);
|
||||
int fl_fgetc (struct fatfs_ctx* ctx, void* file);
|
||||
char* fl_fgets (struct fatfs_ctx* ctx, char* s, int n, void* f);
|
||||
int fl_fputc (struct fatfs_ctx* ctx, int c, void* file);
|
||||
int fl_fputs (struct fatfs_ctx* ctx, const char* str, void* file);
|
||||
int fl_fwrite (struct fatfs_ctx* ctx, const void* data, int size, int count, void* file);
|
||||
int fl_fread (struct fatfs_ctx* ctx, void* data, int size, int count, void* file);
|
||||
int fl_fseek (struct fatfs_ctx* ctx, void* file, long offset, int origin);
|
||||
int fl_fgetpos (struct fatfs_ctx* ctx, void* file, uint32* position);
|
||||
long fl_ftell (struct fatfs_ctx* ctx, void* f);
|
||||
int fl_feof (struct fatfs_ctx* ctx, void* f);
|
||||
int fl_remove (struct fatfs_ctx* ctx, const char* filename);
|
||||
typedef struct fs_dir_list_status FL_DIR;
|
||||
typedef struct fs_dir_ent fl_dirent;
|
||||
FL_DIR* fl_opendir (struct fatfs_ctx* ctx, const char* path, FL_DIR* dir);
|
||||
int fl_readdir (struct fatfs_ctx* ctx, FL_DIR* dirls, fl_dirent* entry);
|
||||
int fl_closedir (struct fatfs_ctx* ctx, FL_DIR* dir);
|
||||
void fl_listdirectory (struct fatfs_ctx* ctx, const char* path);
|
||||
int fl_createdirectory (struct fatfs_ctx* ctx, const char* path);
|
||||
int fl_is_dir (struct fatfs_ctx* ctx, const char* path);
|
||||
int fl_format (struct fatfs_ctx* ctx, uint32 volume_sectors, const char* name);
|
||||
int fatfs_cache_init (struct fatfs* fs, FL_FILE* file);
|
||||
int fatfs_cache_get_next_cluster (struct fatfs* fs, FL_FILE* file, uint32 clusterIdx,
|
||||
uint32* pNextCluster);
|
||||
int fatfs_cache_set_next_cluster (struct fatfs* fs, FL_FILE* file, uint32 clusterIdx,
|
||||
uint32 nextCluster);
|
||||
|
||||
#define __FAT_TABLE_H__
|
||||
void fatfs_fat_init (struct fatfs* fs);
|
||||
int fatfs_fat_purge (struct fatfs_ctx* ctx, struct fatfs* fs);
|
||||
uint32 fatfs_find_next_cluster (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 current_cluster);
|
||||
void fatfs_set_fs_info_next_free_cluster (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 newValue);
|
||||
int fatfs_find_blank_cluster (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 start_cluster,
|
||||
uint32* free_cluster);
|
||||
int fatfs_fat_set_cluster (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 cluster,
|
||||
uint32 next_cluster);
|
||||
int fatfs_fat_add_cluster_to_chain (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 start_cluster,
|
||||
uint32 newEntry);
|
||||
int fatfs_free_cluster_chain (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 start_cluster);
|
||||
uint32 fatfs_count_free_clusters (struct fatfs_ctx* ctx, struct fatfs* fs);
|
||||
|
||||
#define __FAT_WRITE_H__
|
||||
int fatfs_add_file_entry (struct fatfs_ctx* ctx, struct fatfs* fs, uint32 dirCluster,
|
||||
char* filename, char* shortfilename, uint32 startCluster, uint32 size,
|
||||
int dir);
|
||||
int fatfs_add_free_space (struct fatfs_ctx* ctx, struct fatfs* fs, uint32* startCluster,
|
||||
uint32 clusters);
|
||||
int fatfs_allocate_free_space (struct fatfs_ctx* ctx, struct fatfs* fs, int newFile,
|
||||
uint32* startCluster, uint32 size);
|
||||
#pragma clang diagnostic pop
|
||||
139
kernel/fs/fatfs.c
Normal file
139
kernel/fs/fatfs.c
Normal file
@@ -0,0 +1,139 @@
|
||||
#include <desc.h>
|
||||
#include <fs/fat1.h>
|
||||
#include <fs/fatfs.h>
|
||||
#include <fs/fatfs_ctx.h>
|
||||
#include <fs/path.h>
|
||||
#include <fs/vfs.h>
|
||||
#include <libk/align.h>
|
||||
#include <libk/minmax.h>
|
||||
#include <libk/printf.h>
|
||||
#include <libk/std.h>
|
||||
#include <libk/string.h>
|
||||
#include <mm/liballoc.h>
|
||||
#include <path_defs.h>
|
||||
#include <status.h>
|
||||
#include <sys/debug.h>
|
||||
#include <xdrv_device.h>
|
||||
|
||||
static int fat1_diskio_read (struct fatfs_ctx* ctx, uint32_t sector, uint8_t* buffer,
|
||||
uint32_t sector_count) {
|
||||
struct vfs_volume* volume = ctx->udata;
|
||||
struct device* back_device = volume->back_device;
|
||||
|
||||
size_t sector_size;
|
||||
size_t phys_sector, phys_sector_count;
|
||||
int ret;
|
||||
|
||||
spin_lock (&back_device->lock);
|
||||
|
||||
ret = device_op (back_device, XDRV_GET_SECTOR_SIZE, NULL, NULL, §or_size);
|
||||
if (ret < 0) {
|
||||
spin_unlock (&back_device->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vfs_translate (sector, sector_count, FAT_SECTOR_SIZE, sector_size, &phys_sector,
|
||||
&phys_sector_count);
|
||||
|
||||
ret = device_op (back_device, XDRV_READ, NULL, NULL, &phys_sector, &phys_sector_count, buffer);
|
||||
if (ret < 0) {
|
||||
spin_unlock (&back_device->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
spin_unlock (&back_device->lock);
|
||||
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fatfs_mount (struct vfs_volume* volume, struct proc* proc, struct reschedule_ctx* rctx) {
|
||||
(void)proc, (void)rctx;
|
||||
|
||||
struct fatfs_ctx* fatfs_ctx = malloc (sizeof (*fatfs_ctx));
|
||||
|
||||
if (fatfs_ctx == NULL)
|
||||
return -ST_OOM_ERROR;
|
||||
|
||||
memset (fatfs_ctx, 0, sizeof (*fatfs_ctx));
|
||||
fl_attach_media (fatfs_ctx, &fat1_diskio_read, NULL);
|
||||
|
||||
fatfs_ctx->udata = volume;
|
||||
volume->udata = fatfs_ctx;
|
||||
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
int fatfs_describe (struct vfs_volume* volume, const char* path, struct desc* desc) {
|
||||
struct fatfs_ctx* fatfs_ctx = volume->udata;
|
||||
|
||||
if (fl_is_dir (fatfs_ctx, path)) {
|
||||
FL_DIR dir;
|
||||
|
||||
if (fl_opendir (fatfs_ctx, path, &dir) == NULL)
|
||||
return -ST_NOT_FOUND;
|
||||
|
||||
desc->type = FS_DIR;
|
||||
desc->size = 0;
|
||||
|
||||
fl_dirent dirent;
|
||||
while (fl_readdir (fatfs_ctx, &dir, &dirent) == 0)
|
||||
desc->size++;
|
||||
|
||||
fl_closedir (fatfs_ctx, &dir);
|
||||
} else {
|
||||
FL_FILE* file = fl_fopen (fatfs_ctx, path, "r");
|
||||
|
||||
if (file == NULL)
|
||||
return -ST_NOT_FOUND;
|
||||
|
||||
desc->type = FS_FILE;
|
||||
desc->size = file->filelength;
|
||||
|
||||
fl_fclose (fatfs_ctx, file);
|
||||
}
|
||||
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
int fatfs_read (struct vfs_volume* volume, const char* path, uint8_t* buffer, size_t off,
|
||||
size_t size) {
|
||||
struct fatfs_ctx* fatfs_ctx = volume->udata;
|
||||
|
||||
FL_FILE* file = fl_fopen (fatfs_ctx, path, "wb+");
|
||||
|
||||
if (file == NULL)
|
||||
return -ST_NOT_FOUND;
|
||||
|
||||
fl_fseek (fatfs_ctx, file, off, SEEK_SET);
|
||||
fl_fread (fatfs_ctx, buffer, 1, size, file);
|
||||
|
||||
fl_fclose (fatfs_ctx, file);
|
||||
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
int fatfs_read_dir_entry (struct vfs_volume* volume, const char* path, struct dir_entry* entry,
|
||||
size_t entry_num) {
|
||||
struct fatfs_ctx* fatfs_ctx = volume->udata;
|
||||
FL_DIR dir;
|
||||
|
||||
if (fl_opendir (fatfs_ctx, path, &dir) == NULL)
|
||||
return -ST_NOT_FOUND;
|
||||
|
||||
fl_dirent dirent;
|
||||
size_t dirent_num = 0;
|
||||
while (fl_readdir (fatfs_ctx, &dir, &dirent) == 0) {
|
||||
if (dirent_num == entry_num) {
|
||||
strncat (entry->path, path, PATH_MAX);
|
||||
strncat (entry->path, dirent.filename, PATH_MAX);
|
||||
break;
|
||||
}
|
||||
|
||||
dirent_num++;
|
||||
}
|
||||
|
||||
fl_closedir (fatfs_ctx, &dir);
|
||||
return ST_OK;
|
||||
}
|
||||
23
kernel/fs/fatfs.h
Normal file
23
kernel/fs/fatfs.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef _KERNEL_FS_FATFS_H
|
||||
#define _KERNEL_FS_FATFS_H
|
||||
|
||||
#include <desc.h>
|
||||
#include <device/device.h>
|
||||
#include <dir_entry.h>
|
||||
#include <libk/std.h>
|
||||
#include <proc/proc.h>
|
||||
#include <proc/reschedule.h>
|
||||
|
||||
struct vfs_volume;
|
||||
|
||||
int fatfs_mount (struct vfs_volume* volume, struct proc* proc, struct reschedule_ctx* rctx);
|
||||
|
||||
int fatfs_describe (struct vfs_volume* volume, const char* path, struct desc* desc);
|
||||
|
||||
int fatfs_read (struct vfs_volume* volume, const char* path, uint8_t* buffer, size_t off,
|
||||
size_t size);
|
||||
|
||||
int fatfs_read_dir_entry (struct vfs_volume* volume, const char* path, struct dir_entry* entry,
|
||||
size_t entry_num);
|
||||
|
||||
#endif // _KERNEL_FS_FATFS_H
|
||||
14
kernel/fs/fatfs_ctx.h
Normal file
14
kernel/fs/fatfs_ctx.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef _KERNEL_FS_FATFS_CTX_H
|
||||
#define _KERNEL_FS_FATFS_CTX_H
|
||||
|
||||
struct fatfs_ctx {
|
||||
FL_FILE _files[FATFS_MAX_OPEN_FILES];
|
||||
int _filelib_init;
|
||||
int _filelib_valid;
|
||||
struct fatfs _fs;
|
||||
struct fat_list _open_file_list;
|
||||
struct fat_list _free_file_list;
|
||||
void* udata;
|
||||
};
|
||||
|
||||
#endif // _KERNEL_FS_FATFS_CTX_H
|
||||
@@ -1,7 +1,11 @@
|
||||
c += fs/vfs.c \
|
||||
fs/tarfs.c \
|
||||
fs/path.c
|
||||
fs/path.c \
|
||||
fs/fat1.c \
|
||||
fs/fatfs.c
|
||||
|
||||
o += fs/vfs.o \
|
||||
fs/tarfs.o \
|
||||
fs/path.o
|
||||
fs/path.o \
|
||||
fs/fat1.o \
|
||||
fs/fatfs.o
|
||||
|
||||
@@ -71,15 +71,14 @@ int tarfs_mount (struct vfs_volume* volume, struct proc* proc, struct reschedule
|
||||
|
||||
spin_lock (&back_device->lock);
|
||||
|
||||
ret = back_device->ops[XDRV_GET_SIZE](back_device, proc, rctx, &total_size, NULL, NULL, NULL);
|
||||
ret = device_op (back_device, XDRV_GET_SIZE, proc, rctx, &total_size);
|
||||
if (ret < 0) {
|
||||
spin_unlock (&back_device->lock);
|
||||
free (volume->udata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = back_device->ops[XDRV_GET_SECTOR_SIZE](back_device, proc, rctx, §or_size, NULL, NULL,
|
||||
NULL);
|
||||
ret = device_op (back_device, XDRV_GET_SECTOR_SIZE, proc, rctx, §or_size);
|
||||
if (ret < 0) {
|
||||
spin_unlock (&back_device->lock);
|
||||
free (volume->udata);
|
||||
@@ -94,10 +93,10 @@ int tarfs_mount (struct vfs_volume* volume, struct proc* proc, struct reschedule
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t off = 0;
|
||||
size_t sector_count = 1;
|
||||
for (size_t sector = 0; sector < total_size / sector_size; sector++) {
|
||||
uint8_t* dest = (uint8_t*)((uintptr_t)buffer + (sector * sector_size));
|
||||
ret = back_device->ops[XDRV_READ](back_device, proc, rctx, §or, &off, §or_size, dest);
|
||||
ret = device_op (back_device, XDRV_READ, proc, rctx, §or, §or_count, dest);
|
||||
}
|
||||
|
||||
spin_unlock (&back_device->lock);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include <device/device.h>
|
||||
#include <fs/fat1.h>
|
||||
#include <fs/fatfs.h>
|
||||
#include <fs/tarfs.h>
|
||||
#include <fs/vfs.h>
|
||||
#include <id/id_alloc.h>
|
||||
@@ -52,16 +54,21 @@ int vfs_create_volume (const char* key, int fs_type, struct device* back_device,
|
||||
volume->lock = SPIN_LOCK_INIT;
|
||||
|
||||
switch (volume->fs_type) {
|
||||
case VFS_TARFS: {
|
||||
case VFS_TARFS:
|
||||
volume->driver_ops.mount = &tarfs_mount;
|
||||
volume->driver_ops.describe = &tarfs_describe;
|
||||
volume->driver_ops.read = &tarfs_read;
|
||||
volume->driver_ops.read_dir_entry = &tarfs_read_dir_entry;
|
||||
} break;
|
||||
default: {
|
||||
break;
|
||||
case VFS_FAT16:
|
||||
volume->driver_ops.mount = &fatfs_mount;
|
||||
volume->driver_ops.describe = &fatfs_describe;
|
||||
volume->driver_ops.read = &fatfs_read;
|
||||
volume->driver_ops.read_dir_entry = &fatfs_read_dir_entry;
|
||||
break;
|
||||
default:
|
||||
free (volume);
|
||||
return -ST_MOUNT_ERROR;
|
||||
} break;
|
||||
}
|
||||
|
||||
int ret = volume->driver_ops.mount (volume, proc, rctx);
|
||||
@@ -208,3 +215,14 @@ void vfs_init (void) {
|
||||
|
||||
volume_table.lock = SPIN_LOCK_INIT;
|
||||
}
|
||||
|
||||
void vfs_translate (size_t fs_block, size_t fs_block_count, size_t fs_block_size,
|
||||
size_t device_sector_size, size_t* out_phys_sector, size_t* out_sector_count) {
|
||||
size_t ratio = fs_block_size / device_sector_size;
|
||||
|
||||
if (out_phys_sector != NULL)
|
||||
*out_phys_sector = fs_block * ratio;
|
||||
|
||||
if (out_sector_count != NULL)
|
||||
*out_sector_count = fs_block_count * ratio;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#define VFS_KERNEL ((struct proc*)0x123)
|
||||
|
||||
#define VFS_TARFS 0
|
||||
#define VFS_FAT16 1
|
||||
#define VFS_FAT32 2
|
||||
|
||||
struct vfs_volume;
|
||||
|
||||
@@ -66,4 +68,7 @@ int vfs_read_dir_entry (struct proc* proc, const char* volume, const char* path,
|
||||
|
||||
void vfs_init (void);
|
||||
|
||||
void vfs_translate (size_t fs_block, size_t fs_block_count, size_t fs_block_size,
|
||||
size_t device_sector_size, size_t* out_phys_sector, size_t* out_sector_count);
|
||||
|
||||
#endif // _KERNEL_FS_VFS_H
|
||||
|
||||
@@ -11,7 +11,8 @@ cflags += -nostdinc \
|
||||
cflags += -isystem . -isystem ../include
|
||||
|
||||
cflags += -DPRINTF_INCLUDE_CONFIG_H=1 \
|
||||
-D_ALLOC_SKIP_DEFINE
|
||||
-D_ALLOC_SKIP_DEFINE \
|
||||
-D"FAT_PRINTF(a)"
|
||||
|
||||
ifeq ($(buildtype),debug)
|
||||
cflags += -O0 -g
|
||||
|
||||
@@ -65,3 +65,30 @@ int strcmp (const char* s1, const char* s2) {
|
||||
}
|
||||
return *(const unsigned char*)s1 - *(const unsigned char*)s2;
|
||||
}
|
||||
|
||||
/* https://stackoverflow.com/a/2490637 */
|
||||
char* strcat (char* dest, const char* src) {
|
||||
char* rdest = dest;
|
||||
|
||||
while (*dest)
|
||||
dest++;
|
||||
|
||||
while ((*dest++ = *src++))
|
||||
;
|
||||
|
||||
return rdest;
|
||||
}
|
||||
|
||||
char* strncat (char* dest, const char* src, size_t n) {
|
||||
char* ptr = dest;
|
||||
while (*ptr != '\0')
|
||||
ptr++;
|
||||
|
||||
while (n > 0 && *src != '\0') {
|
||||
*ptr++ = *src++;
|
||||
n--;
|
||||
}
|
||||
|
||||
*ptr = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ size_t strlen (const char* str);
|
||||
int memcmp (const void* s1, const void* s2, size_t n);
|
||||
int strncmp (const char* s1, const char* s2, size_t n);
|
||||
int strcmp (const char* s1, const char* s2);
|
||||
char* strncat (char* dest, const char* src, size_t n);
|
||||
|
||||
#define strlen_null(x) (strlen ((x)) + 1)
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ DEFINE_SYSCALL (sys_device_do) {
|
||||
|
||||
spin_lock (&device->lock);
|
||||
|
||||
int ret = device->ops[cmd](device, proc, rctx, (void*)ka1, (void*)ka2, (void*)ka3, (void*)ka4);
|
||||
int ret = device_op (device, cmd, proc, rctx, ka1, ka2, ka3, ka4);
|
||||
|
||||
spin_unlock (&device->lock);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user