From 7cc35984e4ab32af12c5cefd9a624f54d2ef0242 Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Sun, 5 Jan 2020 09:00:43 +0100 Subject: [PATCH] Add VFS + custom RAM FS + SMEM file primitives (read only) --- $ | 41 ++++++ include/kernel/fs/file.h | 15 +- include/kernel/fs/filesystem.h | 104 ++++++++++++++ include/kernel/fs/gladfs.h | 81 +++++++++++ include/kernel/fs/{smem.h => smemfs.h} | 39 ++++-- include/kernel/fs/stat.h | 45 ++++++ include/kernel/fs/vfs.h | 37 +++++ include/kernel/types.h | 3 + include/kernel/unistd_32.h | 38 +++-- include/kernel/util.h | 4 + include/lib/unistd.h | 8 +- src/kernel/bootstrap/start.c | 58 +++++++- src/kernel/fs/gladfs/file/file_pos.c | 34 +++++ src/kernel/fs/gladfs/file/read.c | 65 +++++++++ src/kernel/fs/gladfs/file/write.c | 93 +++++++++++++ src/kernel/fs/gladfs/filesystem/mount.c | 25 ++++ src/kernel/fs/gladfs/filesystem/umount.c | 7 + src/kernel/fs/gladfs/initialize.c | 60 ++++++++ src/kernel/fs/gladfs/inode/creat.c | 30 ++++ src/kernel/fs/gladfs/inode/find_first_child.c | 8 ++ .../fs/gladfs/inode/find_next_sibling.c | 8 ++ src/kernel/fs/gladfs/inode/find_parent.c | 8 ++ src/kernel/fs/gladfs/inode/get_mode.c | 6 + src/kernel/fs/gladfs/inode/get_name.c | 17 +++ src/kernel/fs/gladfs/inode/mkdir.c | 30 ++++ .../fs/gladfs/superblock/alloc_fragdata.c | 22 +++ src/kernel/fs/gladfs/superblock/alloc_inode.c | 25 ++++ .../fs/gladfs/superblock/destroy_fragdata.c | 13 ++ .../fs/gladfs/superblock/destroy_inode.c | 28 ++++ src/kernel/fs/smem/lseek.c | 24 ---- src/kernel/fs/smem/mount.c | 25 ---- src/kernel/fs/smem/open.c | 130 ------------------ src/kernel/fs/{smem => smemfs/file}/read.c | 28 ++-- src/kernel/fs/smemfs/filesystem/mount.c | 10 ++ src/kernel/fs/smemfs/initialize.c | 77 +++++++++++ src/kernel/fs/smemfs/inode/find_first_child.c | 32 +++++ .../fs/smemfs/inode/find_next_sibling.c | 26 ++++ src/kernel/fs/smemfs/inode/find_parent.c | 21 +++ src/kernel/fs/smemfs/inode/get_mode.c | 32 +++++ src/kernel/fs/smemfs/inode/get_name.c | 39 ++++++ src/kernel/fs/smemfs/inode/walk.c | 42 ++++++ src/kernel/fs/syscall/open.c | 16 +++ src/kernel/fs/vfs/dentry/find_first_child.c | 76 ++++++++++ src/kernel/fs/vfs/dentry/find_next_sibling.c | 49 +++++++ src/kernel/fs/vfs/dentry/resolve.c | 90 ++++++++++++ src/kernel/fs/vfs/file/lseek.c | 28 ++++ src/kernel/fs/vfs/file/open.c | 27 ++++ src/kernel/fs/vfs/file/read.c | 22 +++ src/kernel/fs/vfs/file/write.c | 21 +++ src/kernel/fs/vfs/inode/mkdir.c | 56 ++++++++ src/kernel/fs/vfs/register.c | 18 +++ src/kernel/fs/vfs/superblock/mount.c | 95 +++++++++++++ src/kernel/loader/entry.c | 6 +- src/kernel/loader/header.c | 4 +- src/kernel/loader/image.c | 14 +- src/kernel/syscall/handler.c | 14 +- src/kernel/util/printk.c | 9 ++ src/kernel/util/string.c | 49 +++++++ src/kernel/vhex.ld | 12 +- src/lib/string/strchr.c | 31 +++++ src/lib/unistd/close.S | 12 ++ src/lib/unistd/lseek.S | 12 ++ src/lib/unistd/open.S | 12 ++ src/lib/unistd/read.S | 12 ++ src/lib/unistd/write.S | 12 ++ src/user/shell/main.c | 64 +++++---- 66 files changed, 1923 insertions(+), 276 deletions(-) create mode 100644 $ create mode 100644 include/kernel/fs/filesystem.h create mode 100644 include/kernel/fs/gladfs.h rename include/kernel/fs/{smem.h => smemfs.h} (78%) create mode 100644 include/kernel/fs/stat.h create mode 100644 include/kernel/fs/vfs.h create mode 100644 src/kernel/fs/gladfs/file/file_pos.c create mode 100644 src/kernel/fs/gladfs/file/read.c create mode 100644 src/kernel/fs/gladfs/file/write.c create mode 100644 src/kernel/fs/gladfs/filesystem/mount.c create mode 100644 src/kernel/fs/gladfs/filesystem/umount.c create mode 100644 src/kernel/fs/gladfs/initialize.c create mode 100644 src/kernel/fs/gladfs/inode/creat.c create mode 100644 src/kernel/fs/gladfs/inode/find_first_child.c create mode 100644 src/kernel/fs/gladfs/inode/find_next_sibling.c create mode 100644 src/kernel/fs/gladfs/inode/find_parent.c create mode 100644 src/kernel/fs/gladfs/inode/get_mode.c create mode 100644 src/kernel/fs/gladfs/inode/get_name.c create mode 100644 src/kernel/fs/gladfs/inode/mkdir.c create mode 100644 src/kernel/fs/gladfs/superblock/alloc_fragdata.c create mode 100644 src/kernel/fs/gladfs/superblock/alloc_inode.c create mode 100644 src/kernel/fs/gladfs/superblock/destroy_fragdata.c create mode 100644 src/kernel/fs/gladfs/superblock/destroy_inode.c delete mode 100644 src/kernel/fs/smem/lseek.c delete mode 100644 src/kernel/fs/smem/mount.c delete mode 100644 src/kernel/fs/smem/open.c rename src/kernel/fs/{smem => smemfs/file}/read.c (74%) create mode 100644 src/kernel/fs/smemfs/filesystem/mount.c create mode 100644 src/kernel/fs/smemfs/initialize.c create mode 100644 src/kernel/fs/smemfs/inode/find_first_child.c create mode 100644 src/kernel/fs/smemfs/inode/find_next_sibling.c create mode 100644 src/kernel/fs/smemfs/inode/find_parent.c create mode 100644 src/kernel/fs/smemfs/inode/get_mode.c create mode 100644 src/kernel/fs/smemfs/inode/get_name.c create mode 100644 src/kernel/fs/smemfs/inode/walk.c create mode 100644 src/kernel/fs/syscall/open.c create mode 100644 src/kernel/fs/vfs/dentry/find_first_child.c create mode 100644 src/kernel/fs/vfs/dentry/find_next_sibling.c create mode 100644 src/kernel/fs/vfs/dentry/resolve.c create mode 100644 src/kernel/fs/vfs/file/lseek.c create mode 100644 src/kernel/fs/vfs/file/open.c create mode 100644 src/kernel/fs/vfs/file/read.c create mode 100644 src/kernel/fs/vfs/file/write.c create mode 100644 src/kernel/fs/vfs/inode/mkdir.c create mode 100644 src/kernel/fs/vfs/register.c create mode 100644 src/kernel/fs/vfs/superblock/mount.c create mode 100644 src/lib/string/strchr.c create mode 100644 src/lib/unistd/close.S create mode 100644 src/lib/unistd/lseek.S create mode 100644 src/lib/unistd/open.S create mode 100644 src/lib/unistd/read.S create mode 100644 src/lib/unistd/write.S diff --git a/$ b/$ new file mode 100644 index 0000000..c1b5fe1 --- /dev/null +++ b/$ @@ -0,0 +1,41 @@ +#include +#include +#include + +///TODO add flags and mode parameter. +FILE *vfs_file_open(char const *path) +{ + struct dentry *dentry; + FILE *new_file; + + // Get target inode. + dentry = vfs_dentry_resolve(path); + if (dentry == NULL) + { + printk(KERN_DEBUG, "vfs open: inode fault !\n"); + return (NULL); + } + + // Check directory. + // TODO return value ? + // TODO device handling ? + // FIXME: device error !! + //if (inode->type & VFS_INODE_TYPE_PARENT){ + // printk(KERN_DEBUG, "vfs open: file type error !\n"); + // return (NULL); + //} + + // Alloc new FILE. + new_file = pm_heap_alloc(sizeof(FILE)); + if (new_file == NULL) + { + printk(KERN_DEBUG, "vfs open: file alloc error !\n"); + return (NULL); + } + + // Fill new file. + new_file->private = dentry->inode; + new_file->permisssion = 0; //<-- TODO + new_file->cursor = 0; + return (new_file); +} diff --git a/include/kernel/fs/file.h b/include/kernel/fs/file.h index dc31334..15d5a5a 100644 --- a/include/kernel/fs/file.h +++ b/include/kernel/fs/file.h @@ -4,17 +4,26 @@ #include #include #include +#include #ifndef FILE_OPEN_NUMBER # define FILE_OPEN_NUMBER 4 #endif +#define O_RDONLY 0x00 +#define O_WRONLY 0x01 +#define O_RDWR 0x02 + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + struct file_s { - void *abstract; + void *private; off_t cursor; - uint8_t mode; - size_t size; + int permission; + struct file_operations *file_op; }; typedef struct file_s FILE; diff --git a/include/kernel/fs/filesystem.h b/include/kernel/fs/filesystem.h new file mode 100644 index 0000000..15d4f58 --- /dev/null +++ b/include/kernel/fs/filesystem.h @@ -0,0 +1,104 @@ +#ifndef __KERNEL_FS_FS_H__ +# define __KERNEL_FS_FS_H__ + +#include +#include +#include + +// FS flags +#define FS_RDWR (0x01) +#define FS_RDONLY (0x02) +#define FS_NO_DEVICE (0x02) + + +// Internal file operations +struct file_system_operations +{ + void *(*mount)(void); + void *(*umount)(void); +}; + +// Internal super block operations +// TODO +/*struct super_operations +{ + // Inode management part. +// void *(*alloc_inode)(struct super_block *sb); +// void (*destroy_inode)(void *inode); + + // Internal FS primitives +// int (*sync_fs)(struct super_block *sb, int wait); +// int (*statfs) (struct dentry *, struct kstatfs *); +};*/ + +// Internal Inode operations +struct inode_operations +{ + // Inode walk part. + void *(*find_next_sibling)(void *inode); + void *(*find_first_child)(void *inode); + void *(*find_parent)(void *inode); + + // Inode memory part. + void *(*create)(void *parent_inode, char const *name, mode_t mode); + void *(*mkdir)(void *parent_inode, char const *name, mode_t mode); + int (*rmdir)(void *inode); + int (*rename)(void *indde, char const *name); + + // Inode informartions part. + int (*get_name)(void *inode, char *buf, size_t count); + mode_t (*get_mode)(void *inode); +}; + +struct file_operations +{ + ssize_t (*read)(void *inode, void *buf, size_t count, off_t pos); + ssize_t (*write)(void *inode, const void *buf, size_t count, off_t pos); +}; + +// Based on UNIX Kernel 2.6.39 +struct file_system_type +{ + const char *fs_name; + uint8_t fs_flags; + struct file_system_operations filesystem_operations; + struct file_operations file_operations; + struct inode_operations inode_operations; + struct file_system_type *next; +}; + +#define VFS_DENTRY_NAME_LENGHT 24 + +// Used to walk into VFS +struct dentry +{ + // File name. + char name[VFS_DENTRY_NAME_LENGHT]; + + // Internal inode + void *inode; + + // Internal file informations + mode_t mode; + + // Linked list + struct dentry *parent; + struct dentry *child; + struct dentry *next; + + // Mount point + struct { + void *inode; + struct file_operations *file_op; + struct inode_operations *inode_op; + } mnt; + + // Internal dentry openrations + struct { + struct file_operations *file_op; + struct inode_operations *inode_op; + } dentry_op; +}; + + +#endif /*__KERNEL_FS_FS_H__*/ diff --git a/include/kernel/fs/gladfs.h b/include/kernel/fs/gladfs.h new file mode 100644 index 0000000..84d5d55 --- /dev/null +++ b/include/kernel/fs/gladfs.h @@ -0,0 +1,81 @@ +#ifndef __KERNEL_FS_GLADFS_H__ +# define __KERNEL_FS_GLADFS_H__ + +#include +#include +#include + +# define GLADFS_INODE_NAME_LENGHT (16) + +//#define GLADFS_INODE_READ (0x00) +//#define GLADFS_INODE_WRITE (0x01) +//#define GLADFS_INODE_EXEC (0x02) + +#define GLADFS_INODE_TYPE_FILE (0x01) +#define GLADFS_INODE_TYPE_PARENT (0x02) +#define GLADFS_INODE_TYPE_ROOT (0x04) + +struct gladfs_fragment_data_s +{ + uint32_t next; + uint32_t data_size; + uint32_t data_used; + uint32_t data_entry; +}; + +struct gladfs_inode_s +{ + // Internal file informations + char name[GLADFS_INODE_NAME_LENGHT]; + mode_t mode; + + // File organisations + struct gladfs_inode_s *parent; + struct gladfs_inode_s *children; + struct gladfs_inode_s *next; + + // Size / Data informations + size_t size; + uint32_t fragnumber; + struct gladfs_fragment_data_s *fragdata; +}; + +struct gladfs_superblock_s +{ + struct gladfs_inode_s *root_inode; + uint32_t block_size; + struct { + struct gladfs_inode_s *(*alloc_inode)(const char *name, mode_t mode); + int (*destroy_inode)(struct gladfs_inode_s *inode); + int (*alloc_fragdata)(struct gladfs_fragment_data_s **parent, int nb_block); + int (*destroy_fragdata)(struct gladfs_fragment_data_s *parent); + } super_op; +}; + +// Constructor +extern void gladfs_initialize(void); + +// FS openrations +extern void *gladfs_mount(void); +extern int gladfs_umount(void); + +// SuperBlock openrations +extern int gladfs_destroy_inode(struct gladfs_inode_s *inode); +extern struct gladfs_inode_s *gladfs_alloc_inode(const char *name, mode_t mode); +extern int gladfs_alloc_fragdata(struct gladfs_fragment_data_s **parent, int nb_block); +extern int gladfs_destroy_fragdata(struct gladfs_fragment_data_s *fragment); + +// Inode operations +extern void *gladfs_mkdir(void *inode_parent, const char *name, mode_t mode); +extern void *gladfs_creat(void *inode_parent, const char *name, mode_t mode); +extern void *gladfs_find_next_sibling(void *inode); +extern void *gladfs_find_first_child(void *inode); +extern void *gladfs_find_parent(void *inode); +extern int gladfs_get_name(void *inode, char *name, size_t count); +extern mode_t gladfs_get_mode(void *inode); + +// File operations +extern ssize_t gladfs_write(void *inode, const void *buf, size_t count, off_t pos); +extern ssize_t gladfs_read(void *inode, void *buf, size_t count, off_t pos); + +#endif /*__KERNEL_FS_GLADFS_H__*/ diff --git a/include/kernel/fs/smem.h b/include/kernel/fs/smemfs.h similarity index 78% rename from include/kernel/fs/smem.h rename to include/kernel/fs/smemfs.h index ff8c0c0..0c12185 100644 --- a/include/kernel/fs/smem.h +++ b/include/kernel/fs/smemfs.h @@ -6,7 +6,6 @@ #include #include - #define CASIO_SMEM_NAME_LENGHT 12 #define CASIO_SMEM_ROOT_ID 0xffff #define CASIO_SMEM_BLOCK_ENTRY_MAGIC 0x4200 @@ -20,13 +19,6 @@ #define CASIO_SMEM_ROOT_ID 0xffff -#define O_RDONLY 0x00 -#define O_WRONLY 0x01 -#define O_RDWR 0x02 - -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 // typedef struct casio_smem_block_s @@ -80,10 +72,31 @@ typedef struct casio_smem_fragment_s uint8_t fill[12]; // 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ... } casio_smem_fragment_t; -// Primitives -extern int casio_smem_mount(void); -extern int casio_smem_open(FILE *file, char const *name, int mode); -extern ssize_t casio_smem_read(FILE *file, void *buf, size_t count); -extern off_t casio_smem_lseek(FILE *file, off_t offset, int whence); + + +// Internal superblock +struct smemfs_superblock_s +{ + casio_smem_header_t *inode_table; + casio_smem_block_t *sector_table; +}; + +// Constructor +extern void smemfs_initialize(); + + +// Superblock primitives +extern void *smemfs_mount(void); + +// File primitives +extern ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos); + +// Inode primitive +extern void *smemfs_find_first_inode(casio_smem_header_t *inode, uint16_t parent_id); +extern void *smemfs_find_next_sibling(void *inode); +extern void *smemfs_find_first_child(void *inode); +extern void *smemfs_find_parent(void *inode); +extern int smemfs_get_name(void *inode, char *name, size_t count); +extern mode_t smemfs_get_mode(void *inode); #endif /*_CASIO_SMEM_H__*/ diff --git a/include/kernel/fs/stat.h b/include/kernel/fs/stat.h new file mode 100644 index 0000000..43daff8 --- /dev/null +++ b/include/kernel/fs/stat.h @@ -0,0 +1,45 @@ +#ifndef __KERNEL_FS_STAT_H__ +# define __KERNEL_FS_STAT_H__ + +#include +#include + +/* File types. */ +#define __S_IFMT 0170000 /* These bits determine file type. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* Protection bits. */ +#define __S_ISUID 0004000 /* Set user ID on execution. */ +#define __S_ISGID 0002000 /* Set group ID on execution. */ +#define __S_ISVTX 0001000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0000400 /* Read by owner. */ +#define __S_IWRITE 0000200 /* Write by owner. */ +#define __S_IEXEC 0000100 /* Execute by owner. */ + + +#define S_IRUSR __S_IREAD /* Read by owner. */ +#define S_IWUSR __S_IWRITE /* Write by owner. */ +#define S_IXUSR __S_IEXEC /* Execute by owner. */ +/* Read, write, and execute by owner. */ +#define S_IRWXU (__S_IREAD|__S_IWRITE|__S_IEXEC) + +#define S_IRGRP (S_IRUSR >> 3) /* Read by group. */ +#define S_IWGRP (S_IWUSR >> 3) /* Write by group. */ +#define S_IXGRP (S_IXUSR >> 3) /* Execute by group. */ +/* Read, write, and execute by group. */ +#define S_IRWXG (S_IRWXU >> 3) + +#define S_IROTH (S_IRGRP >> 3) /* Read by others. */ +#define S_IWOTH (S_IWGRP >> 3) /* Write by others. */ +#define S_IXOTH (S_IXGRP >> 3) /* Execute by others. */ +/* Read, write, and execute by others. */ +#define S_IRWXO (S_IRWXG >> 3) + + +#endif /*__KERNEL_FS_STAT_H__*/ diff --git a/include/kernel/fs/vfs.h b/include/kernel/fs/vfs.h new file mode 100644 index 0000000..7bdfdeb --- /dev/null +++ b/include/kernel/fs/vfs.h @@ -0,0 +1,37 @@ +#ifndef __KERNEL_FS_VFS_H__ +# define __KERNEL_FS_VFS_H__ + +#include +#include +#include +#include +#include + +// Internal VFS macros +#define VFS_MOUNT_ROOT (-1) + + +// Constructor / destructor +extern int vfs_register_filesystem(struct file_system_type *new); + +// Superblock primitives +extern int vfs_umount(char const *target); +extern int vfs_mount(const char *source, const char *target, + const char *filesystemtype, unsigned long mountflags, + const void *data); + +// Inode operations +extern int vfs_mkdir(const char *pathname, mode_t mode); + +// File operations +extern int vfs_open(FILE *file, const char *pathname, int flags); +extern ssize_t vfs_read(FILE *file, void *buf, size_t count); +extern ssize_t vfs_write(FILE *file, const void *buf, size_t count); +extern off_t vfs_lseek(FILE *file, off_t offset, int whence); + +// Dentry opeations +extern struct dentry *vfs_dentry_find_first_child(struct dentry *dentry); +extern struct dentry *vfs_dentry_find_next_sibling(struct dentry *dentry); +extern struct dentry *vfs_dentry_resolve(const char *path, int mode); + +#endif /*__KERNEL_FS_VFS_H__*/ diff --git a/include/kernel/types.h b/include/kernel/types.h index aa8e77e..9a9a85b 100644 --- a/include/kernel/types.h +++ b/include/kernel/types.h @@ -28,6 +28,9 @@ typedef enum mpu_e typedef int pid_t; +typedef int16_t mode_t; +typedef uint16_t umode_t; + // Force inline function. #define INLINE __attribute__((always_inline)) inline diff --git a/include/kernel/unistd_32.h b/include/kernel/unistd_32.h index 20474e7..e066abd 100644 --- a/include/kernel/unistd_32.h +++ b/include/kernel/unistd_32.h @@ -1,21 +1,33 @@ #ifndef __KERNEL_UNISTD_32_H__ # define __KERNEL_UNISTD_32_H__ -#define __NR_restart_syscall 0 +// Kernel Test +#define __NR_test_syscall 0 + +// Process #define __NR_exit 1 #define __NR_exec 2 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_waitpid 7 +#define __NR_waitpid 3 -// Custom ! -#define __NR_kvram_display 8 -#define __NR_kvram_clear 9 -#define __NR_kvram_print 10 -#define __NR_kvram_ascii 11 -#define __NR_kvram_reverse 12 -#define __NR_kvram_scroll 13 +// VFS +#define __NR_read 4 +#define __NR_write 5 +#define __NR_open 6 +#define __NR_close 7 +#define __NR_lseek 8 + +//-- +// Custom ! +//-- + +// Display +#define __NR_kvram_display 9 +#define __NR_kvram_clear 10 +#define __NR_kvram_print 11 +#define __NR_kvram_ascii 12 +#define __NR_kvram_reverse 13 +#define __NR_kvram_scroll 14 + +//TODO: keyboard #endif /*__KERNEL_UNISTD_32_H__*/ diff --git a/include/kernel/util.h b/include/kernel/util.h index a1d0a0e..5d1dc27 100644 --- a/include/kernel/util.h +++ b/include/kernel/util.h @@ -9,6 +9,10 @@ extern void *memset(void *s, int c, size_t n); extern void *memcpy(void *dest, const void *src, size_t count); extern char *strncpy(char *dest, char const *str, size_t size); extern size_t strnlen(char const *str, size_t maxlen); +extern int strcmp(const char *s1, const char *s2); +extern int strncmp(const char *s1, const char *s2, size_t n); +extern char *strrchr(const char *s1, int c); +extern size_t strlen(char const *str); // Video RAM functions extern void kvram_clear(void); diff --git a/include/lib/unistd.h b/include/lib/unistd.h index 2a9ceb1..7ed0851 100644 --- a/include/lib/unistd.h +++ b/include/lib/unistd.h @@ -8,7 +8,6 @@ // Define syscall LIST #include -extern pid_t fork(void); //TODO: move me #define WNOHANG 0 @@ -16,4 +15,11 @@ extern pid_t fork(void); #define WCONTINUED 2 extern pid_t waitpid(pid_t pid, int *wstatus, int options); +// File syscall +#define O_DIRECT 0 +extern int open(const char *pathname, int flags); // <-- TODO: va_arg +extern ssize_t write(int fd, const void *buf, size_t count); +extern ssize_t read(int fd, void *buf, size_t count); +extern int close(int fd); + #endif /*__LIB_UNISTD_H__*/ diff --git a/src/kernel/bootstrap/start.c b/src/kernel/bootstrap/start.c index adb5c04..59536cc 100644 --- a/src/kernel/bootstrap/start.c +++ b/src/kernel/bootstrap/start.c @@ -6,10 +6,15 @@ #include #include #include +#include +#include +#include //TODO: remove me ! -#include +#include +#include #include +#include // Internal symbols mpu_t current_mpu = MPU_UNKNOWN; @@ -43,6 +48,10 @@ extern void kernel_switch(common_context_t *context); extern mpu_t mpu_get(void); extern int main(void); +// Internal object +extern struct file_system_type gladfs_filesystem; +extern struct file_system_type smemfs_filesystem; + // // rom_explore() - explore all add-in ROM part. @@ -76,6 +85,26 @@ static void section_execute(void *bsection, void *esection) } } +//TEST +void vfs_test(struct dentry *node, int level) +{ + // Check error + if (node == NULL) + return; + + // Space test + for (int i = 0 ; i < level ; i++) + tty_write(" ", 1); + + // display name + tty_write(node->name, strlen(node->name)); + tty_write("\n", 1); + + // Try child and sibling + vfs_test(vfs_dentry_find_first_child(node), level + 1); + vfs_test(vfs_dentry_find_next_sibling(node), level); +} + /* start() - Kernel entry point */ __attribute__((section(".pretext"))) @@ -107,10 +136,6 @@ int start(void) // before switching the VBR. rom_explore(&brom, (int32_t)&srom); - // Mount Casio FS - // TODO: Use Virtual File System ! - casio_smem_mount(); - // Save Casio's hardware context and set // Vhex hardware context. // @note: @@ -126,6 +151,27 @@ int start(void) vhex_context_set(); atomic_end(); + // Internal FS init ! + gladfs_initialize(); + smemfs_initialize(); + + // Initilize Virtual File System + vfs_register_filesystem(&gladfs_filesystem); + vfs_register_filesystem(&smemfs_filesystem); + + // Creat initial file tree + vfs_mount(NULL, NULL, "gladfs", VFS_MOUNT_ROOT, NULL); + vfs_mkdir("/dev", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + vfs_mkdir("/mnt", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + vfs_mkdir("/mnt/smemfs", S_IRUSR | S_IRGRP | S_IROTH); + vfs_mount(NULL, "/mnt/smemfs", "smemfs", /*MS_RDONLY*/0, NULL); + +// extern struct dentry *vfs_root_node; +// tty_open(); +// vfs_test(vfs_root_node->child, 0); +// tty_write("FINI !", 6); +// while (1); + // Create first process: Vhex. pid_t vhex_pid = process_create("Vhex"); process_t *vhex_process = process_get(vhex_pid); @@ -134,7 +180,7 @@ int start(void) vhex_process->context.ssr = atomic_start(); // Load programe. - vhex_process->context.spc = (uint32_t)loader("VHEX/shell.elf", vhex_process); + vhex_process->context.spc = (uint32_t)loader("/mnt/smemfs/VHEX/shell.elf", vhex_process); if (vhex_process->context.spc == 0x00000000) { // Display message. diff --git a/src/kernel/fs/gladfs/file/file_pos.c b/src/kernel/fs/gladfs/file/file_pos.c new file mode 100644 index 0000000..e27f6b5 --- /dev/null +++ b/src/kernel/fs/gladfs/file/file_pos.c @@ -0,0 +1,34 @@ +#include +#include + +struct gladfs_fragment_data_s **gladfs_file_pos(off_t *offset, struct gladfs_inode_s *inode, off_t pos) +{ + struct gladfs_fragment_data_s **fragdata; + uint32_t current_offset; + + // Check first fragment. + fragdata = &inode->fragdata; + if (*fragdata == NULL) + { + *offset = -1; + return (fragdata); + } + + // Check pos + if (pos > inode->size) + pos = inode->size; + + // Get fragment data + current_offset = 0; + while (current_offset + (*fragdata)->data_used < pos) + { + current_offset = current_offset + (*fragdata)->data_used; + fragdata = (void *)&(*fragdata)->next; + } + + // Get offset + *offset = pos - current_offset; + + // Return fragdata + return (fragdata); +} diff --git a/src/kernel/fs/gladfs/file/read.c b/src/kernel/fs/gladfs/file/read.c new file mode 100644 index 0000000..2131785 --- /dev/null +++ b/src/kernel/fs/gladfs/file/read.c @@ -0,0 +1,65 @@ +#include +#include +#include + +// Internal helper +extern struct gladfs_fragment_data_s **gladfs_file_pos(off_t *offset, struct gladfs_inode_s *inode, off_t pos); + +ssize_t gladfs_read(void *inode, void *buf, size_t count, off_t pos) +{ + struct gladfs_fragment_data_s **fragdata; + uint8_t get_next_block; + size_t current_size; + size_t write_size; + off_t offset; + + // Start atomic operations + atomic_start(); + + // Get appropriate data fragment + fragdata = gladfs_file_pos(&offset, inode, pos); + if (fragdata == NULL || *fragdata == NULL) + return (-1); + + // Walk into fragemented data + current_size = 0; + count = count - offset; + while (current_size < count) + { + // Generate writable zone + if ((*fragdata)->data_size - offset >= count - current_size) + { + write_size = count - current_size; + get_next_block = 0; + } else { + write_size = (*fragdata)->data_size - offset; + get_next_block = 1; + } + + // Write data. + memcpy( + (void *)((uint32_t)buf + current_size), + (void *)((uint32_t)(&(*fragdata)->data_entry) + offset), + write_size + ); + + // Update current size and wipe offset + current_size = current_size + write_size; + offset = 0; + + // Get next block if needed + if (get_next_block == 1) + { + // Get next block + fragdata = (void *)&(*fragdata)->next; + if (*fragdata == NULL) + break; + } + } + + // End atomic operations + atomic_end(); + + // Return read bytes + return (current_size); +} diff --git a/src/kernel/fs/gladfs/file/write.c b/src/kernel/fs/gladfs/file/write.c new file mode 100644 index 0000000..c6d64e8 --- /dev/null +++ b/src/kernel/fs/gladfs/file/write.c @@ -0,0 +1,93 @@ +#include +#include +#include + +// Internal helper +extern struct gladfs_fragment_data_s **gladfs_file_pos(off_t *offset, struct gladfs_inode_s *inode, off_t pos); + +ssize_t gladfs_write(void *inode, const void *buf, size_t count, off_t pos) +{ + extern struct gladfs_superblock_s gladfs_superblock; + struct gladfs_fragment_data_s **fragdata; + uint8_t get_next_block; + size_t current_size; + size_t write_size; + off_t offset; + + // Get appropriate data fragment + fragdata = gladfs_file_pos(&offset, inode, pos); + if (fragdata == NULL) + return (-1); + + // Generate new indirect block if needed + if (*fragdata == NULL) + { + // @note: for now, the indirect block allocation is + // not really implemented :( + gladfs_superblock.super_op.alloc_fragdata(fragdata, 1); + if (*fragdata == NULL) + return (-1); + + // Reset offset + offset = 0; + } + + // Debug + kvram_clear(); + printk(0, 0, "Le sexe !"); + printk(0, 1, "offset = %d", offset); + printk(0, 2, "fragdata = %p", *fragdata); + kvram_display(); + DBG_WAIT; + + // Walk into fragemented data + current_size = 0; + count = count - offset; + while (current_size < count) + { + // Generate writable zone + if ((*fragdata)->data_size - offset >= count - current_size) + { + write_size = count - current_size; + get_next_block = 0; + } else { + write_size = (*fragdata)->data_size - offset; + get_next_block = 1; + } + + // Write data. + memcpy( + (void *)((uint32_t)(&(*fragdata)->data_entry) + offset), + (void *)((uint32_t)buf + current_size), + write_size + ); + + // Update fragment / inode informations + ((struct gladfs_inode_s*)inode)->size += write_size; + (*fragdata)->data_used = (*fragdata)->data_used + write_size; + current_size = current_size + write_size; + offset = 0; + + // Get next block if needed + if (get_next_block == 1) + { + // Get next block + fragdata = (void *)&(*fragdata)->next; + if (*fragdata != NULL) + continue; + + // Generate new block + // @note: for now, the indirect block allocation is + // not really implemented :( + gladfs_superblock.super_op.alloc_fragdata(fragdata, 1); + if (*fragdata == NULL) + break; + } + } + + // End atomic operations + atomic_end(); + + // Return written bytes. + return (current_size); +} diff --git a/src/kernel/fs/gladfs/filesystem/mount.c b/src/kernel/fs/gladfs/filesystem/mount.c new file mode 100644 index 0000000..9943f85 --- /dev/null +++ b/src/kernel/fs/gladfs/filesystem/mount.c @@ -0,0 +1,25 @@ +#include +#include + +void *gladfs_mount(void) +{ + extern struct gladfs_superblock_s gladfs_superblock; + + // If already mounted, return the root inode + if (gladfs_superblock.root_inode != NULL) + return (gladfs_superblock.root_inode); + + // Try to create root inode. + gladfs_superblock.root_inode = gladfs_superblock.super_op.alloc_inode("/", GLADFS_INODE_TYPE_ROOT); + if (gladfs_superblock.root_inode == NULL) + { + kvram_clear(); + kvram_print(0, 0, "GladFS: ROOT inode alloc error !"); + kvram_display(); + DBG_WAIT; + return (NULL); + } + + // Return root inode + return (gladfs_superblock.root_inode); +} diff --git a/src/kernel/fs/gladfs/filesystem/umount.c b/src/kernel/fs/gladfs/filesystem/umount.c new file mode 100644 index 0000000..4aef2dc --- /dev/null +++ b/src/kernel/fs/gladfs/filesystem/umount.c @@ -0,0 +1,7 @@ +#include + +int gladfs_umount(void) +{ + // Do nothing for now + return (0); +} diff --git a/src/kernel/fs/gladfs/initialize.c b/src/kernel/fs/gladfs/initialize.c new file mode 100644 index 0000000..e032c44 --- /dev/null +++ b/src/kernel/fs/gladfs/initialize.c @@ -0,0 +1,60 @@ +#include +#include +#include + +// Kernel FS block +struct file_system_type gladfs_filesystem = +{ + // internal informations + .fs_name = "gladfs", + .fs_flags = FS_RDWR | FS_NO_DEVICE, + + // FS specific openrations + .filesystem_operations = { + .mount = &gladfs_mount, + .umount = NULL + }, + + // File operations + .file_operations = { + .read = &gladfs_read, + .write = &gladfs_write + }, + + // Inode operations + .inode_operations = { + // Walk + .find_next_sibling = &gladfs_find_next_sibling, + .find_first_child = &gladfs_find_first_child, + .find_parent = &gladfs_find_parent, + + // Memory + .create = &gladfs_creat, + .mkdir = &gladfs_mkdir, + .rmdir = NULL, + .rename = NULL, + + // Informations + .get_name = &gladfs_get_name, + .get_mode = &gladfs_get_mode + } +}; + +// Internla Glados FS information +struct gladfs_superblock_s gladfs_superblock; + +// Contructor for the superBlock +void gladfs_initialize(void) +{ + // initilaize ROOT inode + gladfs_superblock.root_inode = NULL; + + // Initialize device informations + gladfs_superblock.block_size = PM_BLOCK_SIZE; + + // Iniitlaize superblock openrations + gladfs_superblock.super_op.alloc_inode = &gladfs_alloc_inode; + gladfs_superblock.super_op.destroy_inode = &gladfs_destroy_inode; + gladfs_superblock.super_op.alloc_fragdata = &gladfs_alloc_fragdata; + gladfs_superblock.super_op.destroy_fragdata = &gladfs_destroy_fragdata; +} diff --git a/src/kernel/fs/gladfs/inode/creat.c b/src/kernel/fs/gladfs/inode/creat.c new file mode 100644 index 0000000..1e2abd3 --- /dev/null +++ b/src/kernel/fs/gladfs/inode/creat.c @@ -0,0 +1,30 @@ +#include +#include +#include + +void *gladfs_creat(void *parent_inode, const char *file_name, mode_t mode) +{ + extern struct gladfs_superblock_s gladfs_superblock; + struct gladfs_inode_s *new_inode; + struct gladfs_inode_s *parent; + + // Start atomic operation + atomic_start(); + + // Create new inode + new_inode = gladfs_superblock.super_op.alloc_inode(file_name, mode | __S_IFREG); + if (new_inode == NULL) + return (NULL); + + // Update FHS + parent = parent_inode; + new_inode->parent = parent_inode; + new_inode->next = parent->children; + parent->children = new_inode; + + // Stp atomic operation + atomic_end(); + + // Return inode + return(new_inode); +} diff --git a/src/kernel/fs/gladfs/inode/find_first_child.c b/src/kernel/fs/gladfs/inode/find_first_child.c new file mode 100644 index 0000000..f1e957d --- /dev/null +++ b/src/kernel/fs/gladfs/inode/find_first_child.c @@ -0,0 +1,8 @@ +#include + +void *gladfs_find_first_child(void *inode) +{ + if (inode == NULL) + return (NULL); + return (((struct gladfs_inode_s*)inode)->children); +} diff --git a/src/kernel/fs/gladfs/inode/find_next_sibling.c b/src/kernel/fs/gladfs/inode/find_next_sibling.c new file mode 100644 index 0000000..36ca196 --- /dev/null +++ b/src/kernel/fs/gladfs/inode/find_next_sibling.c @@ -0,0 +1,8 @@ +#include + +void *gladfs_find_next_sibling(void *inode) +{ + if (inode == NULL) + return (NULL); + return (((struct gladfs_inode_s*)inode)->next); +} diff --git a/src/kernel/fs/gladfs/inode/find_parent.c b/src/kernel/fs/gladfs/inode/find_parent.c new file mode 100644 index 0000000..d6b4a09 --- /dev/null +++ b/src/kernel/fs/gladfs/inode/find_parent.c @@ -0,0 +1,8 @@ +#include + +void *gladfs_find_parent(void *inode) +{ + if (inode == NULL) + return (NULL); + return (((struct gladfs_inode_s*)inode)->parent); +} diff --git a/src/kernel/fs/gladfs/inode/get_mode.c b/src/kernel/fs/gladfs/inode/get_mode.c new file mode 100644 index 0000000..a717410 --- /dev/null +++ b/src/kernel/fs/gladfs/inode/get_mode.c @@ -0,0 +1,6 @@ +#include + +mode_t gladfs_get_mode(void *inode) +{ + return (((struct gladfs_inode_s*)inode)->mode); +} diff --git a/src/kernel/fs/gladfs/inode/get_name.c b/src/kernel/fs/gladfs/inode/get_name.c new file mode 100644 index 0000000..83c667d --- /dev/null +++ b/src/kernel/fs/gladfs/inode/get_name.c @@ -0,0 +1,17 @@ +#include +#include + +int gladfs_get_name(void *inode, char *name, size_t count) +{ + // Check potential error + if (inode == NULL || name == NULL) + return (-1); + + // Check count + if (count > GLADFS_INODE_NAME_LENGHT) + count = GLADFS_INODE_NAME_LENGHT; + + // Dump name + strncpy(name, ((struct gladfs_inode_s*)inode)->name, count); + return (0); +} diff --git a/src/kernel/fs/gladfs/inode/mkdir.c b/src/kernel/fs/gladfs/inode/mkdir.c new file mode 100644 index 0000000..4208555 --- /dev/null +++ b/src/kernel/fs/gladfs/inode/mkdir.c @@ -0,0 +1,30 @@ +#include +#include +#include + +void *gladfs_mkdir(void *parent_inode, const char *file_name, mode_t mode) +{ + extern struct gladfs_superblock_s gladfs_superblock; + struct gladfs_inode_s *new_inode; + struct gladfs_inode_s *parent; + + // Start atomic operation + atomic_start(); + + // Create new inode + new_inode = gladfs_superblock.super_op.alloc_inode(file_name, mode | __S_IFDIR); + if (new_inode == NULL) + return (NULL); + + // Update FHS + parent = parent_inode; + new_inode->parent = parent_inode; + new_inode->next = parent->children; + parent->children = new_inode; + + // Stp atomic operation + atomic_end(); + + // Return inode + return(new_inode); +} diff --git a/src/kernel/fs/gladfs/superblock/alloc_fragdata.c b/src/kernel/fs/gladfs/superblock/alloc_fragdata.c new file mode 100644 index 0000000..93fce63 --- /dev/null +++ b/src/kernel/fs/gladfs/superblock/alloc_fragdata.c @@ -0,0 +1,22 @@ +#include +#include + +int gladfs_alloc_fragdata(struct gladfs_fragment_data_s **parent, int nb_block) +{ + extern struct gladfs_superblock_s gladfs_superblock; + + // Check error + if (parent == NULL) + return (-1); + + // Try to alloc block + *parent = pm_alloc(gladfs_superblock.block_size * nb_block); + if (*parent == NULL) + return (-1); + + // Fill default value. + (*parent)->next = 0x00000000; + (*parent)->data_size = gladfs_superblock.block_size * nb_block; + (*parent)->data_used = 0x00000000; + return (0); +} diff --git a/src/kernel/fs/gladfs/superblock/alloc_inode.c b/src/kernel/fs/gladfs/superblock/alloc_inode.c new file mode 100644 index 0000000..c609f99 --- /dev/null +++ b/src/kernel/fs/gladfs/superblock/alloc_inode.c @@ -0,0 +1,25 @@ +#include +#include +#include + +struct gladfs_inode_s *gladfs_alloc_inode(const char *name, mode_t mode) +{ + struct gladfs_inode_s *inode; + + // alloc memory + inode = pm_alloc(sizeof(struct gladfs_inode_s)); + if (inode == NULL) + return (NULL); + + // Fill inode. + memset(inode, 0x00, sizeof(struct gladfs_inode_s)); + strncpy(inode->name, name, GLADFS_INODE_NAME_LENGHT); + inode->mode = mode; + inode->parent = NULL; + inode->children = NULL; + inode->next = NULL; + inode->size = 0; + inode->fragnumber = 0; + inode->fragdata = NULL; + return (inode); +} diff --git a/src/kernel/fs/gladfs/superblock/destroy_fragdata.c b/src/kernel/fs/gladfs/superblock/destroy_fragdata.c new file mode 100644 index 0000000..61807b0 --- /dev/null +++ b/src/kernel/fs/gladfs/superblock/destroy_fragdata.c @@ -0,0 +1,13 @@ +#include +#include + +int gladfs_destroy_fragdata(struct gladfs_fragment_data_s *fragment) +{ + // Check error + if (fragment == NULL) + return (-1); + + // Free'd allocated space + pm_free(fragment); + return (0); +} diff --git a/src/kernel/fs/gladfs/superblock/destroy_inode.c b/src/kernel/fs/gladfs/superblock/destroy_inode.c new file mode 100644 index 0000000..5a32f43 --- /dev/null +++ b/src/kernel/fs/gladfs/superblock/destroy_inode.c @@ -0,0 +1,28 @@ +#include +#include + +int gladfs_destroy_inode(struct gladfs_inode_s *inode) +{ + struct gladfs_fragment_data_s *fragdata; + struct gladfs_fragment_data_s *next; + + // Check error. + if (inode == NULL) + return (-1); + + // Free fragmented data + fragdata = inode->fragdata; + while (fragdata == NULL) + { + // Get next fragement + next = (void *)fragdata->next; + pm_free(fragdata); + + // Update current fragment + fragdata = next; + } + + // Free inode + pm_free(inode); + return (0); +} diff --git a/src/kernel/fs/smem/lseek.c b/src/kernel/fs/smem/lseek.c deleted file mode 100644 index 5eac230..0000000 --- a/src/kernel/fs/smem/lseek.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include - -/* casio_smem_lseek() - File cursor management */ -off_t casio_smem_lseek(FILE *file, off_t offset, int whence) -{ - // Check potential error. - if (file == NULL) - return (-1); - - if (whence == SEEK_SET){ - file->cursor = offset; - return (file->cursor); - } - if (whence == SEEK_CUR){ - file->cursor = file->cursor + offset; - return (file->cursor); - } - if (whence == SEEK_END){ - file->cursor = file->size + offset - 1; - return (file->cursor); - } - return (-1); -} diff --git a/src/kernel/fs/smem/mount.c b/src/kernel/fs/smem/mount.c deleted file mode 100644 index a71a077..0000000 --- a/src/kernel/fs/smem/mount.c +++ /dev/null @@ -1,25 +0,0 @@ -#include - -// Internal symbols -casio_smem_header_t *casio_smem_header_table; -casio_smem_block_t *casio_smem_block_table; -uint16_t current_parent_id; - -/* casio_smem_mount() - Get Block and Preheader Table addresses */ -int casio_smem_mount(void) -{ - // Casio SMEM block table start always at 0xa0270000 - casio_smem_block_table = (void *)0xa0270000; - //TODO: check block table intergrity. - - // Casio SMEM preheader table start always at the end of the block table. - // Normaly start at 0xa0270320 but not always (?) - int i = -1; - while (casio_smem_block_table[++i].magic_start == CASIO_SMEM_BLOCK_ENTRY_MAGIC); - casio_smem_header_table = (void *)&casio_smem_block_table[i]; - - //TODO: check header intergrity ! - - current_parent_id = CASIO_SMEM_ROOT_ID; - return (0); -} diff --git a/src/kernel/fs/smem/open.c b/src/kernel/fs/smem/open.c deleted file mode 100644 index 663b5ad..0000000 --- a/src/kernel/fs/smem/open.c +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include -#include - -//FIXME: find better way to walk into fragment (use ID) -static size_t casio_smem_get_file_size(casio_smem_header_t *file) -{ - casio_smem_fragment_t *fragment; - size_t count; - - count = 0; - fragment = (void *)((uint32_t)file + sizeof(casio_smem_header_t)); - while (fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC) - { - count = count + fragment->data_size + 1; - fragment = fragment + 1; - } - return (count); -} - -/* casio_smem_get_file() - Walk into the Casio's File System and search the target file */ -static casio_smem_header_t *casio_smem_get_file(char const *name, uint16_t *parent_id) -{ - extern casio_smem_header_t *casio_smem_header_table; - casio_smem_fragment_t *fragment; - casio_smem_header_t *header; - int i; - - // Walk into Casio SMEM File System. - header = casio_smem_header_table; - while (header->info == CASIO_SMEM_HEADER_INFO_EXIST || - header->info == CASIO_SMEM_HEADER_INFO_DELETE) - { - // Check new file validity. - if (header->info == CASIO_SMEM_HEADER_INFO_EXIST && - header->parent.id == *parent_id) - { - // Compare File name. - i = -1; - while (++i < 12 && - header->name[i] != 0x0000 && - header->name[i] != 0xffff && - (header->name[i] & 0x00ff) == name[i]); - - // Check error. - if (name[i] == '\0' && - (header->name[i] == 0x0000 || - header->name[i] == 0xffff)) - { - *parent_id = header->id; - return (header); - } - } - - // We need to skip fragmented data - fragment = (void *)((uint32_t)header + sizeof(casio_smem_header_t)); - if (fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC) - { - // The fastest way to skip fragmented data - fragment = (void *)((uint32_t)fragment + - (sizeof(casio_smem_fragment_t) * fragment->frag_total)); - } - - // Get next header. - header = (void *)fragment; - } - return (NULL); -} - -/* casio_smem_open() - Find target file and setup abstraction file structure */ -int casio_smem_open(FILE *file, char const *name, int mode) -{ - extern uint16_t current_parent_id; - casio_smem_header_t *file_raw; - uint16_t parent_id; - char file_name[14]; - int slot_number; - int i; - - // check error. - if (mode != O_RDONLY || name == NULL) - return (-1); - - // Get parent ID. - if (*name == '/') - { - parent_id = CASIO_SMEM_ROOT_ID; - name += 1; - } else { - parent_id = current_parent_id; - } - - // File Systeme walk entry. - while (*name != '\0') - { - // Get current file name. - i = -1; - while (name[++i] != '\0' && name[i] != '/' && i < 14) - file_name[i] = name[i]; - - // Check file name validity. - if (i >= 12 && name[i] != '\0' && name[i] != '/') - return (-1); - - // Update internal informations. - file_name[i] = '\0'; - name = name + i; - - // find the file. - file_raw = casio_smem_get_file(file_name, &parent_id); - if (file_raw == NULL) - return (-1); - - // Directory check - if (name[0] == '/') - { - if (file_raw->type != CASIO_SMEM_HEADER_TYPE_DIRECTORY) - return (-2); - name = name + 1; - } - } - - // Initilaize fiel object - // TODO: Use VFS to do this !! - file->cursor = 0; - file->mode = mode; - file->abstract = file_raw; - file->size = casio_smem_get_file_size(file_raw); - return (0); -} diff --git a/src/kernel/fs/smem/read.c b/src/kernel/fs/smemfs/file/read.c similarity index 74% rename from src/kernel/fs/smem/read.c rename to src/kernel/fs/smemfs/file/read.c index 7e528a7..3907e82 100644 --- a/src/kernel/fs/smem/read.c +++ b/src/kernel/fs/smemfs/file/read.c @@ -1,14 +1,14 @@ -#include +#include #include #include /* casio_smem_data_base_address() - Generate the fragmented data address (0xa0000000 + offset) */ static void *casio_smem_get_data_base_address(casio_smem_fragment_t *fragment) { - extern casio_smem_block_t *casio_smem_block_table; + extern struct smemfs_superblock_s smemfs_superblock; casio_smem_block_t *block; - block = casio_smem_block_table; + block = smemfs_superblock.sector_table; while (block->magic_start == CASIO_SMEM_BLOCK_ENTRY_MAGIC && block->info.id != fragment->data_block_id) { @@ -20,7 +20,7 @@ static void *casio_smem_get_data_base_address(casio_smem_fragment_t *fragment) } /* casio_smem_read() - Read the file data (based on internal cursor) */ -ssize_t casio_smem_read(FILE *file, void *buf, size_t count) +ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos) { casio_smem_fragment_t *fragment; off_t fragment_data_offset; @@ -29,26 +29,26 @@ ssize_t casio_smem_read(FILE *file, void *buf, size_t count) size_t real_size; // Get Check obvious error. - if (file == NULL || buf == NULL || file->cursor > (off_t)file->size) + if (inode == NULL || buf == NULL) return (-1); - // Get the "real" reading size - if (file->size - file->cursor < count) - count = file->size - file->cursor; - // Get the current data fragment. current_size = 0; - fragment = (void *)((uint32_t)file->abstract + sizeof(casio_smem_header_t)); + fragment = (void *)((uint32_t)inode + sizeof(casio_smem_header_t)); while (fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC && - file->cursor > (off_t)(current_size + fragment->data_size + 1)) + pos > (off_t)(current_size + fragment->data_size + 1)) { current_size = current_size + fragment->data_size + 1; fragment = fragment + 1; } - fragment_data_offset = file->cursor - current_size; + + // Check fragment error + if (fragment->magic != CASIO_SMEM_FRAGMENT_MAGIC) + return (-1); // Read file data current_size = 0; + fragment_data_offset = pos - current_size; while (current_size < (ssize_t)count && fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC) { @@ -63,7 +63,8 @@ ssize_t casio_smem_read(FILE *file, void *buf, size_t count) return (current_size); // Handle fragment data offset. - if (fragment_data_offset != 0){ + if (fragment_data_offset != 0) + { data_base_addr = (void *)(((uint32_t)data_base_addr) + fragment_data_offset); fragment_data_offset = 0; } @@ -73,7 +74,6 @@ ssize_t casio_smem_read(FILE *file, void *buf, size_t count) // Update informations. current_size = current_size + real_size; - file->cursor = file->cursor + real_size; fragment = fragment + 1; } return (current_size); diff --git a/src/kernel/fs/smemfs/filesystem/mount.c b/src/kernel/fs/smemfs/filesystem/mount.c new file mode 100644 index 0000000..cd9b36e --- /dev/null +++ b/src/kernel/fs/smemfs/filesystem/mount.c @@ -0,0 +1,10 @@ +#include + +/* casio_smem_mount() - Get Block and Preheader Table addresses */ +void *smemfs_mount(void) +{ + extern struct smemfs_superblock_s smemfs_superblock; + + // Return the sector table to simulate the root inode. + return ((void*)smemfs_superblock.sector_table); +} diff --git a/src/kernel/fs/smemfs/initialize.c b/src/kernel/fs/smemfs/initialize.c new file mode 100644 index 0000000..6279150 --- /dev/null +++ b/src/kernel/fs/smemfs/initialize.c @@ -0,0 +1,77 @@ +#include +#include +#include + +// Kernel FS block +struct file_system_type smemfs_filesystem = +{ + // internal informations + .fs_name = "smemfs", + .fs_flags = FS_RDONLY, + + // FS specific openrations + .filesystem_operations = { + .mount = &smemfs_mount, + .umount = NULL + }, + + // File operations + .file_operations = { + .read = &smemfs_read, + .write = NULL + }, + + // Inode operations + .inode_operations = { + // Walk + .find_next_sibling = &smemfs_find_next_sibling, + .find_first_child = &smemfs_find_first_child, + .find_parent = &smemfs_find_parent, + + // Memory + .create = NULL, + .mkdir = NULL, + .rmdir = NULL, + .rename = NULL, + + // Informations + .get_name = &smemfs_get_name, + .get_mode = &smemfs_get_mode + } +}; + +struct smemfs_superblock_s smemfs_superblock; + +void smemfs_initialize(void) +{ + // Get / check Casio SMEM sector table + // @note: + // Casio SMEM sector table start + // always at 0xa0270000. + smemfs_superblock.sector_table = (void *)0xa0270000; + if (smemfs_superblock.sector_table->magic_start != 0x4200) + { + kvram_clear(); + printk(0, 0, "SMEMFS: Casio sector table error !"); + printk(0, 1, "Wait manual reset..."); + kvram_display(); + while (1){ __asm__ volatile ("sleep"); } + } + + // Casio SMEM inode table start always at the end of the sector table. + // Normaly start at 0xa0270320 but not always (?) + int i = -1; + while (smemfs_superblock.sector_table[++i].magic_start == CASIO_SMEM_BLOCK_ENTRY_MAGIC); + smemfs_superblock.inode_table = (void *)&smemfs_superblock.sector_table[i]; + if ((smemfs_superblock.inode_table->info != 0x51 && + smemfs_superblock.inode_table->info != 0x01) || + smemfs_superblock.inode_table->parent.id != 0xffff || + smemfs_superblock.inode_table->parent.type != 0xffff) + { + kvram_clear(); + printk(0, 0, "SMEMFS: Casio inode table error !"); + printk(0, 1, "Wait manual reset..."); + kvram_display(); + while (1){ __asm__ volatile ("sleep"); } + } +} diff --git a/src/kernel/fs/smemfs/inode/find_first_child.c b/src/kernel/fs/smemfs/inode/find_first_child.c new file mode 100644 index 0000000..65a2fa8 --- /dev/null +++ b/src/kernel/fs/smemfs/inode/find_first_child.c @@ -0,0 +1,32 @@ +#include +#include + +// Internal function +extern casio_smem_header_t *smemfs_walk(casio_smem_header_t *current_inode, + uint16_t parent_id, int skip); + +void *smemfs_find_first_child(void *inode) +{ + extern struct smemfs_superblock_s smemfs_superblock; + uint16_t parent_id; + + // Check error. + if (inode == NULL) + return (NULL); + + // Check root inode + if (inode == smemfs_superblock.sector_table) + { + parent_id = CASIO_SMEM_ROOT_ID; + } else { + // Check directory + if (((struct casio_smem_header_s *)inode)->type != CASIO_SMEM_HEADER_TYPE_DIRECTORY) + return (NULL); + + // Get directory ID + parent_id = ((struct casio_smem_header_s *)inode)->id; + } + + // Return the first child of the file. + return (smemfs_walk(smemfs_superblock.inode_table, parent_id, 0)); +} diff --git a/src/kernel/fs/smemfs/inode/find_next_sibling.c b/src/kernel/fs/smemfs/inode/find_next_sibling.c new file mode 100644 index 0000000..6f44dad --- /dev/null +++ b/src/kernel/fs/smemfs/inode/find_next_sibling.c @@ -0,0 +1,26 @@ +#include +#include + +// Internal function +extern casio_smem_header_t *smemfs_walk(casio_smem_header_t *current_inode, + uint16_t parent_id, int skip); + +void *smemfs_find_next_sibling(void *inode) +{ + extern struct smemfs_superblock_s smemfs_superblock; + uint16_t parent_id; + + // Check error. + if (inode == NULL) + return (NULL); + + // Check root inode + if (inode == smemfs_superblock.sector_table) + return (NULL); + + // Get parent ID. + parent_id = ((struct casio_smem_header_s *)inode)->parent.id; + + // Return the next file of the directory. + return (smemfs_walk(inode, parent_id, 0x01)); +} diff --git a/src/kernel/fs/smemfs/inode/find_parent.c b/src/kernel/fs/smemfs/inode/find_parent.c new file mode 100644 index 0000000..04a101b --- /dev/null +++ b/src/kernel/fs/smemfs/inode/find_parent.c @@ -0,0 +1,21 @@ +#include + +// Internal function +extern casio_smem_header_t *smemfs_walk(casio_smem_header_t *current_inode, + uint16_t parent_id, int skip); + +void *smemfs_find_parent(void *inode) +{ + extern struct smemfs_superblock_s smemfs_superblock; + uint16_t parent_id; + + // Check error. + if (inode == NULL) + return (NULL); + + // Get parent ID. + parent_id = ((struct casio_smem_header_s *)inode)->parent.id; + + // Return first inode find + return (smemfs_walk(smemfs_superblock.inode_table, parent_id, 0x01 | 0x02)); +} diff --git a/src/kernel/fs/smemfs/inode/get_mode.c b/src/kernel/fs/smemfs/inode/get_mode.c new file mode 100644 index 0000000..2364870 --- /dev/null +++ b/src/kernel/fs/smemfs/inode/get_mode.c @@ -0,0 +1,32 @@ +#include +#include + +mode_t smemfs_get_mode(void *inode) +{ + extern struct smemfs_superblock_s smemfs_superblock; + casio_smem_header_t *header; + int inode_type; + + // Check error + if (inode == NULL) + return (-1); + + // Check root inode + if (inode == smemfs_superblock.sector_table) + return (__S_IFDIR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + + // Check inode validity + header = inode; + if (header->info != CASIO_SMEM_HEADER_INFO_EXIST) + return (-1); + + // We can only check if the file is a + // directory or not (Bfile limitation) + if (header->type == CASIO_SMEM_HEADER_TYPE_DIRECTORY) + inode_type = __S_IFDIR; + else + inode_type = __S_IFREG; + + // Return default permission and type + return (inode_type | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); +} diff --git a/src/kernel/fs/smemfs/inode/get_name.c b/src/kernel/fs/smemfs/inode/get_name.c new file mode 100644 index 0000000..95514dc --- /dev/null +++ b/src/kernel/fs/smemfs/inode/get_name.c @@ -0,0 +1,39 @@ +#include + +int smemfs_get_name(void *inode, char *buf, size_t count) +{ + extern struct smemfs_superblock_s smemfs_superblock; + casio_smem_header_t *header; + + // Check error + if (inode == NULL) + return (-1); + + // Check root inode + if (inode == smemfs_superblock.sector_table) + { + buf[0] = '/'; + buf[1] = '\0'; + return (0); + } + + // Check inode validity + header = inode; + if (header->info != CASIO_SMEM_HEADER_INFO_EXIST) + return (-1); + + // Get "real" name size + count = count - 1; + if (count > CASIO_SMEM_NAME_LENGHT) + count = CASIO_SMEM_NAME_LENGHT; + + // Dump name + // @note: The name is stored into Shift-JIS format + int i = -1; + while (++i < (int)count && + header->name[i] != 0x0000 && + header->name[i] != 0xffff) + buf[i] = header->name[i]; + buf[i] = '\0'; + return (0); +} diff --git a/src/kernel/fs/smemfs/inode/walk.c b/src/kernel/fs/smemfs/inode/walk.c new file mode 100644 index 0000000..d6bd34f --- /dev/null +++ b/src/kernel/fs/smemfs/inode/walk.c @@ -0,0 +1,42 @@ +#include +#include + +casio_smem_header_t *smemfs_walk(casio_smem_header_t *current_inode, uint16_t parent_id, int skip) +{ + struct casio_smem_fragment_s *current_fragment; + + // Check current inode validity. + if (current_inode == NULL) + return (NULL); + + // Walk entry + while (current_inode->info == CASIO_SMEM_HEADER_INFO_EXIST || + current_inode->info == CASIO_SMEM_HEADER_INFO_DELETE) + { + // New inode validity check. + if (current_inode->info == CASIO_SMEM_HEADER_INFO_EXIST && + ((skip & 0x01) == 0) && + (((skip & 0x02) == 0 && current_inode->parent.id == parent_id) || + ((skip & 0x02) != 0 && current_inode->id == parent_id))) + { + return (current_inode); + } + + // Fast fragmentation skip + current_fragment = (void *)((uint32_t)(current_inode) + sizeof(struct casio_smem_header_s)); + if (current_fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC) + { + current_fragment = (void *)((uint32_t)current_fragment + + sizeof(struct casio_smem_fragment_s) * + current_fragment->frag_total); + } + + // Update current inode + current_inode = (void*)current_fragment; + + // Workaround update + skip = skip & ~0x01; + + } + return (NULL); +} diff --git a/src/kernel/fs/syscall/open.c b/src/kernel/fs/syscall/open.c new file mode 100644 index 0000000..8d05a26 --- /dev/null +++ b/src/kernel/fs/syscall/open.c @@ -0,0 +1,16 @@ +/*#include + +int sys_open(const char *parthname, int flags, ...) +{ + // TODO: handle flag O_CREAT and mode + (void)flags; + + // Try to find inode + inode = vfs_open(pathname, flags); + if (inode == NULL) + return (-1); + + // TODO: find process file slot ! + // TODO: initialise file informations ! + return (-1); +}*/ diff --git a/src/kernel/fs/vfs/dentry/find_first_child.c b/src/kernel/fs/vfs/dentry/find_first_child.c new file mode 100644 index 0000000..3ec8eaa --- /dev/null +++ b/src/kernel/fs/vfs/dentry/find_first_child.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include + +struct dentry *vfs_dentry_find_first_child(struct dentry *dentry) +{ + // Check file type + if (dentry == NULL || (dentry->mode & __S_IFDIR) == 0) + return (NULL); + + // Try to find next sibling into the VFS cache + if (dentry->child != NULL) + return (dentry->child); + + // Check internal primitives + if (dentry->dentry_op.inode_op == NULL || + dentry->dentry_op.inode_op->find_first_child == NULL || + dentry->dentry_op.inode_op->get_mode == NULL || + dentry->dentry_op.inode_op->get_name == NULL) + return (NULL); + + // Try to get first child inode + int mounted = 0; + void *inode = dentry->dentry_op.inode_op->find_first_child(dentry->inode); + if (inode == NULL) + { + // Check mnt point + if (dentry->mnt.inode == NULL || + dentry->mnt.inode_op == NULL || + dentry->mnt.inode_op->find_first_child == NULL || + dentry->mnt.inode_op->get_mode == NULL || + dentry->mnt.inode_op->get_name == NULL) + return (NULL); + + // Try to get mounted child + inode = dentry->mnt.inode_op->find_first_child(dentry->mnt.inode); + if (inode == NULL) + return (NULL); + + // Indicate mounted point + mounted = 1; + } + + // Try to create new dentry + struct dentry *new_dentry = pm_alloc(sizeof(struct dentry)); + if (new_dentry == NULL) + return (NULL); + + // Initialize new dentry + if (mounted == 0) + { + dentry->dentry_op.inode_op->get_name(inode, new_dentry->name, VFS_DENTRY_NAME_LENGHT); + new_dentry->mode = dentry->dentry_op.inode_op->get_mode(inode); + new_dentry->dentry_op.inode_op = dentry->dentry_op.inode_op; + new_dentry->dentry_op.file_op = dentry->dentry_op.file_op; + } else { + dentry->mnt.inode_op->get_name(inode, new_dentry->name, VFS_DENTRY_NAME_LENGHT); + new_dentry->mode = dentry->mnt.inode_op->get_mode(inode); + new_dentry->dentry_op.inode_op = dentry->mnt.inode_op; + new_dentry->dentry_op.file_op = dentry->mnt.file_op; + } + + // Common init + new_dentry->inode = inode; + new_dentry->parent = dentry; + new_dentry->child = NULL; + new_dentry->next = dentry->child; + new_dentry->mnt.inode = NULL; + new_dentry->mnt.file_op = NULL; + new_dentry->mnt.inode_op = NULL; + + // Update VFS cache en return + dentry->child = new_dentry; + return (new_dentry); +} diff --git a/src/kernel/fs/vfs/dentry/find_next_sibling.c b/src/kernel/fs/vfs/dentry/find_next_sibling.c new file mode 100644 index 0000000..b12fb81 --- /dev/null +++ b/src/kernel/fs/vfs/dentry/find_next_sibling.c @@ -0,0 +1,49 @@ +#include +#include +#include + +struct dentry *vfs_dentry_find_next_sibling(struct dentry *dentry) +{ + // Check error. + if (dentry == NULL) + return (NULL); + + // Try to find next sibling into the VFS cache + if (dentry->next != NULL) + return (dentry->next); + + // Check internal primitives + if (dentry->dentry_op.inode_op == NULL || + dentry->dentry_op.inode_op->find_next_sibling == NULL || + dentry->dentry_op.inode_op->get_mode == NULL || + dentry->dentry_op.inode_op->get_name == NULL) + return (NULL); + + // Try to get next inode + void *inode = dentry->dentry_op.inode_op->find_next_sibling(dentry->inode); + if (inode == NULL) + return (NULL); + + // Try to create new dentry + struct dentry *new_dentry = pm_alloc(sizeof(struct dentry)); + if (new_dentry == NULL) + return (NULL); + + // Initialize new dentry + dentry->dentry_op.inode_op->get_name(inode, new_dentry->name, VFS_DENTRY_NAME_LENGHT); + new_dentry->mode = dentry->dentry_op.inode_op->get_mode(inode); + new_dentry->inode = inode; + new_dentry->parent = dentry; + new_dentry->child = NULL; + new_dentry->next = dentry->next; + new_dentry->dentry_op.file_op = dentry->dentry_op.file_op; + new_dentry->dentry_op.inode_op = dentry->dentry_op.inode_op; + new_dentry->mnt.inode = NULL; + new_dentry->mnt.file_op = NULL; + new_dentry->mnt.inode_op = NULL; + + // Update VFS cache en return + dentry->next = new_dentry; + return (new_dentry); + +} diff --git a/src/kernel/fs/vfs/dentry/resolve.c b/src/kernel/fs/vfs/dentry/resolve.c new file mode 100644 index 0000000..6a51923 --- /dev/null +++ b/src/kernel/fs/vfs/dentry/resolve.c @@ -0,0 +1,90 @@ +#include +#include +#include + +//TODO add '.' handling. +//TODO add '..' handling. +//TODO add '//' handling +struct dentry *vfs_dentry_resolve(const char *path, int mode) +{ + extern struct dentry *vfs_root_node; + struct dentry *curr_dentry; + struct dentry *old_dentry; + int name_lenght; + char name[24]; + + // Check VFS validity + if (vfs_root_node == NULL){ + kvram_clear(); + printk(0, 0, "VFS root error !"); + kvram_display(); + DBG_WAIT; + return (NULL); + } + + // Get start inode + if (path[0] != '/'){ + // TODO get current process working directory + return (NULL); + } else { + curr_dentry = vfs_root_node->child; + old_dentry = vfs_root_node; + path = path + 1; + } + + // VFS walk entry ! + while (path[0] != '\0') + { + // Get file name + name_lenght = 0; + while (name_lenght < 24 && + path[name_lenght] != '/' && + path[name_lenght] != '\0') + { + name[name_lenght] = path[name_lenght]; + name_lenght = name_lenght + 1; + } + + // Check error + if (path[name_lenght] != '/' && path[name_lenght] != '\0') + return (NULL); + + // Add null char + name[name_lenght] = '\0'; + + // Check parthname or path + if (mode == 1 && path[name_lenght] == '\0') + return (old_dentry); + + // Check potential error + if (curr_dentry == NULL) + return (NULL); + + // Try to find file in the current VFS level. + while (strncmp(curr_dentry->name, name, name_lenght) != 0) + { + curr_dentry = vfs_dentry_find_next_sibling(curr_dentry); + if (curr_dentry == NULL) + return (NULL); + } + + // Directory check + if (path[name_lenght] == '/') + { + // Check type + if ((curr_dentry->mode & __S_IFDIR) == 0) + return (NULL); + + // Try to find first child + old_dentry = curr_dentry; + curr_dentry = vfs_dentry_find_first_child(curr_dentry); + + // Update name lenght to skip '/' char + name_lenght = name_lenght + 1; + } + + // Update path + path = &path[name_lenght]; + } + return (curr_dentry); +} diff --git a/src/kernel/fs/vfs/file/lseek.c b/src/kernel/fs/vfs/file/lseek.c new file mode 100644 index 0000000..cf241d6 --- /dev/null +++ b/src/kernel/fs/vfs/file/lseek.c @@ -0,0 +1,28 @@ +#include +#include + +/* vfs_lseek() - File cursor management */ +off_t vfs_lseek(FILE *file, off_t offset, int whence) +{ + // Check potential error. + if (file == NULL) + return (-1); + + if (whence == SEEK_SET) + { + file->cursor = offset; + return (file->cursor); + } + if (whence == SEEK_CUR) + { + file->cursor = file->cursor + offset; + return (file->cursor); + } + if (whence == SEEK_END) + { + //TODO: get file size !! + //file->cursor = file->size + offset - 1; + return (file->cursor); + } + return (-1); +} diff --git a/src/kernel/fs/vfs/file/open.c b/src/kernel/fs/vfs/file/open.c new file mode 100644 index 0000000..007dd35 --- /dev/null +++ b/src/kernel/fs/vfs/file/open.c @@ -0,0 +1,27 @@ +#include +#include +#include + +// Intrenal functions +extern struct dentry *vfs_dentry_resolve(const char *path, int mode); + +int vfs_open(FILE *file, char const *path, int flags) +{ + struct dentry *dentry; + + // Get target inode. + dentry = vfs_dentry_resolve(path, 0); + if (dentry == NULL) + return (-1); + + // Check directory. + if ((dentry->mode & __S_IFDIR) != 0) + return (-2); + + // Initialize new file. + file->private = dentry->inode; + file->permission = dentry->mode & (~__S_IFMT); + file->file_op = dentry->dentry_op.file_op; + file->cursor = 0; + return (0); +} diff --git a/src/kernel/fs/vfs/file/read.c b/src/kernel/fs/vfs/file/read.c new file mode 100644 index 0000000..93e1e70 --- /dev/null +++ b/src/kernel/fs/vfs/file/read.c @@ -0,0 +1,22 @@ +#include +#include + +ssize_t vfs_read(FILE *file, void *buf, size_t count) +{ + //TODO: Check permission !! + + // Check error + if (file == NULL || buf == NULL) + return (-1); + + // Get / check file's informations + if (file->private == NULL || file->file_op->read == NULL) + return (-1); + + // Read with FS specifique primitive and return the numbe of reading bytes. + memset(buf, 0x00, count); + ssize_t read = file->file_op->read(file->private, buf, count, file->cursor); + if (read != -1) + file->cursor = file->cursor + read; + return (read); +} diff --git a/src/kernel/fs/vfs/file/write.c b/src/kernel/fs/vfs/file/write.c new file mode 100644 index 0000000..9d49069 --- /dev/null +++ b/src/kernel/fs/vfs/file/write.c @@ -0,0 +1,21 @@ +#include +#include + +ssize_t vfs_write(FILE *file, const void *buf, size_t count) +{ + //TODO: Check permission !! + + // Check error + if (file == NULL || buf == NULL) + return (-1); + + // Get / check file's informations + if (file->private == NULL || file->file_op->write == NULL) + return (-1); + + // Writa with FS specifique primitive and return the numbe of reading bytes. + ssize_t write = file->file_op->write(file->private, buf, count, file->cursor); + if (write != -1) + file->cursor = file->cursor + write; + return (write); +} diff --git a/src/kernel/fs/vfs/inode/mkdir.c b/src/kernel/fs/vfs/inode/mkdir.c new file mode 100644 index 0000000..b9c294e --- /dev/null +++ b/src/kernel/fs/vfs/inode/mkdir.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include + +// Internal functions +struct dentry *vfs_dentry_resolve(const char *path, int mode); + +int vfs_mkdir(const char *pathname, mode_t mode) +{ + extern struct dentry *vfs_root_node; + struct dentry *parent_dentry; + struct dentry *folder; + char *name; + + // Get folder name + name = strrchr(pathname, '/'); + name = (name == NULL) ? (void *)pathname : &name[1]; + + // Get parent dentry + parent_dentry = vfs_dentry_resolve(pathname, 1); + + // Check parent dentry and FS primitives + if (parent_dentry == NULL || parent_dentry->dentry_op.inode_op->mkdir == NULL) + return (-1); + + // Try to create new dentry + folder = pm_alloc(sizeof(struct dentry)); + if (folder == NULL) + return (-2); + + // Try to request new folder + folder->inode = parent_dentry->dentry_op.inode_op->mkdir(parent_dentry->inode, name, mode); + if (folder->inode == NULL) + { + pm_free(folder); + return (-3); + } + + // Initialize new dentry + memset(folder->name, 0x00, VFS_DENTRY_NAME_LENGHT); + strncpy(folder->name, name, VFS_DENTRY_NAME_LENGHT); + folder->mode = mode | __S_IFDIR; + folder->parent = parent_dentry; + folder->next = parent_dentry->child; + folder->child = NULL; + folder->dentry_op.file_op = parent_dentry->dentry_op.file_op; + folder->dentry_op.inode_op = parent_dentry->dentry_op.inode_op; + folder->mnt.inode = NULL; + folder->mnt.inode_op = NULL; + folder->mnt.file_op = NULL; + + // Release dentry + parent_dentry->child = folder; + return (0); +} diff --git a/src/kernel/fs/vfs/register.c b/src/kernel/fs/vfs/register.c new file mode 100644 index 0000000..618669f --- /dev/null +++ b/src/kernel/fs/vfs/register.c @@ -0,0 +1,18 @@ +#include + +// Internal cache for registered FS +struct file_system_type *fs_list = NULL; + +// vfs_register_filesystem() - Register a new FS into kernel supported FS list +int vfs_register_filesystem(struct file_system_type *new) +{ + // Check error. + // TODO: check FS validity + if (new == NULL) + return (-1); + + // Register new FS. + new->next = fs_list; + fs_list = new; + return (0); +} diff --git a/src/kernel/fs/vfs/superblock/mount.c b/src/kernel/fs/vfs/superblock/mount.c new file mode 100644 index 0000000..2a70992 --- /dev/null +++ b/src/kernel/fs/vfs/superblock/mount.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +// Internal informations +struct dentry *vfs_root_node = NULL; + +// filesystem_get() - Get FS registered by the VFS +static struct file_system_type *filesystem_get(const char *name) +{ + extern struct file_system_type *fs_list; + struct file_system_type *filesystem; + + filesystem = fs_list; + while (filesystem != NULL) + { + // Check file system + if (strcmp(filesystem->fs_name, name) == 0) + return (filesystem); + + // Get next file system + filesystem = filesystem->next; + } + return (NULL); +} + +/* vfs_mount() - mount filesystem */ +int vfs_mount(const char *source, const char *target, + const char *filesystemtype, unsigned long mountflags, + const void *data) +{ + // Check error. + if (filesystemtype == NULL) + return (-1); + + // Get file system informations + struct file_system_type *filesystem = filesystem_get(filesystemtype); + if (filesystem == NULL) + return (-1); + + // Check ROOT mount. + if (target == NULL && mountflags == (unsigned long)VFS_MOUNT_ROOT) + { + // Alloc root mnt + vfs_root_node = pm_alloc(sizeof(struct dentry)); + if (vfs_root_node == NULL) + return (-1); + + // Try to mount the FS. + vfs_root_node->inode = filesystem->filesystem_operations.mount(); + if (vfs_root_node->inode == NULL) + { + kvram_clear(); + printk(0, 0, "VFS: Unable to mount ROOT inode !"); + printk(0, 1, "VFS: Wait manual reset..."); + kvram_display(); + while (1) { __asm__ volatile ("sleep"); } + } + + // Initialize entry + vfs_root_node->name[0] = '/'; + vfs_root_node->name[1] = '\0'; + vfs_root_node->parent = NULL; + vfs_root_node->child = NULL; + vfs_root_node->next = NULL; + vfs_root_node->dentry_op.file_op = &filesystem->file_operations; + vfs_root_node->dentry_op.inode_op = &filesystem->inode_operations; + vfs_root_node->mnt.inode = NULL; + vfs_root_node->mnt.file_op = NULL; + vfs_root_node->mnt.inode_op = NULL; + return (0); + } + + // Get target inode informations + struct dentry *mnt = vfs_dentry_resolve(target, 0); + if (mnt == NULL) + return (-1); + + // Check directory validity + if ((mnt->mode & __S_IFDIR) == 0) + return (-2); + + // Try to mount the directory + void *inode = filesystem->filesystem_operations.mount(); + if (inode == NULL) + return (-3); + + // Init mount point: set new FS specific primitives + // TODO: set new FS flags + mnt->mnt.inode = inode; + mnt->mnt.file_op = &filesystem->file_operations; + mnt->mnt.inode_op = &filesystem->inode_operations; + return (0); +} diff --git a/src/kernel/loader/entry.c b/src/kernel/loader/entry.c index cac95d8..2bf97ff 100644 --- a/src/kernel/loader/entry.c +++ b/src/kernel/loader/entry.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -14,13 +14,13 @@ void *loader(const char *path, process_t *process) return (NULL); // TODO: use VFS ! - if (casio_smem_open(&file, path, O_RDONLY) != 0) + if (vfs_open(&file, path, O_RDONLY) != 0) return (NULL); // Debug ! kvram_clear(); printk(0, 0, "File found !!"); - printk(0, 1, "inode = %p", file.abstract); + printk(0, 1, "inode = %p", file.private); printk(0, 2, "path = %s", path); kvram_display(); DBG_WAIT; diff --git a/src/kernel/loader/header.c b/src/kernel/loader/header.c index 28f4bf1..48d54f6 100644 --- a/src/kernel/loader/header.c +++ b/src/kernel/loader/header.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -7,7 +7,7 @@ int loader_get_header(FILE *file, Elf32_Ehdr *header) { // Read ELF header. - if (casio_smem_read(file, header, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr)) + if (vfs_read(file, header, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr)) return (-1); // Check magic number diff --git a/src/kernel/loader/image.c b/src/kernel/loader/image.c index 417d6f1..be4b3fe 100644 --- a/src/kernel/loader/image.c +++ b/src/kernel/loader/image.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -18,8 +18,8 @@ void *loader_load_image(FILE *file, Elf32_Ehdr *header, process_t *process) while (++i < header->e_phnum) { // Read programme header. - casio_smem_lseek(file, header->e_phoff + (sizeof(Elf32_Phdr) * i), SEEK_SET); - if (casio_smem_read(file, &program, sizeof(Elf32_Phdr)) != sizeof(Elf32_Phdr)) + vfs_lseek(file, header->e_phoff + (sizeof(Elf32_Phdr) * i), SEEK_SET); + if (vfs_read(file, &program, sizeof(Elf32_Phdr)) != sizeof(Elf32_Phdr)) return (NULL); // Check programe type. @@ -42,8 +42,8 @@ void *loader_load_image(FILE *file, Elf32_Ehdr *header, process_t *process) while (++i < header->e_phnum) { // Read programme header. - casio_smem_lseek(file, header->e_phoff + (sizeof(Elf32_Phdr) * i), SEEK_SET); - casio_smem_read(file, &program, sizeof(Elf32_Phdr)); + vfs_lseek(file, header->e_phoff + (sizeof(Elf32_Phdr) * i), SEEK_SET); + vfs_read(file, &program, sizeof(Elf32_Phdr)); // Generate physical address paddress = program.p_vaddr + process->memory.program.start; @@ -53,8 +53,8 @@ void *loader_load_image(FILE *file, Elf32_Ehdr *header, process_t *process) memset((void *)paddress, 0, program.p_memsz); // Dump the program. - casio_smem_lseek(file, program.p_offset, SEEK_SET); - casio_smem_read(file, (void *)paddress, program.p_filesz); + vfs_lseek(file, program.p_offset, SEEK_SET); + vfs_read(file, (void *)paddress, program.p_filesz); } // Generate program entry address diff --git a/src/kernel/syscall/handler.c b/src/kernel/syscall/handler.c index 73dd0a1..70529d8 100644 --- a/src/kernel/syscall/handler.c +++ b/src/kernel/syscall/handler.c @@ -12,17 +12,23 @@ static void sys_test(uint32_t a, uint32_t b, uint32_t c, uint32_t d) DBG_WAIT; } -static const void *sys_handler[14] = { +static const void *sys_handler[15] = { + // Kernel Test sys_test, //restart + + // Process NULL, //exit - NULL, //exiec + sys_waitpid, //waitpid + NULL, //exec + + // VFS NULL, //read NULL, //write NULL, //open NULL, //close - sys_waitpid, //waitpid + NULL, //lseek - // Custom + // Display kvram_display, //kvram_display kvram_clear, //kvram_clear kvram_print, //kvram_print diff --git a/src/kernel/util/printk.c b/src/kernel/util/printk.c index 49055d6..5b84b0d 100644 --- a/src/kernel/util/printk.c +++ b/src/kernel/util/printk.c @@ -51,6 +51,15 @@ void printk(int x, int y, char const *str, ...) nb = va_arg(ap, int32_t); base = (str[i + 1] == 'd') ? 10 : 16; + // Check negative value + // FIXME: negative error (max) + if (nb < 0 && str[i + 1] == 'd') + { + nb = 0 - nb; + font_draw(x, y, '-'); + x = x + KERNEL_FONT_REAL_WIDTH + 1; + } + // Generate buffer // @note: generate in LSB mode. while (digits == 0 || nb != 0) diff --git a/src/kernel/util/string.c b/src/kernel/util/string.c index 794f1aa..c6734e9 100644 --- a/src/kernel/util/string.c +++ b/src/kernel/util/string.c @@ -41,3 +41,52 @@ size_t strnlen(char const *str, size_t maxlen) while (str[++i] != '\0' && (size_t)i < maxlen); return (i); } + +// TODO: update me :( +size_t strlen(char const *str) +{ + int i; + + if (str == NULL) + return (0); + i = -1; + while (str[++i] != '\0'); + return (i); +} + +//TODO: update me :( +int strcmp(const char *s1, const char *s2) +{ + if (s1 == NULL || s2 == NULL) + return (0); + while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2) + { + s1 += 1; + s2 += 1; + } + return (*s1 - *s2); +} + +//TODO: update me :( +int strncmp(const char *s1, const char *s2, size_t n) +{ + if (s1 == NULL || s2 == NULL) + return (0); + size_t i = -1; + while (++i < n && s1[i] != '\0' && s2[i] != '\0' && s1[i] == s2[i]); + return (s1[i] - s2[i]); +} + +//TODO asm ? +char *strrchr(const char *s1, int c) +{ + void *saved; + + saved = NULL; + for (int i = 0 ; s1[i] != '\0' ; i++) + { + if (s1[i] == (char)c) + saved = (void *)&s1[i]; + } + return (saved); +} diff --git a/src/kernel/vhex.ld b/src/kernel/vhex.ld index 00f208a..827258e 100644 --- a/src/kernel/vhex.ld +++ b/src/kernel/vhex.ld @@ -51,16 +51,16 @@ SECTIONS _bctors = ALIGN(4) ; *(SORT_BY_INIT_PRIORITY(.ctors.*)) *(.ctors); - _ectors = ALIGN(4) ; + _ectors = . ; _bdtors = ALIGN(4) ; *(SORT_BY_INIT_PRIORITY(.dtors.*)) *(.dtors); - _edtors = ALIGN(4) ; + _edtors = . ; - /* Built-in */ - _bbuiltin_section = ALIGN(4) ; - *(.builtin); - _ebuiltin_section = ALIGN(4) ; + /* File System */ + _bfilesystem_section = ALIGN(4) ; + *(.filesystem); + _efilesystem_section = . ; } > rom : text diff --git a/src/lib/string/strchr.c b/src/lib/string/strchr.c new file mode 100644 index 0000000..60cadfe --- /dev/null +++ b/src/lib/string/strchr.c @@ -0,0 +1,31 @@ +#include + +//TODO: asm ? +char *strchr(const char *s1, int c) +{ + int i = -1; + while (s1[++i] != '\0' && s1[i] != c); + return ((s1[i] == '\0') ? NULL : (void*)&s1[i]); +} + +//TODO: asm ? +char *strchrnul(const char *s1, int c) +{ + int i = -1; + while (s1[++i] != '\0' && s1[i] != c); + return ((void*)&s1[i]); +} + +//TODO asm ? +char *strrchr(const char *s1, int c) +{ + void *saved; + + saved = NULL; + for (int i = 0 ; s1[i] != '\0' ; i++) + { + if (s1[i] == c) + saved = (void *)&s1[i]; + } + return (saved); +} diff --git a/src/lib/unistd/close.S b/src/lib/unistd/close.S new file mode 100644 index 0000000..1c3abf9 --- /dev/null +++ b/src/lib/unistd/close.S @@ -0,0 +1,12 @@ +.text +.global _close +.type _close, @function + +#include "kernel/unistd_32.h" + +.align 2 +_close: + trapa #__NR_close + rts + nop +.end diff --git a/src/lib/unistd/lseek.S b/src/lib/unistd/lseek.S new file mode 100644 index 0000000..59a3f88 --- /dev/null +++ b/src/lib/unistd/lseek.S @@ -0,0 +1,12 @@ +.text +.global _lseek +.type _lseek, @function + +#include "kernel/unistd_32.h" + +.align 2 +_lseek: + trapa #__NR_lseek + rts + nop +.end diff --git a/src/lib/unistd/open.S b/src/lib/unistd/open.S new file mode 100644 index 0000000..5dd9385 --- /dev/null +++ b/src/lib/unistd/open.S @@ -0,0 +1,12 @@ +.text +.global _open +.type _open, @function + +#include "kernel/unistd_32.h" + +.align 2 +_open: + trapa #__NR_open + rts + nop +.end diff --git a/src/lib/unistd/read.S b/src/lib/unistd/read.S new file mode 100644 index 0000000..21f94c3 --- /dev/null +++ b/src/lib/unistd/read.S @@ -0,0 +1,12 @@ +.text +.global _read +.type _read, @function + +#include "kernel/unistd_32.h" + +.align 2 +_read: + trapa #__NR_read + rts + nop +.end diff --git a/src/lib/unistd/write.S b/src/lib/unistd/write.S new file mode 100644 index 0000000..c4dc6a8 --- /dev/null +++ b/src/lib/unistd/write.S @@ -0,0 +1,12 @@ +.text +.global _write +.type _write, @function + +#include "kernel/unistd_32.h" + +.align 2 +_write: + trapa #__NR_write + rts + nop +.end diff --git a/src/user/shell/main.c b/src/user/shell/main.c index 6cb1638..ed46e25 100644 --- a/src/user/shell/main.c +++ b/src/user/shell/main.c @@ -1,48 +1,62 @@ #include +#include #include "util.h" +// @note +// For now all kernel invocation is +// made by the `unistd` library. + //TODO: documentation. int main(void) { - dclear(); - dprint(0, 0, "First user program !"); - dupdate(); - while (1) - { - // @note: we can use "sleep" because we - // are in privilegied mode - __asm__ volatile ("sleep"); - } - - -/* char input[12]; + char input[12]; int cmd_size; char **argv; int argc; + int fd; - // Open TTY. - tty_open(); + // Try to open TTY + // @note: + // We use O_DIRECT to avoid cache + // generation because we do not have a + // lot of memory. + fd = open("/dev/tty", O_DIRECT); + if (fd < 0) + { + // Display error. + dclear(); + dprint(0, 0, "User program fail to open TTY"); + dprint(0, 1, "Wait user manual reset..."); + dupdate(); + + // Wait user manual reset. + while (1) + { + // @note: we can use "sleep" because we + // are in privilegied mode. + // TODO: use sleep syscall ! + __asm__ volatile ("sleep"); + } + } - // Entry ! :D - tty_write("Boot Complete !\n", 16); - // Shell main loop. + write(fd, "Boot Complete !\n", 16); while (1) { // Get user command. - tty_write(">", 1); - cmd_size = tty_read(input, 12); + write(fd, ">", 1); + cmd_size = read(fd, input, 12); // Remove '\n' char. // FIXME: create argc, argv !! input[cmd_size - 1] = '\0'; // Check buit-in. - if (check_builtin(input) != 0) - { - tty_write(input, cmd_size - 1); - tty_write(": command not found\n", 20); - } + //if (check_builtin(input) != 0) + //{ + write(fd, input, cmd_size - 1); + write(fd, ": command not found\n", 20); + //} } - return (0);*/ + return (0); }