Add VFS + custom RAM FS + SMEM file primitives (read only)
This commit is contained in:
parent
9a9ac9614b
commit
7cc35984e4
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__*/
|
|
@ -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__*/
|
|
@ -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__*/
|
|
@ -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__*/
|
|
@ -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__*/
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#include <kernel/fs/gladfs.h>
|
||||
|
||||
int gladfs_umount(void)
|
||||
{
|
||||
// Do nothing for now
|
||||
return (0);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#include <kernel/fs/gladfs.h>
|
||||
|
||||
mode_t gladfs_get_mode(void *inode)
|
||||
{
|
||||
return (((struct gladfs_inode_s*)inode)->mode);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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"); }
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}*/
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
.text
|
||||
.global _close
|
||||
.type _close, @function
|
||||
|
||||
#include "kernel/unistd_32.h"
|
||||
|
||||
.align 2
|
||||
_close:
|
||||
trapa #__NR_close
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -0,0 +1,12 @@
|
|||
.text
|
||||
.global _lseek
|
||||
.type _lseek, @function
|
||||
|
||||
#include "kernel/unistd_32.h"
|
||||
|
||||
.align 2
|
||||
_lseek:
|
||||
trapa #__NR_lseek
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -0,0 +1,12 @@
|
|||
.text
|
||||
.global _open
|
||||
.type _open, @function
|
||||
|
||||
#include "kernel/unistd_32.h"
|
||||
|
||||
.align 2
|
||||
_open:
|
||||
trapa #__NR_open
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -0,0 +1,12 @@
|
|||
.text
|
||||
.global _read
|
||||
.type _read, @function
|
||||
|
||||
#include "kernel/unistd_32.h"
|
||||
|
||||
.align 2
|
||||
_read:
|
||||
trapa #__NR_read
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -0,0 +1,12 @@
|
|||
.text
|
||||
.global _write
|
||||
.type _write, @function
|
||||
|
||||
#include "kernel/unistd_32.h"
|
||||
|
||||
.align 2
|
||||
_write:
|
||||
trapa #__NR_write
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue