Fix FAT driver issues (FAT32 while being under 32MiB), liballoc alignment so SSE doesnt break

This commit is contained in:
2026-03-10 21:01:49 +01:00
parent 38557bab7d
commit 4b099f04f5
27 changed files with 3447 additions and 18 deletions

View File

@@ -14,3 +14,4 @@ include make/libaux.mk
include make/libarena.mk include make/libarena.mk
include make/libioutil.mk include make/libioutil.mk
include make/libmath.mk include make/libmath.mk
include make/libfat.mk

View File

@@ -13,3 +13,4 @@ make -B all_compiledb_libaux
make -B all_compiledb_libarena make -B all_compiledb_libarena
make -B all_compiledb_libioutil make -B all_compiledb_libioutil
make -B all_compiledb_libmath make -B all_compiledb_libmath
make -B all_compiledb_libfat

View File

@@ -20,6 +20,7 @@ make -B all_libaux "$bt"
make -B all_libarena "$bt" make -B all_libarena "$bt"
make -B all_libioutil "$bt" make -B all_libioutil "$bt"
make -B all_libmath "$bt" make -B all_libmath "$bt"
make -B all_libfat "$bt"
make -B all_apps "$bt" make -B all_apps "$bt"
make -B all_dist make -B all_dist
./aux/limine_iso_amd64.sh ./aux/limine_iso_amd64.sh

View File

@@ -14,5 +14,6 @@ make -B docs_libaux
make -B docs_libarena make -B docs_libarena
make -B docs_libioutil make -B docs_libioutil
make -B docs_libmath make -B docs_libmath
make -B docs_libfat
mkdocs build mkdocs build

View File

@@ -13,4 +13,5 @@ make -B format_libaux
make -B format_libarena make -B format_libarena
make -B format_libioutil make -B format_libioutil
make -B format_libmath make -B format_libmath
make -B format_libfat
make -B format_apps make -B format_apps

View File

@@ -64,7 +64,9 @@ static void mkfile (struct context* context, char** file_paths, size_t files_cou
continue; continue;
} }
create_file (path); if ((ret = create_file (path)) < 0) {
cprintf (context, "ERROR could not create file '%s': %s\n", file_path, str_status[-ret]);
}
volume_close (); volume_close ();
} }
@@ -284,14 +286,14 @@ static void mkvol (struct context* context, const char* volume, const char* str_
} else if (strcmp (str_fs_type, "fat32") == 0) { } else if (strcmp (str_fs_type, "fat32") == 0) {
fs_type = FS_FAT32; fs_type = FS_FAT32;
} else { } else {
cprintf (context, "Unknown filesystem '%s'\n", str_fs_type); cprintf (context, "ERROR Unknown filesystem '%s'\n", str_fs_type);
return; return;
} }
int ret = create_volume (volume, fs_type, device); int ret = create_volume (volume, fs_type, device);
if (ret < 0) if (ret < 0)
cprintf (context, "Could not create volume: %s\n", str_status[-ret]); cprintf (context, "ERROR Could not create volume: %s\n", str_status[-ret]);
} }
static void help (struct context* context) { static void help (struct context* context) {

View File

@@ -67,7 +67,7 @@ void bootmain (void) {
device_probe_partitions (temp); device_probe_partitions (temp);
struct device* tempp0 = device_find ("TEMPp0"); struct device* tempp0 = device_find ("TEMPp0");
vfs_create_volume ("TEMP", FS_FAT32, tempp0, true); int x = vfs_create_volume ("TEMP", FS_FAT16, tempp0, true);
proc_pid_alloc_init (); proc_pid_alloc_init ();
procgroup_pgid_alloc_init (); procgroup_pgid_alloc_init ();

View File

@@ -3,17 +3,22 @@
#define fx_save(buf) \ #define fx_save(buf) \
do { \ do { \
__asm__ volatile ("fxsave64 (%0)" ::"r"((buf)) : "memory"); \ __asm__ volatile ("fxsave64 %0" : "=m"(*(buf))::"memory"); \
} while (0) } while (0)
#define fx_restore(buf) \ #define fx_restore(buf) \
do { \ do { \
__asm__ volatile ("fxrstor64 (%0)" ::"r"((buf)) : "memory"); \ __asm__ volatile ("fxrstor64 %0" ::"m"(*(buf)) : "memory"); \
} while (0) } while (0)
#define fx_init(buf) \ #define fx_init(buf) \
do { \ do { \
__asm__ volatile ("fninit; fxsave64 (%0)" ::"r"((buf)) : "memory"); \ memset ((buf), 0, sizeof ((buf))); \
__asm__ volatile ("fninit; fxsave64 %0" : "=m"(*(buf))::"memory"); \
uint32_t* __mxcsr = (uint32_t*)&(buf)[24]; \
*__mxcsr = 0x1F80; \
uint16_t* __fcw = (uint16_t*)&(buf)[0]; \
*__fcw = 0x037F; \
} while (0) } while (0)
#endif // _KERNEL_AMD64_FX_H #endif // _KERNEL_AMD64_FX_H

View File

@@ -14,11 +14,11 @@
/* Platform-dependent process data */ /* Platform-dependent process data */
struct proc_platformdata { struct proc_platformdata {
uint8_t fx_env[512] ALIGNED (16);
struct saved_regs regs; struct saved_regs regs;
uintptr_t kernel_stack; uintptr_t kernel_stack;
uint64_t fs_base; uint64_t fs_base;
uintptr_t tls_vaddr; uintptr_t tls_vaddr;
uint8_t fx_env[512] ALIGNED (16);
}; };
#endif // _KERNEL_AMD64_PROC_H #endif // _KERNEL_AMD64_PROC_H

View File

@@ -1,5 +1,4 @@
#include <device/device.h> #include <device/device.h>
#include <device/dos.h>
#include <device/partdrv.h> #include <device/partdrv.h>
#include <device/partitions.h> #include <device/partitions.h>
#include <device/pci.h> #include <device/pci.h>

View File

@@ -1,4 +0,0 @@
#ifndef _KERNEL_DEVICE_DOS_H
#define _KERNEL_DEVICE_DOS_H
#endif // _KERNEL_DEVICE_DOS_H

View File

@@ -1,6 +1,7 @@
#include <amd64/io.h> #include <amd64/io.h>
#include <device/device.h> #include <device/device.h>
#include <device/idedrv.h> #include <device/idedrv.h>
#include <device/partitions.h>
#include <devices.h> #include <devices.h>
#include <libk/std.h> #include <libk/std.h>
#include <mm/liballoc.h> #include <mm/liballoc.h>
@@ -183,6 +184,8 @@ bool idedrv_init (struct device* device, void* arg) {
device->udata = idedrv; device->udata = idedrv;
device_probe_partitions (device);
return true; return true;
} }

View File

@@ -1,6 +1,7 @@
/* liballoc breaks when optimized too aggressively, for eg. clang's -Oz */ /* liballoc breaks when optimized too aggressively, for eg. clang's -Oz */
#pragma clang optimize off #pragma clang optimize off
#include <libk/align.h>
#include <limine/requests.h> #include <limine/requests.h>
#include <mm/liballoc.h> #include <mm/liballoc.h>
#include <mm/pmm.h> #include <mm/pmm.h>
@@ -240,6 +241,8 @@ static struct boundary_tag* allocate_new_tag (unsigned int size) {
} }
void* malloc (size_t size) { void* malloc (size_t size) {
size = align_up (size, 16);
int index; int index;
void* ptr; void* ptr;
struct boundary_tag* tag = NULL; struct boundary_tag* tag = NULL;

View File

@@ -1,6 +1,7 @@
#ifndef _LIBALLOC_H #ifndef _LIBALLOC_H
#define _LIBALLOC_H #define _LIBALLOC_H
#include <aux/compiler.h>
#include <libk/std.h> #include <libk/std.h>
// If we are told to not define our own size_t, then we // If we are told to not define our own size_t, then we
@@ -38,7 +39,7 @@ struct boundary_tag {
struct boundary_tag* next; //< Linked list info. struct boundary_tag* next; //< Linked list info.
struct boundary_tag* prev; //< Linked list info. struct boundary_tag* prev; //< Linked list info.
}; } ALIGNED (16);
/** This function is supposed to lock the memory data structures. It /** This function is supposed to lock the memory data structures. It
* could be as simple as disabling interrupts or acquiring a spinlock. * could be as simple as disabling interrupts or acquiring a spinlock.

View File

@@ -217,6 +217,8 @@ static struct boundary_tag* allocate_new_tag (unsigned int size) {
} }
void* malloc (size_t size) { void* malloc (size_t size) {
size = (size + 15) & ~15;
int index; int index;
void* ptr; void* ptr;
struct boundary_tag* tag = NULL; struct boundary_tag* tag = NULL;

View File

@@ -41,7 +41,7 @@ struct boundary_tag {
struct boundary_tag* next; //< Linked list info. struct boundary_tag* next; //< Linked list info.
struct boundary_tag* prev; //< Linked list info. struct boundary_tag* prev; //< Linked list info.
}; } __attribute__ ((aligned (16)));
/** This function is supposed to lock the memory data structures. It /** This function is supposed to lock the memory data structures. It
* could be as simple as disabling interrupts or acquiring a spinlock. * could be as simple as disabling interrupts or acquiring a spinlock.

4
libfat/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
*.o
*.json
docs/
.cache/

10
libfat/Makefile Normal file
View File

@@ -0,0 +1,10 @@
include ../make/ufuncs.mk
$(eval $(call add_include,libsystem))
$(eval $(call add_lib,libstring))
cflags += -D"FAT_PRINTF(a)"
libname := libfat
include ../make/lib.mk

2899
libfat/_fat.c Normal file

File diff suppressed because it is too large Load Diff

451
libfat/_fat.h Normal file
View 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

13
libfat/_fatctx.h Normal file
View File

@@ -0,0 +1,13 @@
#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;
};
#endif // _KERNEL_FS_FATFS_CTX_H

1
libfat/build/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.a

3
libfat/libfat.c Normal file
View File

@@ -0,0 +1,3 @@
#include <libfat.h>
int a;

4
libfat/libfat.h Normal file
View File

@@ -0,0 +1,4 @@
#ifndef _LIBFAT_LIBFAT_H
#define _LIBFAT_LIBFAT_H
#endif // _LIBFAT_LIBFAT_H

5
libfat/src.mk Normal file
View File

@@ -0,0 +1,5 @@
c += _fat.c \
libfat.c
o += _fat.o \
libfat.o

16
make/libfat.mk Normal file
View File

@@ -0,0 +1,16 @@
all_libfat:
make -C libfat platform=$(platform) all
all_compiledb_libfat:
bear --output libfat/compile_commands.json -- make -C libfat platform=$(platform) all
clean_libfat:
make -C libfat platform=$(platform) clean
format_libfat:
make -C libfat platform=$(platform) format
docs_libfat:
make -C libfat platform=$(platform) docs
.PHONY: all_libfat clean_libfat format_libfat docs_libfat all_compiledb_libfat

View File

@@ -1,5 +1,12 @@
#!/bin/sh #!/bin/sh
# 50MiB set -xe
dd if=/dev/zero of=./test_drive.img bs=512 count=102400
mkfs.vfat -F 32 ./test_drive.img rm -f test_drive.img
dd if=/dev/zero of=test_drive.img bs=1M count=128
parted test_drive.img --script mklabel msdos
parted test_drive.img --script mkpart primary fat32 1MiB 128MiB
mkfs.vfat -F 32 --offset 2048 test_drive.img