diff options
| author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-11-12 15:29:52 +0100 |
|---|---|---|
| committer | Justus Winter <justus@gnupg.org> | 2016-09-04 12:31:06 +0200 |
| commit | 31ddc1d95301867736fcd64e9e34fe885ae98fd8 (patch) | |
| tree | 311c3848239d55bf0bbb3ec60dd069a038caa842 | |
| parent | 4b99a6fcf9ac292105290c447827b9b2f4a57b8c (diff) | |
moar boot
| -rw-r--r-- | boot/Makefile | 4 | ||||
| -rw-r--r-- | boot/boot.c | 134 |
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; } |
