Add VFS + custom RAM FS + SMEM file primitives (read only)

This commit is contained in:
Yann MAGNIN 2020-01-05 09:00:43 +01:00
parent 9a9ac9614b
commit 7cc35984e4
66 changed files with 1923 additions and 276 deletions

41
$ Normal file
View File

@ -0,0 +1,41 @@
#include <fs/vfs.h>
#include <physical_memory.h>
#include <utils.h>
///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);
}

View File

@ -4,17 +4,26 @@
#include <stdint.h>
#include <stddef.h>
#include <kernel/types.h>
#include <kernel/fs/filesystem.h>
#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;

View File

@ -0,0 +1,104 @@
#ifndef __KERNEL_FS_FS_H__
# define __KERNEL_FS_FS_H__
#include <stddef.h>
#include <stdint.h>
#include <kernel/types.h>
// 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__*/

View File

@ -0,0 +1,81 @@
#ifndef __KERNEL_FS_GLADFS_H__
# define __KERNEL_FS_GLADFS_H__
#include <stdint.h>
#include <stddef.h>
#include <kernel/types.h>
# 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__*/

View File

@ -6,7 +6,6 @@
#include <kernel/types.h>
#include <kernel/fs/file.h>
#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__*/

45
include/kernel/fs/stat.h Normal file
View File

@ -0,0 +1,45 @@
#ifndef __KERNEL_FS_STAT_H__
# define __KERNEL_FS_STAT_H__
#include <stddef.h>
#include <stdint.h>
/* 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__*/

37
include/kernel/fs/vfs.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef __KERNEL_FS_VFS_H__
# define __KERNEL_FS_VFS_H__
#include <stddef.h>
#include <stdint.h>
#include <kernel/types.h>
#include <kernel/fs/filesystem.h>
#include <kernel/fs/file.h>
// 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__*/

View File

@ -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

View File

@ -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__*/

View File

@ -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);

View File

@ -8,7 +8,6 @@
// Define syscall LIST
#include <kernel/unistd_32.h>
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__*/

View File

@ -6,10 +6,15 @@
#include <kernel/process.h>
#include <kernel/syscall.h>
#include <kernel/util.h>
#include <kernel/fs/vfs.h>
#include <kernel/fs/stat.h>
#include <kernel/util.h>
//TODO: remove me !
#include <kernel/fs/smem.h>
#include <kernel/fs/smemfs.h>
#include <kernel/fs/gladfs.h>
#include <kernel/loader.h>
#include <kernel/devices/tty.h>
// 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.

View File

@ -0,0 +1,34 @@
#include <kernel/fs/gladfs.h>
#include <kernel/memory.h>
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);
}

View File

@ -0,0 +1,65 @@
#include <kernel/fs/gladfs.h>
#include <kernel/atomic.h>
#include <kernel/util.h>
// 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);
}

View File

@ -0,0 +1,93 @@
#include <kernel/fs/gladfs.h>
#include <kernel/atomic.h>
#include <kernel/util.h>
// 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);
}

View File

@ -0,0 +1,25 @@
#include <kernel/fs/gladfs.h>
#include <kernel/util.h>
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);
}

View File

@ -0,0 +1,7 @@
#include <kernel/fs/gladfs.h>
int gladfs_umount(void)
{
// Do nothing for now
return (0);
}

View File

@ -0,0 +1,60 @@
#include <kernel/fs/gladfs.h>
#include <kernel/fs/filesystem.h>
#include <kernel/memory.h>
// 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;
}

View File

@ -0,0 +1,30 @@
#include <kernel/fs/gladfs.h>
#include <kernel/fs/stat.h>
#include <kernel/atomic.h>
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);
}

View File

@ -0,0 +1,8 @@
#include <kernel/fs/gladfs.h>
void *gladfs_find_first_child(void *inode)
{
if (inode == NULL)
return (NULL);
return (((struct gladfs_inode_s*)inode)->children);
}

View File

@ -0,0 +1,8 @@
#include <kernel/fs/gladfs.h>
void *gladfs_find_next_sibling(void *inode)
{
if (inode == NULL)
return (NULL);
return (((struct gladfs_inode_s*)inode)->next);
}

View File

@ -0,0 +1,8 @@
#include <kernel/fs/gladfs.h>
void *gladfs_find_parent(void *inode)
{
if (inode == NULL)
return (NULL);
return (((struct gladfs_inode_s*)inode)->parent);
}

View File

@ -0,0 +1,6 @@
#include <kernel/fs/gladfs.h>
mode_t gladfs_get_mode(void *inode)
{
return (((struct gladfs_inode_s*)inode)->mode);
}

View File

@ -0,0 +1,17 @@
#include <kernel/fs/gladfs.h>
#include <kernel/util.h>
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);
}

View File

@ -0,0 +1,30 @@
#include <kernel/fs/gladfs.h>
#include <kernel/fs/stat.h>
#include <kernel/atomic.h>
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);
}

View File

@ -0,0 +1,22 @@
#include <kernel/fs/gladfs.h>
#include <kernel/memory.h>
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);
}

View File

@ -0,0 +1,25 @@
#include <kernel/fs/gladfs.h>
#include <kernel/memory.h>
#include <kernel/util.h>
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);
}

View File

@ -0,0 +1,13 @@
#include <kernel/fs/gladfs.h>
#include <kernel/memory.h>
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);
}

View File

@ -0,0 +1,28 @@
#include <kernel/fs/gladfs.h>
#include <kernel/memory.h>
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);
}

View File

@ -1,24 +0,0 @@
#include <kernel/fs/smem.h>
#include <kernel/fs/file.h>
/* 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);
}

View File

@ -1,25 +0,0 @@
#include <kernel/fs/smem.h>
// 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);
}

View File

@ -1,130 +0,0 @@
#include <kernel/fs/smem.h>
#include <kernel/fs/file.h>
#include <kernel/util.h>
//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);
}

View File

@ -1,14 +1,14 @@
#include <kernel/fs/smem.h>
#include <kernel/fs/smemfs.h>
#include <kernel/fs/file.h>
#include <kernel/util.h>
/* 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);

View File

@ -0,0 +1,10 @@
#include <kernel/fs/smemfs.h>
/* 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);
}

View File

@ -0,0 +1,77 @@
#include <kernel/fs/smemfs.h>
#include <kernel/fs/filesystem.h>
#include <kernel/util.h>
// 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"); }
}
}

View File

@ -0,0 +1,32 @@
#include <kernel/fs/smemfs.h>
#include <kernel/util.h>
// 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));
}

View File

@ -0,0 +1,26 @@
#include <kernel/fs/smemfs.h>
#include <kernel/util.h>
// 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));
}

View File

@ -0,0 +1,21 @@
#include <kernel/fs/smemfs.h>
// 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));
}

View File

@ -0,0 +1,32 @@
#include <kernel/fs/smemfs.h>
#include <kernel/fs/stat.h>
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);
}

View File

@ -0,0 +1,39 @@
#include <kernel/fs/smemfs.h>
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);
}

View File

@ -0,0 +1,42 @@
#include <kernel/fs/smemfs.h>
#include <kernel/util.h>
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);
}

View File

@ -0,0 +1,16 @@
/*#include <kernel/fs/vfs.h>
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);
}*/

View File

@ -0,0 +1,76 @@
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
#include <kernel/util.h>
#include <kernel/fs/stat.h>
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);
}

View File

@ -0,0 +1,49 @@
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
#include <kernel/util.h>
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);
}

View File

@ -0,0 +1,90 @@
#include <kernel/fs/vfs.h>
#include <kernel/fs/stat.h>
#include <kernel/util.h>
//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);
}

View File

@ -0,0 +1,28 @@
#include <kernel/fs/vfs.h>
#include <kernel/fs/file.h>
/* 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);
}

View File

@ -0,0 +1,27 @@
#include <kernel/fs/vfs.h>
#include <kernel/fs/stat.h>
#include <kernel/util.h>
// 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);
}

View File

@ -0,0 +1,22 @@
#include <kernel/fs/vfs.h>
#include <kernel/util.h>
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);
}

View File

@ -0,0 +1,21 @@
#include <kernel/fs/vfs.h>
#include <kernel/util.h>
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);
}

View File

@ -0,0 +1,56 @@
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
#include <kernel/fs/stat.h>
#include <kernel/util.h>
// 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);
}

View File

@ -0,0 +1,18 @@
#include <kernel/fs/vfs.h>
// 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);
}

View File

@ -0,0 +1,95 @@
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
#include <kernel/util.h>
#include <kernel/fs/stat.h>
// 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);
}

View File

@ -1,5 +1,5 @@
#include <kernel/loader.h>
#include <kernel/fs/smem.h>
#include <kernel/fs/vfs.h>
#include <kernel/fs/file.h>
#include <kernel/util.h>
#include <kernel/elf.h>
@ -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;

View File

@ -1,5 +1,5 @@
#include <kernel/loader.h>
#include <kernel/fs/smem.h>
#include <kernel/fs/vfs.h>
#include <kernel/util.h>
#include <kernel/elf.h>
@ -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

View File

@ -1,5 +1,5 @@
#include <kernel/loader.h>
#include <kernel/fs/smem.h>
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
#include <kernel/util.h>
#include <kernel/elf.h>
@ -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

View File

@ -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

View File

@ -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)

View File

@ -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);
}

View File

@ -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

31
src/lib/string/strchr.c Normal file
View File

@ -0,0 +1,31 @@
#include <lib/string.h>
//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);
}

12
src/lib/unistd/close.S Normal file
View File

@ -0,0 +1,12 @@
.text
.global _close
.type _close, @function
#include "kernel/unistd_32.h"
.align 2
_close:
trapa #__NR_close
rts
nop
.end

12
src/lib/unistd/lseek.S Normal file
View File

@ -0,0 +1,12 @@
.text
.global _lseek
.type _lseek, @function
#include "kernel/unistd_32.h"
.align 2
_lseek:
trapa #__NR_lseek
rts
nop
.end

12
src/lib/unistd/open.S Normal file
View File

@ -0,0 +1,12 @@
.text
.global _open
.type _open, @function
#include "kernel/unistd_32.h"
.align 2
_open:
trapa #__NR_open
rts
nop
.end

12
src/lib/unistd/read.S Normal file
View File

@ -0,0 +1,12 @@
.text
.global _read
.type _read, @function
#include "kernel/unistd_32.h"
.align 2
_read:
trapa #__NR_read
rts
nop
.end

12
src/lib/unistd/write.S Normal file
View File

@ -0,0 +1,12 @@
.text
.global _write
.type _write, @function
#include "kernel/unistd_32.h"
.align 2
_write:
trapa #__NR_write
rts
nop
.end

View File

@ -1,48 +1,62 @@
#include <lib/display.h>
#include <lib/unistd.h>
#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);
}