Hello everyone!
Here's my attempt to add storeio to the GNU/Hurd bootstrap chain to fix
GPLv2 vs. GPLv3 license incompatibility between ext2fs and libparted.
So far, I've managed to add it to the bootstrap chain in grub.cfg:
module /hurd/rumpdisk.static rumpdisk \
    --next-task='${storeio-task}' \
    '$(disk-task=task-create)'
module /hurd/storeio.static storeio \
    --next-task='${fs-task}' -T typed '${root}' \
    '$(storeio-task=task-create)'
module /hurd/ext2fs.static ext2fs \
    --multiboot-command-line='${kernel-command-line}' \
    --exec-server-task='${exec-task}' -T typed '${root}' \
    '$(fs-task=task-create)'

The system boots, but I don't fully understand how to access the store provided
by storeio if I remove the -T typed '${root}' from the ext2fs arguments.
I tried extending libdiskfs/init-main.c so that at system startup, the store is accessed via store_create instead of store_parsed_open, which in turn accesses
the parent task, but boot fails with the error code MIG_BAD_ID. I spent some
time trying to figure this out on my own, but my knowledge is still lacking.
So any advice and comments are welcome!

--
Mikhail Karpov
From 3751be3c72e3b9ac038289e1f003c77bab95fcbe Mon Sep 17 00:00:00 2001
From: Mikhail Karpov <[email protected]>
Date: Fri, 24 Apr 2026 18:50:10 +0700
Subject: [PATCH] Adding storeio to the bootstrap chain

---
 libdiskfs/boot-start.c     |   2 +-
 libdiskfs/diskfs.h         |   2 +
 libdiskfs/init-main.c      |  22 ++++--
 libmachdev/trivfs_server.c |  24 +++---
 libmachdev/trivfs_server.h |   4 +
 storeio/Makefile           |   8 +-
 storeio/dev.c              |   2 +-
 storeio/dev.h              |   4 +-
 storeio/storeio.c          | 150 +++++++++++++++++++++++++++++++++----
 9 files changed, 178 insertions(+), 40 deletions(-)

diff --git a/libdiskfs/boot-start.c b/libdiskfs/boot-start.c
index 93738b42..fcb74afa 100644
--- a/libdiskfs/boot-start.c
+++ b/libdiskfs/boot-start.c
@@ -45,7 +45,7 @@ static struct port_info *bootinfo;
 static mach_port_t diskfs_exec_ctl;
 extern task_t diskfs_exec_server_task;
 extern task_t diskfs_kernel_task;
-static task_t parent_task = MACH_PORT_NULL;
+task_t parent_task = MACH_PORT_NULL;
 
 static pthread_mutex_t execstartlock;
 static pthread_cond_t execstarted;
diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h
index 4473a3c2..b1c06d4a 100644
--- a/libdiskfs/diskfs.h
+++ b/libdiskfs/diskfs.h
@@ -30,6 +30,8 @@
 #include <features.h>
 #include <refcount.h>
 
+extern task_t parent_task;
+
 #ifdef DISKFS_DEFINE_EXTERN_INLINE
 #define DISKFS_EXTERN_INLINE
 #else
diff --git a/libdiskfs/init-main.c b/libdiskfs/init-main.c
index 69c30fd1..c2e229c5 100644
--- a/libdiskfs/init-main.c
+++ b/libdiskfs/init-main.c
@@ -31,6 +31,7 @@ diskfs_init_main (struct argp *startup_argp,
 {
   error_t err;
   struct store_argp_params store_params = { 0 };
+  //store_params.store_optional = 1;
   struct store *store;
 
   /* We must use ARGP_IN_ORDER for the parsing of --boot-command to work.  */
@@ -40,9 +41,12 @@ diskfs_init_main (struct argp *startup_argp,
   assert_perror_backtrace (err);
   *store_parsed = store_params.result;
 
-  err = store_parsed_name (*store_parsed, &diskfs_disk_name);
-  if (err)
-    error (2, err, "store_parsed_name");
+  //if (!diskfs_boot_filesystem ())
+  //  {
+      err = store_parsed_name (*store_parsed, &diskfs_disk_name);
+      if (err)
+        error (2, err, "store_parsed_name");
+  //  }
 
   /* This must come after the args have been parsed, as this is where the
      host priv ports are set for booting.  */
@@ -63,8 +67,16 @@ diskfs_init_main (struct argp *startup_argp,
   if (err)
     error (4, err, "diskfs_init_diskfs");
 
-  err = store_parsed_open (*store_parsed, diskfs_readonly ? STORE_READONLY : 0,
-			   &store);
+  //if (diskfs_boot_filesystem ())
+  //  {
+  //    err = store_create (parent_task, diskfs_readonly ? STORE_READONLY : 0,
+  //                        0, &store);
+  //    diskfs_disk_name = "storeio";
+  //  }
+  //else
+    err = store_parsed_open (*store_parsed,
+                             diskfs_readonly ? STORE_READONLY : 0, &store);
+
   if (err)
     error (3, err, "%s", diskfs_disk_name);
 
diff --git a/libmachdev/trivfs_server.c b/libmachdev/trivfs_server.c
index 2c905a63..475053ca 100644
--- a/libmachdev/trivfs_server.c
+++ b/libmachdev/trivfs_server.c
@@ -49,12 +49,12 @@
 struct port_bucket *port_bucket;
 
 /* Trivfs hooks.  */
-int trivfs_fstype = FSTYPE_MISC;
-int trivfs_fsid = 0;
-int trivfs_support_read = 0;
-int trivfs_support_write = 0;
-int trivfs_support_exec = 0;
-int trivfs_allow_open = O_READ | O_WRITE;
+int __attribute__ ((weak)) trivfs_fstype = FSTYPE_MISC;
+int __attribute__ ((weak)) trivfs_fsid = 0;
+int __attribute__ ((weak)) trivfs_support_read = 0;
+int __attribute__ ((weak)) trivfs_support_write = 0;
+int __attribute__ ((weak)) trivfs_support_exec = 0;
+int __attribute__ ((weak)) trivfs_allow_open = O_READ | O_WRITE;
 
 /* Our port classes */
 struct port_class *trivfs_cntl_class;
@@ -80,7 +80,7 @@ struct port_class *machdev_shutdown_notify_class;
 static void arrange_shutdown_notification (void);
 
 /* Our parent's task, if applicable */
-static task_t parent_task;
+task_t parent_task;
 
 /* Our argument vector */
 static char **machdev_argv;
@@ -124,7 +124,7 @@ machdev_is_master_device (mach_port_t port)
   return ret;
 }
 
-error_t
+error_t __attribute__ ((weak))
 trivfs_append_args (struct trivfs_control *fsys, char **argz, size_t *argz_len)
 {
   error_t err = 0;
@@ -356,7 +356,7 @@ arrange_shutdown_notification (void)
 }
 
 /* Override the privileged ports for booting the system */
-kern_return_t
+kern_return_t __attribute__ ((weak))
 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,
@@ -483,7 +483,7 @@ S_startup_dosync (mach_port_t handle)
   return 0;
 }
 
-error_t
+error_t __attribute__ ((weak))
 trivfs_goaway (struct trivfs_control *fsys, int flags)
 {
   int count;
@@ -506,7 +506,7 @@ trivfs_goaway (struct trivfs_control *fsys, int flags)
   exit (0);
 }
 
-static int
+int
 demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)
 {
   mig_routine_t routine;
@@ -524,7 +524,7 @@ demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)
     return FALSE;
 }
 
-void
+void __attribute__ ((weak))
 trivfs_modify_stat (struct trivfs_protid *cred, io_statbuf_t *stat)
 {
 }
diff --git a/libmachdev/trivfs_server.h b/libmachdev/trivfs_server.h
index 40ae57fe..3818bc72 100644
--- a/libmachdev/trivfs_server.h
+++ b/libmachdev/trivfs_server.h
@@ -26,6 +26,10 @@ extern struct port_bucket *port_bucket;
 extern struct port_class *trivfs_protid_class;
 extern struct port_class *trivfs_cntl_class;
 extern struct port_class *machdev_shutdown_notify_class;
+extern struct trivfs_control *control;
+extern task_t parent_task;
+
+int demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp);
 
 #endif /* _MACHDEV_TRIVFS_SERVER_H */
 
diff --git a/storeio/Makefile b/storeio/Makefile
index 83b7684d..5d5b8878 100644
--- a/storeio/Makefile
+++ b/storeio/Makefile
@@ -19,11 +19,13 @@
 dir := storeio
 makemode := server
 
-target = storeio
+target = storeio storeio.static
 SRCS = dev.c storeio.c open.c pager.c io.c
 
 OBJS = $(SRCS:.c=.o)
-HURDLIBS = trivfs pager fshelp iohelp store ports ihash shouldbeinlibc
-LDLIBS = -lpthread
+HURDLIBS = trivfs pager fshelp iohelp store ports ihash shouldbeinlibc machdev
+LDLIBS = -lpthread $(and $(HAVE_LIBBZ2),-lbz2) $(and $(HAVE_LIBZ),-lz)
 
 include ../Makeconf
+
+storeio.static: $(boot-store-types:%=../libstore/libstore_%.a)
diff --git a/storeio/dev.c b/storeio/dev.c
index c87400c0..30dc0354 100644
--- a/storeio/dev.c
+++ b/storeio/dev.c
@@ -143,7 +143,7 @@ dev_buf_rw (struct dev *dev, size_t buf_offs, size_t *io_offs, size_t *len,
 
 /* Called with DEV->lock held.  Try to open the store underlying DEV.  */
 error_t
-dev_open (struct dev *dev)
+dev_open (struct dev *dev, struct trivfs_control *storeio_fsys)
 {
   error_t err;
   const int flags = ((dev->readonly ? STORE_READONLY : 0)
diff --git a/storeio/dev.h b/storeio/dev.h
index eda7a93d..c017eb6e 100644
--- a/storeio/dev.h
+++ b/storeio/dev.h
@@ -26,8 +26,6 @@
 #include <hurd/store.h>
 #include <hurd/trivfs.h>
 
-extern struct trivfs_control *storeio_fsys;
-
 /* Information about backend store, which we presumptively call a "device".  */
 struct dev
 {
@@ -91,7 +89,7 @@ dev_is_readonly (const struct dev *dev)
 }
 
 /* Called with DEV->lock held.  Try to open the store underlying DEV.  */
-error_t dev_open (struct dev *dev);
+error_t dev_open (struct dev *dev, struct trivfs_control *storeio_fsys);
 
 /* Shut down the store underlying DEV and free any resources it consumes.
    DEV itself remains intact so that dev_open can be called again.
diff --git a/storeio/storeio.c b/storeio/storeio.c
index 4e8a9628..081eb277 100644
--- a/storeio/storeio.c
+++ b/storeio/storeio.c
@@ -29,11 +29,14 @@
 #include <hurd.h>
 #include <hurd/ports.h>
 #include <hurd/trivfs.h>
+#include <hurd/fsys.h>
 #include <version.h>
 
 #include "open.h"
 #include "dev.h"
 #include "libtrivfs/trivfs_fsys_S.h"
+#include "libmachdev/machdev.h"
+#include "libmachdev/trivfs_server.h"
 
 static struct argp_option options[] =
 {
@@ -48,6 +51,11 @@ static struct argp_option options[] =
   {"rdev",     'n', "ID", 0,
    "The stat rdev number for this node; may be either a"
    " single integer, or of the form MAJOR,MINOR"},
+  {0, 0, 0, 0,              "Boot options:"},
+  {"next-task", 'N', "TASK", 0, "Next bootstrap task"},
+  {"host-priv-port", 'H', "PORT", 0, "Port for bootstrapping host"},
+  {"device-master-port", 'P', "PORT", 0, "Port for bootstrapping device"
+   " master"},
   {0}
 };
 static const char doc[] = "Translator for devices and other stores";
@@ -57,6 +65,8 @@ const char *argp_program_version = STANDARD_HURD_VERSION (storeio);
 static bool debug=false;
 static char *debug_fname=NULL;
 
+static mach_port_t next_task;
+
 /* Desired store parameters specified by the user.  */
 struct storeio_argp_params
 {
@@ -64,6 +74,63 @@ struct storeio_argp_params
   struct dev *dev;		/* We fill in its flag members.  */
 };
 
+static error_t
+storeio_bootstrap_startup (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);
+  error_t err = trivfs_startup (bootstrap, 0, trivfs_cntl_class, port_bucket,
+                                trivfs_protid_class, 0, &control);
+  if (err)
+    return err;
+
+  err = fsys_getpriv (bootstrap, &_hurd_host_priv,
+                      &_hurd_device_master, &parent_task);
+  if (err)
+   return err;
+
+  mach_port_t right = ports_get_send_right (&control->pi);
+  err = task_set_special_port (next_task, TASK_BOOTSTRAP_PORT, right);
+  if (err)
+    return err;
+
+  err = mach_port_deallocate (mach_task_self (), right);
+  if (err)
+    return err;
+
+  err = task_resume (next_task);
+  if (err)
+    return err;
+
+  /* Make sure we have a console.  */
+  mach_port_t dev;
+  err = get_privileged_ports (NULL, &dev);
+  if (err)
+    return err;
+
+  mach_port_t cons;
+  err = device_open (dev, D_READ | D_WRITE, "console", &cons);
+  if (err)
+    return err;
+
+  err = mach_port_deallocate (mach_task_self (), dev);
+  if (err)
+    return err;
+
+  stdin = mach_open_devstream (cons, "r");
+  stdout = stderr = mach_open_devstream (cons, "w");
+  err = mach_port_deallocate (mach_task_self (), cons);
+  if (err)
+    return err;
+
+  setlinebuf (stderr);
+  printf ("storeio ");
+  fflush (stdout);
+
+  return 0;
+}
+
 /* Parse a single option.  */
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
@@ -80,6 +147,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case 'e': params->dev->enforced = 1; break;
     case 'F': params->dev->no_fileio = 1; break;
 
+    case 'N': next_task = atoi (arg); break;
+    case 'H': _hurd_host_priv = atoi (arg); break;
+    case 'P': _hurd_device_master = atoi (arg); break;
+
     case 'n':
       {
 	char *start = arg, *end;
@@ -134,7 +205,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
 static const struct argp_child argp_kids[] = { { &store_argp }, {0} };
 static const struct argp argp = { options, parse_opt, 0, doc, argp_kids };
-
+
 struct trivfs_control *storeio_fsys;
 
 int
@@ -163,21 +234,39 @@ main (int argc, char *argv[])
     {
       task_get_bootstrap_port (mach_task_self (), &bootstrap);
       if (bootstrap == MACH_PORT_NULL)
-	error (2, 0, "Must be started as a translator");
-
-      /* Reply to our parent */
-      err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &storeio_fsys);
-      if (err)
-	error (3, err, "trivfs_startup");
+        error (2, 0, "Must be started as a translator");
+
+      if (next_task != MACH_PORT_NULL)
+        {
+          err = storeio_bootstrap_startup (bootstrap);
+          if (err)
+            error (1, err, "storeio_bootstrap_init");
+
+          dev_open (&device, control);
+
+          control->hook = &device;
+
+          /* Launch. */
+          ports_manage_port_operations_multithread (control->pi.bucket,
+                                              demuxer,
+                                              30*1000, 5*60*1000, 0);
+        }
+      else
+        {
+          /* Reply to our parent */
+          err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &storeio_fsys);
+          if (err)
+            error (3, err, "trivfs_startup");
+
+          storeio_fsys->hook = &device;
+
+          /* Launch. */
+          ports_manage_port_operations_multithread (storeio_fsys->pi.bucket,
+                                              trivfs_demuxer,
+                                              30*1000, 5*60*1000, 0);
+        }
     }
 
-  storeio_fsys->hook = &device;
-
-  /* Launch. */
-  ports_manage_port_operations_multithread (storeio_fsys->pi.bucket,
-					    trivfs_demuxer,
-					    30*1000, 5*60*1000, 0);
-
   return 0;
 }
 
@@ -254,7 +343,11 @@ check_open_hook (struct trivfs_control *trivfs_control,
   if (dev->store == NULL)
     {
       /* Try and open the store.  */
-      err = dev_open (dev);
+      if (next_task != MACH_PORT_NULL)
+        err = dev_open (dev, control);
+      else
+        err = dev_open (dev, storeio_fsys);
+
       if (err && (flags & (O_READ|O_WRITE)) == 0)
 	/* If we're not opening for read or write, then just ignore the
 	   error, as this allows stat to work correctly.  XXX  */
@@ -452,3 +545,30 @@ trivfs_S_fsys_syncfs (struct trivfs_control *cntl,
   else
     return 0;
 }
+
+/* Override the privileged ports for booting the system */
+kern_return_t
+trivfs_S_fsys_getpriv (struct trivfs_control *cntl,
+		       mach_port_t reply,
+		       mach_msg_type_name_t replytype,
+		       mach_port_t *host, mach_msg_type_name_t *host_privPoly,
+		       mach_port_t *dev, mach_msg_type_name_t *devPoly,
+		       mach_port_t *fstask, mach_msg_type_name_t *fstPoly)
+{
+  mach_port_t right;
+  if (next_task != MACH_PORT_NULL)
+    right = ports_get_send_right (&control->pi);
+  else
+    right = ports_get_send_right (&storeio_fsys->pi);
+
+  error_t err = get_privileged_ports (host, NULL);
+  if (!err)
+    {
+      *dev = right;
+      *fstask = mach_task_self ();
+      *host_privPoly = *devPoly = MACH_MSG_TYPE_MOVE_SEND;
+      *fstPoly = MACH_MSG_TYPE_COPY_SEND;
+    }
+
+  return err;
+}
-- 
2.43.0

Reply via email to