diff --git a/etc/make/conf.mk b/etc/make/conf.mk index 6abfbb0..2f22fa7 100644 --- a/etc/make/conf.mk +++ b/etc/make/conf.mk @@ -8,7 +8,8 @@ CFLAGS+=-Wall \ -Wno-unused-variable \ -Wno-language-extension-token \ -Wno-gnu-zero-variadic-macro-arguments \ - -O0 + -O0 \ + -ggdb ifdef KERNEL_TEST_MODE CFLAGS+=-DKERNEL_TEST_MODE @@ -40,7 +41,6 @@ CFLAGS+=-D__KERNEL__ # $(O)/sys/vfs/tar.o \ # $(O)/sys/binfmt_elf.o \ # $(O)/sys/errno.o \ -# $(O)/sys/tty.o \ # $(O)/sys/chr.o OBJS+=$(O)/sys/debug.o \ @@ -64,12 +64,12 @@ OBJS+=$(O)/sys/debug.o \ $(O)/sys/vfs/ext2/ext2blk.o \ $(O)/sys/vfs/tar.o \ $(O)/sys/blk/ram.o \ + $(O)/sys/tty.o \ $(O)/sys/reboot.o \ $(O)/sys/random.o \ $(O)/sys/init.o # \ - $(O)/sys/tty.o \ $(O)/sys/vfs/pty.o \ $(O)/sys/vfs/ext2/ext2alloc.o \ $(O)/sys/vfs/ext2/ext2dir.o \ diff --git a/include/sys/fs/ofile.h b/include/sys/fs/ofile.h index 85664d6..586b525 100644 --- a/include/sys/fs/ofile.h +++ b/include/sys/fs/ofile.h @@ -2,6 +2,10 @@ #include "node.h" #include +#define OF_WRITABLE (1 << 0) +#define OF_READABLE (1 << 1) +#define OF_DIRECTORY (1 << 2) + struct ofile { int flags; struct vnode *vnode; diff --git a/include/sys/fs/vfs.h b/include/sys/fs/vfs.h index f1da6d8..9a88f83 100644 --- a/include/sys/fs/vfs.h +++ b/include/sys/fs/vfs.h @@ -28,9 +28,11 @@ int vfs_link_resolve(struct vfs_ioctx *ctx, struct vnode *lnk, struct vnode **re int vfs_find(struct vfs_ioctx *ctx, struct vnode *rel, const char *path, struct vnode **node); int vfs_mount(struct vfs_ioctx *ctx, const char *at, void *blk, const char *fs, const char *opt); +int vfs_open_vnode(struct vfs_ioctx *ctx, struct ofile *fd, struct vnode *node, int opt); int vfs_open(struct vfs_ioctx *ctx, struct ofile *fd, const char *path, int flags, int mode); void vfs_close(struct vfs_ioctx *ctx, struct ofile *fd); int vfs_stat(struct vfs_ioctx *ctx, const char *path, struct stat *st); +ssize_t vfs_write(struct vfs_ioctx *ctx, struct ofile *fd, const void *buf, size_t count); ssize_t vfs_read(struct vfs_ioctx *ctx, struct ofile *fd, void *buf, size_t count); diff --git a/include/sys/thread.h b/include/sys/thread.h index 33abf03..30d34f9 100644 --- a/include/sys/thread.h +++ b/include/sys/thread.h @@ -16,8 +16,6 @@ #define THREAD_STOPPED (1 << 2) // Thread init flags: -// Initialize I/O context and open stdio -#define THREAD_INIT_IOCTX (1 << 1) // Initialize platform context #define THREAD_INIT_CTX (1 << 0) @@ -26,6 +24,8 @@ typedef uint64_t *mm_space_t; #include "sys/amd64/sys/thread.h" #endif +#define THREAD_MAX_FDS 16 + struct image_info { uintptr_t image_end; uintptr_t brk; @@ -47,7 +47,7 @@ struct thread { int exit_code; struct vfs_ioctx ioctx; - struct ofile fds[4]; + struct ofile *fds[THREAD_MAX_FDS]; // Signals uint32_t sigq; diff --git a/sys/amd64/hw/ps2.c b/sys/amd64/hw/ps2.c index e94dcc7..a36523b 100644 --- a/sys/amd64/hw/ps2.c +++ b/sys/amd64/hw/ps2.c @@ -33,7 +33,7 @@ uint32_t ps2_irq_keyboard(void *ctx) { char key_char = ps2_key_table_0[key]; if (key_char != 0) { - //tty_buffer_write(0, key_char); + tty_buffer_write(0, key_char); } } diff --git a/sys/amd64/hw/rs232.c b/sys/amd64/hw/rs232.c index ba71fb7..7b19080 100644 --- a/sys/amd64/hw/rs232.c +++ b/sys/amd64/hw/rs232.c @@ -48,7 +48,7 @@ static uint32_t rs232_irq(void *ctx) { c = '\n'; } - //tty_buffer_write(0, c); + tty_buffer_write(0, c); } return has_data ? IRQ_HANDLED : IRQ_UNHANDLED; diff --git a/sys/amd64/kernel.c b/sys/amd64/kernel.c index 169e140..2572f18 100644 --- a/sys/amd64/kernel.c +++ b/sys/amd64/kernel.c @@ -64,7 +64,7 @@ void kernel_main(struct amd64_loader_data *data) { pci_init(); vfs_init(); - //tty_init(); + tty_init(); if (data->initrd_ptr) { // Create ram0 block device ramblk_init(MM_VIRTUALIZE(data->initrd_ptr), data->initrd_len); diff --git a/sys/amd64/sys/thread.c b/sys/amd64/sys/thread.c index 630e7f3..b009ee2 100644 --- a/sys/amd64/sys/thread.c +++ b/sys/amd64/sys/thread.c @@ -102,14 +102,6 @@ int thread_platctx_init(struct thread *t, uintptr_t entry, void *arg) { return 0; } -static int thread_ioctx_init(struct thread *t, uint32_t init_flags) { - _assert(t); - - // Setup default I/O context - - return 0; -} - int thread_init( struct thread *t, mm_space_t space, @@ -191,11 +183,6 @@ int thread_init( thread_platctx_init(t, entry, arg); } - // 4. Setup I/O context if requested - if (init_flags & THREAD_INIT_IOCTX) { - thread_ioctx_init(t, init_flags); - } - return 0; } @@ -204,7 +191,7 @@ void thread_cleanup(struct thread *t) { // Release files for (size_t i = 0; i < 4; ++i) { - if (t->fds[i].vnode) { + if (t->fds[i]) { //vfs_close(&t->ioctx, &t->fds[i]); } } diff --git a/sys/amd64/sys_file.c b/sys/amd64/sys_file.c index 8cebf99..a5a6684 100644 --- a/sys/amd64/sys_file.c +++ b/sys/amd64/sys_file.c @@ -10,24 +10,33 @@ #include "sys/debug.h" ssize_t sys_read(int fd, void *buf, size_t lim) { - return -EINVAL; - //if (fd >= 4 || fd < 0) { - // return -EBADF; - //} - //struct thread *thr = get_cpu()->thread; - //_assert(thr); + struct thread *thr = get_cpu()->thread; + _assert(thr); - //struct ofile *of = &thr->fds[fd]; + if (fd < 0 || fd >= THREAD_MAX_FDS) { + return -EBADF; + } - //if (!of->vnode) { - // return -EBADF; - //} + if (thr->fds[fd] == NULL) { + return -EBADF; + } - //return vfs_read(&thr->ioctx, of, buf, lim); + return vfs_read(&thr->ioctx, thr->fds[fd], buf, lim); } ssize_t sys_write(int fd, const void *buf, size_t lim) { - return -EINVAL; + struct thread *thr = get_cpu()->thread; + _assert(thr); + + if (fd < 0 || fd >= THREAD_MAX_FDS) { + return -EBADF; + } + + if (thr->fds[fd] == NULL) { + return -EBADF; + } + + return vfs_write(&thr->ioctx, thr->fds[fd], buf, lim); } ssize_t sys_readdir(int fd, struct dirent *ent) { diff --git a/sys/init.c b/sys/init.c index e1b3297..412f645 100644 --- a/sys/init.c +++ b/sys/init.c @@ -72,6 +72,33 @@ static void user_init_start(void) { kfree(file_buffer); + // Setup I/O context for init task + struct ofile *stdin, *stdout, *stderr; + file_buffer = kmalloc(sizeof(struct ofile) * 2); + _assert(file_buffer); + + stdin = (struct ofile *) file_buffer; + stdout = (struct ofile *) (file_buffer + sizeof(struct ofile)); + stderr = stdout; + + // TODO: use dev_find and open its node instead + struct vnode *stdout_device; + if ((res = dev_find(DEV_CLASS_CHAR, "tty0", &stdout_device)) != 0) { + panic("%s: %s\n", "tty0", kstrerror(res)); + } + + if ((res = vfs_open_vnode(&user_init->ioctx, stdin, stdout_device, O_RDONLY)) != 0) { + panic("Failed to open stdin for init task: %s\n", kstrerror(res)); + } + if ((res = vfs_open_vnode(&user_init->ioctx, stdout, stdout_device, O_WRONLY)) != 0) { + panic("Failed to open stdout/stderr for init task: %s\n", kstrerror(res)); + } + + // TODO: use STDIN_/STDOUT_/STDERR_FILENO macros + user_init->fds[0] = stdin; + user_init->fds[1] = stdout; + user_init->fds[2] = stderr; + sched_add(user_init); } diff --git a/sys/tty.c b/sys/tty.c index fdad8dc..aa8cb6e 100644 --- a/sys/tty.c +++ b/sys/tty.c @@ -22,12 +22,6 @@ static struct chrdev _dev_tty0 = { .write = tty_write, .read = tty_read }; -static struct dev_entry _ent_tty0 = { - .dev = &_dev_tty0, - .dev_class = DEV_CLASS_CHAR, - .dev_subclass = DEV_CHAR_TTY, - .dev_name = "tty0" -}; static struct ring tty_ring = {0}; @@ -38,7 +32,8 @@ void tty_buffer_write(int tty_no, char c) { void tty_init(void) { ring_init(&tty_ring, 16); - dev_entry_add(&_ent_tty0); + + dev_add(DEV_CLASS_CHAR, DEV_CHAR_TTY, &_dev_tty0, "tty0"); } // TODO: multiple ttys diff --git a/sys/vfs/vfs.c b/sys/vfs/vfs.c index 28d8dfe..c10369f 100644 --- a/sys/vfs/vfs.c +++ b/sys/vfs/vfs.c @@ -6,6 +6,7 @@ #include "sys/debug.h" #include "sys/errno.h" #include "sys/fcntl.h" +#include "sys/chr.h" static int vfs_find_internal(struct vfs_ioctx *ctx, struct vnode *at, const char *path, struct vnode **child); @@ -348,6 +349,45 @@ int vfs_find(struct vfs_ioctx *ctx, struct vnode *rel, const char *path, struct /////////// +int vfs_open_vnode(struct vfs_ioctx *ctx, struct ofile *fd, struct vnode *node, int opt) { + int res; + + _assert(ctx); + _assert(fd); + _assert(node); + + if (opt & O_DIRECTORY) { + panic("NYI: O_DIRECTORY\n"); + } + + // 1. If file operations struct specifies some non-trivial open() + // function for the node - use it + if (node->op && node->op->open) { + if ((res = node->op->open(node, opt)) != 0) { + return res; + } + } + + // 2. Setup ofile + fd->pos = 0; + fd->vnode = node; + fd->flags = 0; + + switch (opt & O_ACCMODE) { + case O_RDONLY: + fd->flags |= OF_READABLE; + break; + case O_WRONLY: + fd->flags |= OF_WRITABLE; + break; + case O_RDWR: + fd->flags |= OF_READABLE | OF_WRITABLE; + break; + } + + return 0; +} + int vfs_open(struct vfs_ioctx *ctx, struct ofile *fd, const char *path, int opt, int mode) { struct vnode *node; int res; @@ -358,27 +398,14 @@ int vfs_open(struct vfs_ioctx *ctx, struct ofile *fd, const char *path, int opt, // 1. Try to find the file if ((res = vfs_find(ctx, ctx->cwd_vnode, path, &node)) != 0) { - panic("NYI: O_CREAT\n"); - } - - if (opt & O_DIRECTORY) { - panic("NYI: O_DIRECTORY\n"); - } - - // 2. If file operations struct specifies some non-trivial open() - // function for the node - use it - if (node->op && node->op->open) { - if ((res = node->op->open(node, opt)) != 0) { + if (opt & O_CREAT) { + panic("NYI: O_CREAT\n"); + } else { return res; } } - // 3. Setup ofile - fd->pos = 0; - fd->vnode = node; - fd->flags = opt; - - return 0; + return vfs_open_vnode(ctx, fd, node, opt); } void vfs_close(struct vfs_ioctx *ctx, struct ofile *fd) { @@ -405,9 +432,43 @@ int vfs_stat(struct vfs_ioctx *ctx, const char *path, struct stat *st) { return node->op->stat(node, st); } +ssize_t vfs_write(struct vfs_ioctx *ctx, struct ofile *fd, const void *buf, size_t count) { + struct vnode *node; + + _assert(fd); + + if (!(fd->flags & OF_WRITABLE) || (fd->flags & OF_DIRECTORY)) { + return -EINVAL; + } + + node = fd->vnode; + + _assert(ctx); + _assert(buf); + _assert(node); + + switch (node->type) { + case VN_REG: + _assert(node->op && node->op->write); + return node->op->write(fd, buf, count); + case VN_CHR: + _assert(node->dev && ((struct chrdev *) node->dev)->write); + return chr_write(node->dev, buf, fd->pos, count); + + case VN_DIR: + default: + // Cannot do such things + return -EINVAL; + } +} + ssize_t vfs_read(struct vfs_ioctx *ctx, struct ofile *fd, void *buf, size_t count) { struct vnode *node; + if (!(fd->flags & OF_READABLE)) { + return -EINVAL; + } + _assert(fd); node = fd->vnode; @@ -420,6 +481,9 @@ ssize_t vfs_read(struct vfs_ioctx *ctx, struct ofile *fd, void *buf, size_t coun case VN_REG: _assert(node->op && node->op->read); return node->op->read(fd, buf, count); + case VN_CHR: + _assert(node->dev && ((struct chrdev *) node->dev)->read); + return chr_read(node->dev, buf, fd->pos, count); case VN_DIR: default: