summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-11-12 15:29:52 +0100
committerJustus Winter <justus@gnupg.org>2016-09-04 12:31:06 +0200
commit31ddc1d95301867736fcd64e9e34fe885ae98fd8 (patch)
tree311c3848239d55bf0bbb3ec60dd069a038caa842
parent4b99a6fcf9ac292105290c447827b9b2f4a57b8c (diff)
moar boot
-rw-r--r--boot/Makefile4
-rw-r--r--boot/boot.c134
2 files changed, 129 insertions, 9 deletions
diff --git a/boot/Makefile b/boot/Makefile
index f02f87cd..51882ee3 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -23,13 +23,13 @@ SRCS = mach-crt0.c boot.c ux.c sigvec.S syscall.S \
COMMON-OBJS = notifyServer.o deviceServer.o \
ioServer.o io_replyUser.o device_replyUser.o \
termServer.o bootstrapServer.o boot_script.o userland-boot.o
-MIGSTUBS = machServer.o mach_hostServer.o gnumachServer.o
+MIGSTUBS = machServer.o mach_hostServer.o gnumachServer.o task_notifyServer.o
OBJS = boot.o $(COMMON-OBJS) $(MIGSTUBS)
UX-OBJS = mach-crt0.o uxboot.o sigvec.o syscall.o ux.o $(COMMON-OBJS)
target = boot
MIGSFLAGS=-imacros $(srcdir)/mig-mutate.h
io-MIGSFLAGS=-DREPLY_PORTS
-HURDLIBS = store shouldbeinlibc
+HURDLIBS = store shouldbeinlibc ihash
LDLIBS += -lpthread
include ../Makeconf
diff --git a/boot/boot.c b/boot/boot.c
index 0238a9fe..f84d2f7a 100644
--- a/boot/boot.c
+++ b/boot/boot.c
@@ -38,6 +38,7 @@
#include <mach/machine/vm_param.h> /* For VM_XXX_ADDRESS */
#include <argp.h>
#include <hurd/store.h>
+#include <sys/reboot.h>
#include <sys/mman.h>
#include <version.h>
@@ -52,6 +53,7 @@
#include "mach_S.h"
#include "mach_host_S.h"
#include "gnumach_S.h"
+#include "task_notify_S.h"
#include "boot_script.h"
@@ -124,7 +126,11 @@ mach_port_t pseudo_privileged_host_port, pseudo_master_device_port;
mach_port_t receive_set;
mach_port_t pseudo_console, pseudo_root, pseudo_time;
mach_port_t pseudo_pset;
+task_t pseudo_kernel;
+mach_port_t task_notification_port;
+mach_port_t dead_task_notification_port;
auth_t authserver;
+mach_port_t procserver;
struct store *root_store;
@@ -224,7 +230,8 @@ boot_demuxer (mach_msg_header_t *inp,
(routine = term_server_routine (inp)) ||
(routine = mach_server_routine (inp)) ||
(routine = mach_host_server_routine (inp)) ||
- (routine = gnumach_server_routine (inp))
+ (routine = gnumach_server_routine (inp)) ||
+ (routine = task_notify_server_routine (inp))
/* (routine = tioctl_server_routine (inp)) */)
{
(*routine) (inp, outp);
@@ -541,8 +548,6 @@ main (int argc, char **argv, char **envp)
get_privileged_ports (&privileged_host_port, &master_device_port);
device_pass_through = MACH_PORT_VALID (master_device_port);
- strcat (bootstrap_args, "f");
-
mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET,
&receive_set);
@@ -615,6 +620,30 @@ main (int argc, char **argv, char **envp)
mach_port_move_member (mach_task_self (), pseudo_pset,
receive_set);
+ /* We will receive new task notifications on this port. */
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &task_notification_port);
+ mach_port_move_member (mach_task_self (), task_notification_port,
+ receive_set);
+
+ /* And information about dying tasks here. */
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &dead_task_notification_port);
+ mach_port_move_member (mach_task_self (), dead_task_notification_port,
+ receive_set);
+
+ /* Create a new task namespace for us. */
+ procserver = getproc ();
+ err = proc_make_task_namespace (procserver, task_notification_port,
+ MACH_MSG_TYPE_MAKE_SEND);
+ if (err)
+ error (1, err, "proc_make_task_namespace");
+
+ /* Create an empty task that the subhurds can freely frobnicate. */
+ err = task_create (mach_task_self (), 0, &pseudo_kernel);
+ if (err)
+ return (1, err, "task_create");
+
if (kernel_command_line == 0)
asprintf (&kernel_command_line, "%s %s root=%s",
argv[0], bootstrap_args, bootdevice);
@@ -1368,7 +1397,10 @@ do_mach_notify_dead_name (mach_port_t notify,
if (name == child_task && notify == bootport)
host_exit (0);
#endif
- return EOPNOTSUPP;
+ if (notify != dead_task_notification_port)
+ return EOPNOTSUPP;
+ task_died (name);
+ return 0;
}
@@ -1944,6 +1976,16 @@ S_vm_set_default_memory_manager (mach_port_t host_priv,
}
kern_return_t
+S_host_reboot (mach_port_t host_priv,
+ int options)
+{
+ fprintf (stderr, "Would %s the system. Bye.\n",
+ options & RB_HALT? "halt": "reboot");
+ host_exit (0);
+}
+
+
+kern_return_t
S_host_processor_set_priv (mach_port_t host_priv,
mach_port_t set_name,
mach_port_t *set)
@@ -1959,19 +2001,97 @@ S_host_processor_set_priv (mach_port_t host_priv,
return KERN_SUCCESS;
}
+mach_port_t new_task_notification;
+
kern_return_t
S_register_new_task_notification (mach_port_t host_priv,
mach_port_t notification)
{
+ if (host_priv != pseudo_privileged_host_port)
+ return KERN_INVALID_HOST;
+
+ if (! MACH_PORT_VALID (notification))
+ return KERN_INVALID_ARGUMENT;
+
+ if (MACH_PORT_VALID (new_task_notification))
+ return KERN_NO_ACCESS;
+
+ new_task_notification = notification;
return KERN_SUCCESS;
}
+task_t *tasks;
+size_t tasks_size, tasks_count;
+
+void
+task_died (mach_port_t name)
+{
+ size_t i;
+ /* XXX terrible! use a hash table instead! */
+ for (i = 0; i < tasks_count; i++)
+ if (tasks[i] == name)
+ {
+ mach_port_deallocate (mach_task_self (), name);
+ tasks[i] = MACH_PORT_DEAD;
+ }
+}
+
+/* Handle new task notifications from the kernel. */
+error_t
+S_mach_notify_new_task (mach_port_t notify,
+ mach_port_t task,
+ mach_port_t parent)
+{
+ if (notify != task_notification_port)
+ return EOPNOTSUPP;
+
+ if (tasks_size == tasks_count)
+ {
+ tasks_size = tasks_size? tasks_size << 1: 64;
+ tasks = realloc (tasks, tasks_size * sizeof *tasks);
+ assert (tasks);
+ }
+
+ mach_port_t previous;
+ mach_port_request_notification (mach_task_self (), task,
+ MACH_NOTIFY_DEAD_NAME, 0,
+ dead_task_notification_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
+ if (MACH_PORT_VALID (previous))
+ mach_port_deallocate (mach_task_self (), previous);
+
+ mach_port_mod_refs (mach_task_self (), task, MACH_PORT_RIGHT_SEND, +1);
+ tasks[tasks_count] = task;
+ tasks_count += 1;
+
+ if (MACH_PORT_VALID (new_task_notification))
+ /* Relay the notification. This consumes TASK and PARENT. */
+ return mach_notify_new_task (new_task_notification, task, parent);
+
+ mach_port_deallocate (mach_task_self (), task);
+ mach_port_deallocate (mach_task_self (), parent);
+ return 0;
+}
+
kern_return_t
S_processor_set_tasks(mach_port_t processor_set,
task_array_t *task_list,
mach_msg_type_number_t *task_listCnt)
{
- *task_list = NULL;
- *task_listCnt = 0;
- return KERN_SUCCESS;
+ error_t err;
+ size_t i;
+
+ err = vm_allocate (mach_task_self (), (vm_address_t *) task_list,
+ tasks_count * sizeof **task_list, 1);
+ if (err)
+ return err;
+
+ for (i = 0; i < tasks_count; i++)
+ mach_port_mod_refs (mach_task_self (),
+ tasks[i], MACH_PORT_RIGHT_SEND, +1);
+
+ memcpy (*task_list, tasks, tasks_count * sizeof *tasks);
+ *task_listCnt = tasks_count;
+
+ return 0;
}