From aac35bcbd3f4a1a3d963e90a7436a7dd6c10ac41 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Fri, 24 Dec 2021 17:07:38 +0000 Subject: [PATCH] Horizon init now initialises MIO using bootstrap handles --- photon/libc/sys/horizon/init.c | 106 ++++++++++++++++++++++++++++++- photon/libc/sys/horizon/unistd.c | 33 ++++++++-- 2 files changed, 134 insertions(+), 5 deletions(-) diff --git a/photon/libc/sys/horizon/init.c b/photon/libc/sys/horizon/init.c index a929705..b0bd32a 100644 --- a/photon/libc/sys/horizon/init.c +++ b/photon/libc/sys/horizon/init.c @@ -2,12 +2,19 @@ #include #include #include +#include #include +#include +#include +#include #include +#include #include "__init.h" #include "__heap.h" #include "__fio.h" +#define dbg_log(...) + static const char **environ = NULL; const char **__crt_environ() @@ -73,6 +80,92 @@ static void hang() } } +static void init_stdio_fd(int fd, mx_handle_t *handles, size_t nhandles) +{ + if (handles[0] == MX_NULL_HANDLE) { + dbg_log("** photon: FD %d is closed\n", fd); + return; + } + + mx_info_basic_t handle0_info; + mx_status_t err = mx_object_get_info(handles[0], MX_INFO_HANDLE_BASIC, &handle0_info, sizeof(handle0_info)); + if (err != MX_OK) { + /* bad handle. TODO report error somehow */ + return; + } + + mio_object *obj = NULL; + + if (handle0_info.type == MX_OBJECT_PIPE) { + obj = mio_pipe_create(handles[0]); + dbg_log("** photon: FD %d is a pipe\n", fd); + } else { + /* just assume all other stdio handles implement the file protocol over a tunnel */ + obj = mio_file_create(handles[0]); + dbg_log("** photon: FD %d is a file\n", fd); + } + + mio_fd_list_alloc_at(mio_global_fd_list(), obj, fd); +} + +static void init_stdio(mx_bootstrap_handle_t *handles, size_t nhandles) +{ + dbg_log("** photon: initialising stdio\n"); + bool no_fds = true; + int max_fd = 0; + for (size_t i = 0; i < nhandles; i++) { + uint32_t info = handles[i].info; + if (MX_B_HND_TYPE(info) != MX_B_FD) { + continue; + } + + no_fds = false; + int fd = MX_B_HND_ARG(info); + if (fd > max_fd) { + max_fd = fd; + } + } + + if (no_fds) { + dbg_log("** photon: we've been given no FDs\n"); + return; + } + + int nfds = max_fd + 1; + dbg_log("** photon: we've been given up to %d FDs\n", nfds); + + /* Supports up to two handles per FD */ + mx_handle_t fd_handles[nfds][2]; + memset(fd_handles, 0x0, sizeof(mx_handle_t) * 2 * nfds); + + for (size_t i = 0; i < nhandles; i++) { + uint32_t info = handles[i].info; + if (MX_B_HND_TYPE(info) != MX_B_FD) { + continue; + } + + int fd = MX_B_HND_ARG(info); + mx_handle_t *this_fd_handles = fd_handles[fd]; + + if (this_fd_handles[0] != MX_NULL_HANDLE) { + this_fd_handles[1] = handles[i].handle; + } else { + this_fd_handles[0] = handles[i].handle; + } + } + + for (int i = 0; i < nfds; i++) { + size_t n = 1; + if (fd_handles[i][1] != MX_NULL_HANDLE) { + n++; + } + + //dbg_log("** photon: handles for FD %d = { %x, %x }\n", i, fd_handles[i][0], fd_handles[i][1]); + + init_stdio_fd(i, fd_handles[i], n); + } +} + int __crt_init(mx_handle_t bootstrap) { size_t msg_size = 0; @@ -81,7 +174,7 @@ int __crt_init(mx_handle_t bootstrap) if (status != MX_OK) { /* TODO replace with a better error handler */ - printf("error: cannot read bootstrap message from handle %lx (error %d)\n", + dbg_log("error: cannot read bootstrap message from handle %lx (error %d)\n", bootstrap, status); hang(); } @@ -94,20 +187,31 @@ int __crt_init(mx_handle_t bootstrap) const char *argv[msg->args_num + 1]; const char *envp[msg->environ_num + 1]; +#ifdef LIBSYSTEM_STATIC mx_bootstrap_handle_t start_handles[nr_handles + 1]; start_handles[nr_handles].handle = bootstrap; start_handles[nr_handles].info = MX_B_HND(MX_B_TUNNEL_BTSTP, 0); +#else + mx_bootstrap_handle_t start_handles[nr_handles]; + mx_handle_close(bootstrap); +#endif argv[msg->args_num] = NULL; envp[msg->environ_num] = NULL; environ = envp; parse_args(msg, handles, argv, envp, nr_handles, start_handles); +#ifdef LIBSYSTEM_STATIC mx_bootstrap_handle_init(start_handles, nr_handles + 1); +#else + mx_bootstrap_handle_init(start_handles, nr_handles); +#endif + init_stdio(start_handles, nr_handles); int ret = main(msg->args_num, argv); __crt_run_atexit(); + mio_destroy_global_fd_list(); mx_task_kill(mx_bootstrap_handle_get(MX_B_TASK_SELF), ret); /* unreachable */ diff --git a/photon/libc/sys/horizon/unistd.c b/photon/libc/sys/horizon/unistd.c index 6a8fea3..c56830a 100644 --- a/photon/libc/sys/horizon/unistd.c +++ b/photon/libc/sys/horizon/unistd.c @@ -1,22 +1,47 @@ #include +#include #include ssize_t read(int fd, void *buf, size_t count) { - return mio_read(fd, buf, count); + ssize_t ret = mio_read(fd, buf, count); + if (ret < 0) { + __set_errno(-(int)ret); + return -1; + } + + return ret; } ssize_t write(int fd, const void *buf, size_t count) { - return mio_write(fd, buf, count); + ssize_t ret = mio_write(fd, buf, count); + if (ret < 0) { + __set_errno(-(int)ret); + return -1; + } + + return ret; } int open(const char *pathname, int flags) { - return mio_open(pathname, flags); + int ret = mio_open(pathname, flags); + if (ret < 0) { + __set_errno(-ret); + return -1; + } + + return ret; } int close(int fd) { - return mio_close(fd); + int ret = mio_close(fd); + if (ret < 0) { + __set_errno(-ret); + return -1; + } + + return ret; }