From d68537c1ca22d58f1c219d970d5aa462df9e0c6b Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sat, 22 Feb 2025 02:18:33 -0500 Subject: kernel: vfs: Add support for write() Signed-off-by: Ian Moffett --- sys/kern/kern_descrip.c | 50 ++++++++++++++++++++++++++++++++++++++++++------- sys/kern/kern_syscall.c | 1 + sys/kern/vfs_subr.c | 13 +++++++++++++ sys/kern/vfs_syscalls.c | 12 ++++++++++++ 4 files changed, 69 insertions(+), 7 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index d1ed044..201db3e 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -135,15 +136,16 @@ fd_close(unsigned int fd) } /* - * Read bytes from a file using a file + * Read/write bytes to/from a file using a file * descriptor number. * * @fd: File descriptor number. - * @buf: Buffer to read into. + * @buf: Buffer with data to read/write * @count: Number of bytes to read. + * @write: Set to 1 for writes */ -int -fd_read(unsigned int fd, void *buf, size_t count) +static int +fd_rw(unsigned int fd, void *buf, size_t count, uint8_t write) { char *kbuf = NULL; struct filedesc *filedes; @@ -173,13 +175,34 @@ fd_read(unsigned int fd, void *buf, size_t count) goto done; } + /* Check if this violates the file seal */ + if (!ISSET(filedes->flags, O_ALLOW_WR) && write) { + return -EPERM; + } else if (ISSET(O_RDONLY, filedes->flags) && write) { + return -EPERM; + } + sio.len = count; sio.buf = kbuf; sio.offset = filedes->offset; - if ((count = vfs_vop_read(filedes->vp, &sio)) < 0) { - retval = -EIO; - goto done; + if (write) { + /* Copy in user buffer */ + if (copyin(buf, kbuf, count) < 0) { + retval = -EFAULT; + goto done; + } + + /* Call VFS write hook */ + if ((count = vfs_vop_write(filedes->vp, &sio)) < 0) { + retval = -EIO; + goto done; + } + } else { + if ((count = vfs_vop_read(filedes->vp, &sio)) < 0) { + retval = -EIO; + goto done; + } } if (copyout(kbuf, buf, count) < 0) { @@ -195,6 +218,18 @@ done: return retval; } +int +fd_read(unsigned int fd, void *buf, size_t count) +{ + return fd_rw(fd, buf, count, 0); +} + +int +fd_write(unsigned int fd, void *buf, size_t count) +{ + return fd_rw(fd, buf, count, 1); +} + /* * Open a file and get a file descriptor * number. @@ -224,6 +259,7 @@ fd_open(const char *pathname, int flags) } filedes->vp = nd.vp; + filedes->flags = flags; return filedes->fdno; } diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c index 1d961a7..986d82a 100644 --- a/sys/kern/kern_syscall.c +++ b/sys/kern/kern_syscall.c @@ -41,6 +41,7 @@ scret_t(*g_sctab[])(struct syscall_args *) = { sys_close, /* SYS_close */ sys_stat, /* SYS_stat */ sys_sysctl, /* SYS_sysctl */ + sys_write, /* SYS_write */ }; const size_t MAX_SYSCALLS = NELEM(g_sctab); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index f67bcfe..da0a4f9 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -166,6 +166,19 @@ vfs_vop_read(struct vnode *vp, struct sio_txn *sio) return vops->read(vp, sio); } +int +vfs_vop_write(struct vnode *vp, struct sio_txn *sio) +{ + const struct vops *vops = vp->vops; + + if (vops == NULL) + return -EIO; + if (vops->write == NULL) + return -EIO; + + return vops->write(vp, sio); +} + int vfs_vop_getattr(struct vnode *vp, struct vop_getattr_args *args) { diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index fa613c2..6f2d683 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -128,6 +128,18 @@ sys_read(struct syscall_args *scargs) scargs->arg2); } +/* + * arg0: fd + * arg1: buf + * arg2: count + */ +scret_t +sys_write(struct syscall_args *scargs) +{ + return fd_write(scargs->arg0, (void *)scargs->arg1, + scargs->arg2); +} + /* * arg0: path * arg1: buf -- cgit v1.2.3 From 218187d55e26c8bc9bd25881d5e84b38a3c28213 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sat, 22 Feb 2025 02:21:55 -0500 Subject: kernel: dev: Add /dev/console Signed-off-by: Ian Moffett --- sys/dev/cons/cons.c | 48 ++++++++++++++++++++++++++++++++++++++++++++- sys/include/dev/cons/cons.h | 1 + sys/kern/init_main.c | 3 +++ 3 files changed, 51 insertions(+), 1 deletion(-) (limited to 'sys/kern') diff --git a/sys/dev/cons/cons.c b/sys/dev/cons/cons.c index c3a3197..0de5590 100644 --- a/sys/dev/cons/cons.c +++ b/sys/dev/cons/cons.c @@ -30,13 +30,16 @@ #include #include #include +#include #include #include #include +#include #include #include struct cons_screen g_root_scr = {0}; +static struct cdevsw cons_cdevsw; /* * Create a chracter descriptor for drawing @@ -89,7 +92,7 @@ static void cons_draw_cursor(struct cons_screen *scr, uint32_t color) { size_t idx; - + for (uint32_t cy = 0; cy < FONT_HEIGHT; ++cy) { for (uint32_t cx = 0; cx < FONT_WIDTH; ++cx) { idx = fbdev_get_index(&scr->fbdev, (scr->curs_col * FONT_WIDTH) + cx, (scr->curs_row * FONT_HEIGHT) + cy); @@ -141,6 +144,20 @@ cons_handle_special(struct cons_screen *scr, char c) return -1; } +/* + * Character device function. + */ +static int +dev_write(dev_t dev, struct sio_txn *sio, int flags) +{ + char *p = sio->buf; + + for (size_t i = 0; i < sio->len; ++i) { + cons_putch(&g_root_scr, p[i]); + } + + return sio->len; +} /* * Put a character on the screen. @@ -204,3 +221,32 @@ cons_init(void) g_root_scr.ncols = fbdev.width / FONT_WIDTH; g_root_scr.fbdev = fbdev; } + +/* + * Expose the console to /dev/console + */ +void +cons_expose(void) +{ + static int once = 0; + char devname[] = "console"; + devmajor_t major; + dev_t dev; + + /* Only run once */ + if (once) { + return; + } + + /* Register the device here */ + major = dev_alloc_major(); + dev = dev_alloc(major); + dev_register(major, dev, &cons_cdevsw); + devfs_create_entry(devname, major, dev, 0444); + once ^= 1; +} + +static struct cdevsw cons_cdevsw = { + .read = noread, + .write = dev_write +}; diff --git a/sys/include/dev/cons/cons.h b/sys/include/dev/cons/cons.h index fe7eb6d..3415617 100644 --- a/sys/include/dev/cons/cons.h +++ b/sys/include/dev/cons/cons.h @@ -56,6 +56,7 @@ struct cons_screen { }; void cons_init(void); +void cons_expose(void); int cons_putch(struct cons_screen *scr, char c); extern struct cons_screen g_root_scr; diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 1fb3418..f3f88d7 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -83,6 +83,9 @@ main(void) DRIVERS_INIT(); + /* Expose the console to devfs */ + cons_expose(); + /* Start scheduler and bootstrap APs */ sched_init(); mp_bootstrap_aps(&g_bsp_ci); -- cgit v1.2.3