From ce19ccc5ebf20a799e59aa79d77c8d4c07631523 Mon Sep 17 00:00:00 2001 From: Alexander Jung Date: Fri, 15 Jan 2021 23:44:56 +0100 Subject: [PATCH] devfs: Introduce stdout device This commit introduces a new device, `/dev/stdout` which pipes output to the platform console. Signed-off-by: Alexander Jung Reviewed-by: Cezar Craciunoiu Tested-by: Unikraft CI GitHub-Pull-Request: #104 --- lib/devfs/Config.uk | 5 ++ lib/devfs/Makefile.uk | 1 + lib/devfs/stdout.c | 119 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 lib/devfs/stdout.c diff --git a/lib/devfs/Config.uk b/lib/devfs/Config.uk index af61747f2..660fa4119 100644 --- a/lib/devfs/Config.uk +++ b/lib/devfs/Config.uk @@ -25,4 +25,9 @@ if LIBDEVFS default y if LIBDEVFS_AUTOMOUNT select LIBDEVFS_DEV_NULL_ZERO default n + + config LIBDEVFS_DEV_STDOUT + bool "Register stdout device" + default y if LIBDEVFS_AUTOMOUNT + default n endif diff --git a/lib/devfs/Makefile.uk b/lib/devfs/Makefile.uk index b23ebf151..48445f3e9 100644 --- a/lib/devfs/Makefile.uk +++ b/lib/devfs/Makefile.uk @@ -7,3 +7,4 @@ LIBDEVFS_CFLAGS-$(call gcc_version_ge,8,0) += -Wno-cast-function-type LIBDEVFS_SRCS-y += $(LIBDEVFS_BASE)/device.c LIBDEVFS_SRCS-y += $(LIBDEVFS_BASE)/devfs_vnops.c LIBDEVFS_SRCS-$(CONFIG_LIBDEVFS_DEV_NULL_ZERO) += $(LIBDEVFS_BASE)/null.c +LIBDEVFS_SRCS-$(CONFIG_LIBDEVFS_DEV_STDOUT) += $(LIBDEVFS_BASE)/stdout.c diff --git a/lib/devfs/stdout.c b/lib/devfs/stdout.c new file mode 100644 index 000000000..e44396e44 --- /dev/null +++ b/lib/devfs/stdout.c @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Authors: Alexander Jung + * + * Copyright (c) 2021, Lancaster University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_LIBDEVFS_DEV_STDOUT + +#define DEV_STDOUT_NAME "stdout" + +static int __write_fn(void *dst __unused, void *src, size_t *cnt) +{ + int ret = ukplat_coutk(src, *cnt); + + if (ret < 0) + /* TODO: remove -1 when vfscore switches to negative + * error numbers + */ + return ret * -1; + + *cnt = (size_t) ret; + return 0; +} + +/* One function for stderr and stdout */ +int dev_stdout_write(struct device *dev __unused, struct uio *uio, + int flags __unused) +{ + return vfscore_uioforeach(__write_fn, NULL, uio->uio_resid, uio); +} + +int dev_stdout_open(struct device *device __unused, int mode __unused) +{ + return 0; +} + +int dev_stdout_close(struct device *device __unused) +{ + return 0; +} + +int dev_stdout_read(struct device *dev __unused, struct uio *uio, + int flags __unused) +{ + uio->uio_resid = uio->uio_iov->iov_len; + return 0; +} + +static struct devops stdout_devops = { + .read = dev_stdout_read, + .write = dev_stdout_write, + .open = dev_stdout_open, + .close = dev_stdout_close, +}; + +static struct driver drv_stdout = { + .devops = &stdout_devops, + .devsz = 0, + .name = DEV_STDOUT_NAME +}; + +#endif /* CONFIG_LIBDEVFS_DEV_STDOUT */ + +static int devfs_register_stdout(void) +{ + struct device *dev; + +#ifdef CONFIG_LIBDEVFS_DEV_STDOUT + uk_pr_debug("Register '%s' to devfs\n", DEV_STDOUT_NAME); + + /* register /dev/stdout */ + dev = device_create(&drv_stdout, DEV_STDOUT_NAME, D_CHR); + if (dev == NULL) { + uk_pr_err("Failed to register '%s' to devfs\n", + DEV_STDOUT_NAME); + return -1; + } +#endif /* LIBDEVFS_DEV_STDOUT */ + + return 0; +} + +devfs_initcall(devfs_register_stdout); -- 2.39.5