Horizon init now initialises MIO using bootstrap handles

This commit is contained in:
2021-12-24 17:07:38 +00:00
parent 62319ba0d2
commit aac35bcbd3
2 changed files with 134 additions and 5 deletions

View File

@@ -2,12 +2,19 @@
#include <magenta/tunnel.h>
#include <magenta/bootstrap.h>
#include <magenta/errors.h>
#include <magenta/handle.h>
#include <magenta/misc.h>
#include <magenta/object.h>
#include <mio/object.h>
#include <mio/fd.h>
#include <stdio.h>
#include <string.h>
#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 */

View File

@@ -1,22 +1,47 @@
#include <unistd.h>
#include <errno.h>
#include <mio/fs.h>
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;
}