summaryrefslogtreecommitdiff
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
parent1bb4fdc3a2c725276d457d2fa7cd1962d3e232d6 (diff)
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>
-rw-r--r--libmachdev/ds_routines.c15
-rw-r--r--libmachdev/machdev.h5
-rw-r--r--libmachdev/trivfs_server.c154
3 files changed, 148 insertions, 26 deletions
diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c
index da5e47e2..53e0c080 100644
--- a/libmachdev/ds_routines.c
+++ b/libmachdev/ds_routines.c
@@ -65,6 +65,7 @@
#include <hurd.h>
#include <mach.h>
+#include <device/device.h> /* fallback to kernel device */
#include "device_S.h"
#include "notify_S.h"
@@ -94,7 +95,8 @@ ds_device_open (mach_port_t open_port, mach_port_t reply_port,
char *name, device_t *devp, mach_msg_type_name_t *devicePoly)
{
int i;
- io_return_t err;
+ mach_port_t dev_master;
+ io_return_t err = D_NO_SUCH_DEVICE;
/* Open must be called on the master device port. */
if (!machdev_is_master_device (open_port))
@@ -108,11 +110,18 @@ ds_device_open (mach_port_t open_port, mach_port_t reply_port,
for (i = 0; i < num_emul; i++)
{
err = (*emulation_list[i]->open) (reply_port, reply_port_type,
- mode, name, devp, devicePoly);
+ mode, name, devp, devicePoly);
if (err != D_NO_SUCH_DEVICE)
- break;
+ break;
}
+ /* Fall back to opening kernel device master */
+ if (err)
+ {
+ get_privileged_ports(NULL, &dev_master);
+ err = device_open (dev_master, mode, name, devp);
+ *devicePoly = MACH_MSG_TYPE_MOVE_SEND;
+ }
return err;
}
diff --git a/libmachdev/machdev.h b/libmachdev/machdev.h
index 9b2dbd31..55a56e0d 100644
--- a/libmachdev/machdev.h
+++ b/libmachdev/machdev.h
@@ -32,9 +32,8 @@ void machdev_register (struct machdev_device_emulation_ops *ops);
void machdev_device_init(void);
void * machdev_server(void *);
error_t machdev_create_device_port (size_t size, void *result);
-
-int machdev_trivfs_init(void);
-void machdev_trivfs_server(void);
+int machdev_trivfs_init(mach_port_t bootstrap_resume_task, const char *name, mach_port_t *bootstrap);
+void machdev_trivfs_server(mach_port_t bootstrap);
boolean_t machdev_is_master_device (mach_port_t port);
#endif
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