Add device managment + syscall file primitives + TTY device

This commit is contained in:
Yann MAGNIN 2020-01-06 20:25:06 +01:00
parent 75ad9af523
commit d83175f1dd
25 changed files with 347 additions and 33 deletions

View File

@ -0,0 +1,27 @@
#ifndef __KERNEL_DEVICES_DEVICE_H__
# define __KERNEL_DEVICES_DEVICE_H__
#include <stddef.h>
#include <stdint.h>
#include <kernel/fs/filesystem.h>
#define dev_get_major(dev) (dev & 0xff00)
#define dev_get_minor(dev) (dev & 0x00ff)
#define dev_make_major(major) ((major & 0xff) << 8)
#define DEVICE(name) \
__attribute__((section(".device"))) \
static struct device name##_dev
// Define dev_t
typedef uint16_t dev_t;
struct device
{
dev_t major;
void *(*open)(dev_t major, dev_t minor);
struct file_operations file_op;
int (*close)(void *inode);
};
#endif /*__KERNEL_DEVICES_DEVICE_H__*/

View File

@ -4,6 +4,7 @@
#include <stddef.h>
#include <stdint.h>
#include <kernel/devices/display.h>
#include <kernel/devices/device.h>
#include <kernel/types.h>
// Define default buffer size.
@ -11,6 +12,9 @@
#define TTY_BUFFER_LINES (DISPLAY_VCHAR_MAX * 3)
#define TTY_BUFFER_COLUMNS (DISPLAY_HCHAR_MAX)
// Define TTY major
#define TTY_DEV_MAJOR (4)
struct tty_s
{
char buffer[TTY_BUFFER_LINES + 1][TTY_BUFFER_COLUMNS + 1];
@ -51,14 +55,14 @@ struct keyboard_obj_s
};
// primitives.
extern int tty_open(void);
extern ssize_t tty_write(const void *buffer, size_t count);
extern ssize_t tty_read(void *buffer, size_t count);
extern int tty_close(void);
extern void *tty_open(dev_t major, dev_t minor);
extern ssize_t tty_write(void *inode, const void *buffer, size_t count);
extern ssize_t tty_read(void *inode, void *buffer, size_t count);
extern int tty_close(void *inode);
// IOCTL.
#define TTY_IOCTL_GETDX (0x00)
#define TTY_IOCTL_GETDY (0x01)
extern void tty_ioctl(uint32_t cmd, ...);
extern void tty_ioctl(void *inode, uint32_t cmd, ...);
#endif /*__KERNEL_TTY_H__*/

View File

@ -54,6 +54,7 @@ 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);
void (*ioctl)(void *inode, uint32_t cmd, ...);
};
// Based on UNIX Kernel 2.6.39

View File

@ -6,6 +6,7 @@
#include <kernel/types.h>
#include <kernel/fs/filesystem.h>
#include <kernel/fs/file.h>
#include <kernel/devices/device.h>
// Internal VFS macros
#define VFS_MOUNT_ROOT (-1)
@ -22,16 +23,20 @@ extern int vfs_mount(const char *source, const char *target,
// Inode operations
extern int vfs_mkdir(const char *pathname, mode_t mode);
extern int vfs_mknod(const char *pathname, mode_t mode, dev_t dev);
// 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);
extern int vfs_close(FILE *file);
// 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);
extern struct dentry *vfs_dentry_alloc(const char *name, mode_t mdode);
extern void vfs_dentry_free(struct dentry *dentry);
#endif /*__KERNEL_FS_VFS_H__*/

View File

@ -3,9 +3,11 @@
#include <stddef.h>
#include <stdint.h>
#include <kernel/fs/file.h>
#include <kernel/context.h>
#include <kernel/types.h>
#define PROCESS_NB_OPEN_FILE (4)
#define PROCESS_USER_STACK_SIZE (2048)
#define PROCESS_KERNEL_STACK_SIZE (512)
#define PROCESS_NAME_LENGHT (16)
@ -29,6 +31,15 @@ typedef struct process_s
// Context management
common_context_t context;
// Open file management
struct {
enum {
PROCESS_FILE_SLOT_UNUSED,
PROCESS_FILE_SLOT_USED
} status;
FILE file;
} opfile[PROCESS_NB_OPEN_FILE];
// Signals management.
//sighandler_t signal[NSIG];

View File

@ -15,6 +15,11 @@ extern pid_t sys_getpid(void);
extern pid_t sys_getppid(void);
extern pid_t sys_waitpid(pid_t pid, int *wstatus, int options);
extern int sys_open(const char *pathname, int flags, ...);
extern ssize_t sys_write(int fd, const void *buf, size_t count);
extern ssize_t sys_read(int fd, void *buf, size_t count);
extern off_t sys_lseek(int fd, off_t offset, int whence);
extern int sys_close(int fd);
//---
//

View File

@ -85,6 +85,23 @@ static void section_execute(void *bsection, void *esection)
}
}
void vfs_test(struct dentry *node, int level)
{
if (node == NULL)
return;
// space !
for (int i = 0 ; i < level ; i++)
tty_write(NULL, " ", 1);
// Name
tty_write(NULL, node->name, strlen(node->name));
tty_write(NULL, "\n", 1);
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")))
int start(void)
@ -144,6 +161,17 @@ int start(void)
vfs_mkdir("/mnt", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
vfs_mkdir("/mnt/smemfs", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
vfs_mount(NULL, "/mnt/smemfs", "smemfs", /*MS_RDONLY*/0, NULL);
// Add devices
vfs_mknod("/dev/tty", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
dev_make_major(TTY_DEV_MAJOR));
// VFS test
tty_open(0, 0);
extern struct dentry *vfs_root_node;
vfs_test(vfs_root_node, 0);
tty_write(NULL, "FINIT !\n", 8);
DBG_WAIT;
// Create first process: Vhex.
pid_t vhex_pid = process_create("Vhex");

View File

@ -0,0 +1,13 @@
#include <kernel/devices/tty.h>
#include <kernel/devices/device.h>
DEVICE(tty) = {
.major = dev_make_major(TTY_DEV_MAJOR),
.open = &tty_open,
.file_op = {
.read = (void *)&tty_read,
.write =(void *)&tty_write,
.ioctl = &tty_ioctl
},
.close = &tty_close
};

View File

@ -15,7 +15,7 @@ static int buffer_insert(struct keyboard_obj_s *keyboard, char n);
static void cursor_callback(struct keyboard_obj_s *keyboard);
//FIXME: this function is device-specifique !!
ssize_t tty_read(void *buffer, size_t count)
ssize_t tty_read(void *inode, void *buffer, size_t count)
{
extern struct keycache_s *keylist;
extern struct tty_s tty;
@ -238,7 +238,7 @@ static void tty_buffer_display(struct keyboard_obj_s *keyboard)
: keyboard->buffer.clen;
// Write buffer.
tty_write(keyboard->buffer.addr, size);
tty_write(NULL, keyboard->buffer.addr, size);
}
static int update_buffer(struct keyboard_obj_s *keyboard, key_t key)
@ -333,8 +333,8 @@ static void cursor_callback(struct keyboard_obj_s *keyboard)
tty.cursor.y = y;
// Get Display X and Y position.
tty_ioctl(TTY_IOCTL_GETDX, &x);
tty_ioctl(TTY_IOCTL_GETDY, &y);
tty_ioctl(NULL, TTY_IOCTL_GETDX, &x);
tty_ioctl(NULL, TTY_IOCTL_GETDY, &y);
// Display cursor.
kvram_reverse(x, y, (KERNEL_FONT_REAL_WIDTH + 1), (KERNEL_FONT_REAL_HEIGHT + 1));

View File

@ -174,7 +174,7 @@ static void tty_display(void)
atomic_end();
}
ssize_t tty_write(const void *buffer, size_t count)
ssize_t tty_write(void *inode, const void *buffer, size_t count)
{
ssize_t written;

View File

@ -1,6 +1,6 @@
#include <kernel/devices/tty.h>
int tty_close(void)
int tty_close(void *inode)
{
// Do nothing for now.
return (0);

View File

@ -6,7 +6,7 @@
// Internal TTY object.
struct tty_s tty;
int tty_open(void)
void *tty_open(dev_t major, dev_t minor)
{
int lines;
@ -31,5 +31,5 @@ int tty_open(void)
// Call TTY primitives constructor
keyboard_open();
display_open();
return (0);
return (&tty);
}

View File

@ -1,7 +1,7 @@
#include <kernel/devices/tty.h>
#include <stdarg.h>
void tty_ioctl(uint32_t cmd, ...)
void tty_ioctl(void *inode, uint32_t cmd, ...)
{
extern struct tty_s tty;
va_list ap;

View File

@ -0,0 +1,8 @@
#include <kernel/fs/vfs.h>
#include <kernel/process.h>
int sys_close(int fd)
{
//TODO !!!!
return (-1);
}

View File

@ -0,0 +1,14 @@
#include <kernel/fs/vfs.h>
#include <kernel/process.h>
off_t sys_lseek(int fd, off_t offset, int whence)
{
extern process_t *process_current;
// Check fd
if (fd < 0 || fd >= PROCESS_NB_OPEN_FILE)
return (-1);
// call VFS read primitive
return (vfs_lseek(&process_current->opfile[fd].file, offset, whence));
}

View File

@ -1,16 +1,36 @@
/*#include <kernel/fs/vfs.h>
#include <kernel/fs/vfs.h>
#include <kernel/process.h>
#include <kernel/util.h>
int sys_open(const char *parthname, int flags, ...)
int sys_open(const char *pathname, int flags, ...)
{
// TODO: handle flag O_CREAT and mode
extern process_t *process_current;
kvram_clear();
printk(0, 0, "Syscall open() !");
printk(0, 1, "path: %s", pathname);
printk(0, 2, "flags: %#x", flags);
kvram_display();
DBG_WAIT;
// Get current process
if (process_current == NULL)
return (-1);
// Try to find free file slot
int fd = -1;
while (++fd < PROCESS_NB_OPEN_FILE &&
process_current->opfile[fd].status == PROCESS_FILE_SLOT_USED);
if (fd >= PROCESS_NB_OPEN_FILE)
return (-1);
// TODO: handle flags and mode !!
(void)flags;
// Try to find inode
inode = vfs_open(pathname, flags);
if (inode == NULL)
if (vfs_open(&process_current->opfile[fd].file, pathname, flags) != 0)
return (-1);
// TODO: find process file slot !
// TODO: initialise file informations !
return (-1);
}*/
// Return the file descriptor
return (fd);
}

View File

@ -0,0 +1,14 @@
#include <kernel/fs/vfs.h>
#include <kernel/process.h>
ssize_t sys_read(int fd, void *buf, size_t count)
{
extern process_t *process_current;
// Check fd
if (fd < 0 || fd >= PROCESS_NB_OPEN_FILE)
return (-1);
// call VFS read primitive
return (vfs_read(&process_current->opfile[fd].file, buf, count));
}

View File

@ -0,0 +1,14 @@
#include <kernel/fs/vfs.h>
#include <kernel/process.h>
ssize_t sys_write(int fd, const void *buf, size_t count)
{
extern process_t *process_current;
// Check fd
if (fd < 0 || fd >= PROCESS_NB_OPEN_FILE)
return (-1);
// call VFS read primitive
return (vfs_write(&process_current->opfile[fd].file, buf, count));
}

View File

@ -0,0 +1,28 @@
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
#include <kernel/util.h>
struct dentry *vfs_dentry_alloc(const char *name, mode_t mode)
{
struct dentry *node;
// Try to create new dentry
node = pm_alloc(sizeof(struct dentry));
if (node == NULL)
return (NULL);
// Initialize dentry
memset(node->name, 0x00, VFS_DENTRY_NAME_LENGHT);
strncpy(node->name, name, VFS_DENTRY_NAME_LENGHT);
node->inode = NULL;
node->mode = mode;
node->parent = NULL;
node->child = NULL;
node->next = NULL;
node->mnt.inode = NULL;
node->mnt.file_op = NULL;
node->mnt.inode_op = NULL;
node->dentry_op.file_op = NULL;
node->dentry_op.inode_op = NULL;
return (node);
}

View File

@ -0,0 +1,12 @@
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
void vfs_dentry_free(struct dentry *dentry)
{
// Check error
if (dentry == NULL)
return;
// Free'd allocated space
pm_free(dentry);
}

View File

@ -5,18 +5,30 @@
// Intrenal functions
extern struct dentry *vfs_dentry_resolve(const char *path, int mode);
int vfs_open(FILE *file, char const *path, int flags)
int vfs_open(FILE *file, char const *pathname, int flags)
{
struct dentry *dentry;
// Get target inode.
dentry = vfs_dentry_resolve(path, 0);
dentry = vfs_dentry_resolve(pathname, 0);
if (dentry == NULL)
{
kvram_clear();
printk(0, 0, "VFS_open(): path error '%s'", pathname);
kvram_display();
DBG_WAIT;
return (-1);
}
// Check directory.
if ((dentry->mode & __S_IFDIR) != 0)
{
kvram_clear();
printk(0, 0, "VFS_open(): file type error '%s'", pathname);
kvram_display();
DBG_WAIT;
return (-2);
}
// Initialize new file.
file->private = dentry->inode;

View File

@ -0,0 +1,87 @@
#include <kernel/fs/vfs.h>
#include <kernel/fs/stat.h>
#include <kernel/util.h>
struct device *device_get(dev_t major)
{
extern uint32_t bdevice_section;
extern uint32_t edevice_section;
struct device *device;
int i;
i = -1;
device = (void *)&bdevice_section;
while ((uint32_t)&device[++i] < (uint32_t)&edevice_section)
{
if (device[i].major == major)
return (&device[i]);
}
return (NULL);
}
int vfs_mknod(const char *pathname, mode_t mode, dev_t dev)
{
extern struct dentry *vfs_root_node;
struct dentry *parent_dentry;
struct device *device;
struct dentry *file;
char *name;
// Get parent dentry
parent_dentry = vfs_dentry_resolve(pathname, 1);
if (parent_dentry == NULL)
{
kvram_clear();
printk(0, 0, "mknod: parent dentry error !");
kvram_display();
DBG_WAIT;
return (-1);
}
// Get folder name
name = strrchr(pathname, '/');
name = (name == NULL) ? (void *)pathname : &name[1];
// Try to find open device
device = device_get(dev_get_major(dev));
if (device == NULL)
{
kvram_clear();
printk(0, 0, "mknod: device error !");
kvram_display();
DBG_WAIT;
return (-2);
}
// Tru to create empty node
file = vfs_dentry_alloc(name, mode | __S_IFCHR);
if (file == NULL)
{
kvram_clear();
printk(0, 0, "mknod: dentry alloc error !");
kvram_display();
DBG_WAIT;
return (-3);
}
// Try to open device
file->inode = device->open(dev_get_major(dev), dev_get_minor(dev));
if (file->inode == NULL)
{
kvram_clear();
printk(0, 0, "mknod: device inode error !");
kvram_display();
DBG_WAIT;
vfs_dentry_free(file);
return (-4);
}
// Set file operations
file->dentry_op.file_op = &device->file_op;
// Add file into VFS
file->next = parent_dentry->child;
parent_dentry->child = file;
return (0);
}

View File

@ -1,5 +1,5 @@
#include <kernel/memory.h>
#include <kernel/devices/tty.h>
#include <kernel/util.h>
void pm_free(void *ptr)
{
@ -17,10 +17,13 @@ void pm_free(void *ptr)
// Check misaligned pointer.
if (((uint32_t)ptr % PM_BLOCK_SIZE) != 0)
{
tty_write(
kvram_clear();
printk(0, 0,
"pm_free: Warning, you try to free misaligned"
"pointer address (%p)\n", sptr
);
kvram_display();
DBG_WAIT;
return;
}
@ -46,8 +49,11 @@ void pm_free(void *ptr)
}
// No block found, display error.
tty_write(
kvram_clear();
printk(0, 0,
"pm_free: Warning, you try to free unused"
"allocated memory (%p)", sptr
);
kvram_display();
DBG_WAIT;
}

View File

@ -22,11 +22,11 @@ static const void *sys_handler[15] = {
NULL, //exec
// VFS
NULL, //read
NULL, //write
NULL, //open
NULL, //close
NULL, //lseek
sys_read, //read
sys_write, //write
sys_open, //open
sys_close, //close
sys_lseek, //lseek
// Display
kvram_display, //kvram_display

View File

@ -61,6 +61,11 @@ SECTIONS
_bfilesystem_section = ALIGN(4) ;
*(.filesystem);
_efilesystem_section = . ;
/* Device */
_bdevice_section = ALIGN(4);
*(.device);
_edevice_section = . ;
} > rom : text