aboutsummaryrefslogtreecommitdiff
path: root/libmachdev/trivfs_server.c
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2020-07-25 11:18:44 +1000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-07-25 13:09:31 +0200
commit67c9d475e7204296ca9bcfbd08a896df1a87e74a (patch)
tree2a1d624c891740becfb2b95dd547dba4aa779036 /libmachdev/trivfs_server.c
parent1bb4fdc3a2c725276d457d2fa7cd1962d3e232d6 (diff)
downloadhurd-67c9d475e7204296ca9bcfbd08a896df1a87e74a.tar.gz
hurd-67c9d475e7204296ca9bcfbd08a896df1a87e74a.tar.bz2
hurd-67c9d475e7204296ca9bcfbd08a896df1a87e74a.zip
libmachdev: Add resume for bootstrap server
machdev users can now pass along a port to the next translator in the bootstrap chain (bootstrap_resume_task), that they'll get from their command line set by the bootloader. machdev will then call task_resume on it as appropriate. It will also have the opportunity to get fsys_getpriv calls, and thus redirect the device master port, thus having the opportunity to expose its devices on the device master port, as if they were handled by the kernel. Message-Id: <20200725011847.186969-1-damien@zamaudio.com>
Diffstat (limited to 'libmachdev/trivfs_server.c')
-rw-r--r--libmachdev/trivfs_server.c154
1 files changed, 134 insertions, 20 deletions
diff --git a/libmachdev/trivfs_server.c b/libmachdev/trivfs_server.c
index d6bafccb..05efde2e 100644
--- a/libmachdev/trivfs_server.c
+++ b/libmachdev/trivfs_server.c
@@ -27,9 +27,12 @@
#include <hurd/ports.h>
#include <hurd/trivfs.h>
#include <hurd.h>
+#include <device/device.h> /* mach console */
+#include "libdiskfs/diskfs.h"
#include "device_S.h"
#include "notify_S.h"
+#include "fsys_S.h"
static struct port_bucket *port_bucket;
@@ -90,13 +93,31 @@ do_mach_notify_dead_name (struct port_info *pi,
boolean_t
machdev_is_master_device (mach_port_t port)
{
- struct port_info *pi = ports_lookup_port (port_bucket, port,
+ struct port_info *pi0 = ports_lookup_port (port_bucket, port,
trivfs_protid_class);
- if (pi == NULL)
- return FALSE;
+ struct port_info *pi1 = ports_lookup_port (port_bucket, port,
+ trivfs_cntl_class);
+ if (pi0 == NULL)
+ {
+ if (pi1 == NULL)
+ {
+ return FALSE;
+ }
+ else
+ {
+ ports_port_deref (pi1);
+ return TRUE;
+ }
+ }
+ else
+ {
+ ports_port_deref (pi0);
- ports_port_deref (pi);
- return TRUE;
+ if (pi1 != NULL)
+ ports_port_deref (pi1);
+
+ return TRUE;
+ }
}
error_t
@@ -114,11 +135,106 @@ trivfs_append_args (struct trivfs_control *fsys, char **argz, size_t *argz_len)
return err;
}
-int machdev_trivfs_init()
+/* This is fraud */
+kern_return_t
+trivfs_S_fsys_startup (mach_port_t bootport,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ int flags,
+ mach_port_t cntl,
+ mach_port_t *realnode,
+ mach_msg_type_name_t *realnodetype)
+{
+ *realnode = MACH_PORT_NULL;
+ *realnodetype = MACH_MSG_TYPE_MOVE_SEND;
+ return 0;
+}
+
+/* Override the privileged ports for booting the system */
+kern_return_t
+trivfs_S_fsys_getpriv (struct diskfs_control *init_bootstrap_port,
+ mach_port_t reply, mach_msg_type_name_t reply_type,
+ mach_port_t *host_priv, mach_msg_type_name_t *hp_type,
+ mach_port_t *dev_master, mach_msg_type_name_t *dm_type,
+ mach_port_t *fstask, mach_msg_type_name_t *task_type)
+{
+ error_t err;
+ mach_port_t right;
+ struct port_info *server_info;
+
+ err = ports_create_port (trivfs_protid_class, port_bucket,
+ sizeof (struct port_info), &server_info);
+ assert_perror_backtrace (err);
+ right = ports_get_send_right (server_info);
+ ports_port_deref (server_info);
+
+ err = get_privileged_ports (host_priv, NULL);
+ if (!err)
+ {
+ *dev_master = right;
+ *fstask = mach_task_self ();
+ *hp_type = *dm_type = MACH_MSG_TYPE_COPY_SEND;
+ *task_type = MACH_MSG_TYPE_COPY_SEND;
+ }
+ return err;
+}
+
+static void
+resume_bootstrap_server(mach_port_t server_task, const char *server_name)
+{
+ error_t err;
+ mach_port_t right;
+ mach_port_t dev, cons;
+ struct port_info *server_info;
+
+ assert_backtrace (server_task != MACH_PORT_NULL);
+
+ err = ports_create_port (trivfs_cntl_class, port_bucket,
+ sizeof (struct port_info), &server_info);
+ assert_perror_backtrace (err);
+ right = ports_get_send_right (server_info);
+ ports_port_deref (server_info);
+ err = task_set_special_port (server_task, TASK_BOOTSTRAP_PORT, right);
+ assert_perror_backtrace (err);
+ err = mach_port_deallocate (mach_task_self (), right);
+ assert_perror_backtrace (err);
+
+ err = task_resume (server_task);
+ assert_perror_backtrace (err);
+
+ /* Make sure we have a console */
+ err = get_privileged_ports (NULL, &dev);
+ assert_perror_backtrace (err);
+ err = device_open (dev, D_READ|D_WRITE, "console", &cons);
+ mach_port_deallocate (mach_task_self (), dev);
+ assert_perror_backtrace (err);
+ stdin = mach_open_devstream (cons, "r");
+ stdout = stderr = mach_open_devstream (cons, "w");
+ mach_port_deallocate (mach_task_self (), cons);
+
+ printf (" %s", server_name);
+ fflush (stdout);
+}
+
+int
+machdev_trivfs_init(mach_port_t bootstrap_resume_task, const char *name, mach_port_t *bootstrap)
{
port_bucket = ports_create_bucket ();
trivfs_cntl_class = ports_create_class (trivfs_clean_cntl, 0);
trivfs_protid_class = ports_create_class (trivfs_clean_protid, 0);
+
+ if (bootstrap_resume_task != MACH_PORT_NULL)
+ {
+ resume_bootstrap_server(bootstrap_resume_task, name);
+ *bootstrap = MACH_PORT_NULL;
+ }
+ else
+ {
+ task_get_bootstrap_port (mach_task_self (), bootstrap);
+ if (*bootstrap == MACH_PORT_NULL)
+ error (1, 0, "must be started as a translator");
+ }
+
return 0;
}
@@ -166,23 +282,21 @@ trivfs_modify_stat (struct trivfs_protid *cred, io_statbuf_t *stat)
{
}
-void machdev_trivfs_server()
+void
+machdev_trivfs_server(mach_port_t bootstrap)
{
- mach_port_t bootstrap;
- struct trivfs_control *fsys;
+ struct trivfs_control *fsys = NULL;
int err;
- task_get_bootstrap_port (mach_task_self (), &bootstrap);
- if (bootstrap == MACH_PORT_NULL)
- error (1, 0, "must be started as a translator");
-
- /* Reply to our parent. */
- err = trivfs_startup (bootstrap, 0,
- trivfs_cntl_class, port_bucket,
- trivfs_protid_class, port_bucket, &fsys);
- mach_port_deallocate (mach_task_self (), bootstrap);
- if (err)
- error (1, err, "Contacting parent");
+ if (bootstrap != MACH_PORT_NULL)
+ {
+ err = trivfs_startup (bootstrap, 0,
+ trivfs_cntl_class, port_bucket,
+ trivfs_protid_class, port_bucket, &fsys);
+ mach_port_deallocate (mach_task_self (), bootstrap);
+ if (err)
+ error (1, err, "Contacting parent");
+ }
/* Launch. */
do