summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorJustus Winter <justus@gnupg.org>2017-09-13 14:10:33 +0200
committerJustus Winter <justus@gnupg.org>2017-09-13 14:10:33 +0200
commit1c5e9b5fd65d2c385f5d3f696eb0d05a86fb2755 (patch)
tree82a7293c31238d516d12fa25fcddb2e8339598c0 /boot
parent5018bd32c87250ed3fd4249d050b772750827db0 (diff)
parent89a49ec8b3a847f3b770cff6a4a80b98b94ad7bf (diff)
Merge remote-tracking branch 'mainline/master' into dde
Diffstat (limited to 'boot')
-rw-r--r--boot/Makefile35
-rw-r--r--boot/boot.c976
-rw-r--r--boot/frank1.ld94
-rw-r--r--boot/frankemul.ld107
-rw-r--r--boot/mach-crt0.c158
-rw-r--r--boot/mig-decls.h27
-rw-r--r--boot/mig-mutate.h25
-rw-r--r--boot/private.h25
-rw-r--r--boot/sigvec.S23
-rw-r--r--boot/syscall.S35
-rw-r--r--boot/userland-boot.c261
-rw-r--r--boot/ux.c303
-rw-r--r--boot/ux.h114
13 files changed, 820 insertions, 1363 deletions
diff --git a/boot/Makefile b/boot/Makefile
index b24022203..e2eeb20b0 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -18,37 +18,16 @@
dir := boot
makemode := utility
-SRCS = mach-crt0.c boot.c ux.c sigvec.S syscall.S \
- boot_script.c userland-boot.c list.c mach_proxy.c
+SRCS = boot.c boot_script.c userland-boot.c
COMMON-OBJS = notifyServer.o deviceServer.o \
ioServer.o io_replyUser.o device_replyUser.o \
- termServer.o bootstrapServer.o boot_script.o userland-boot.o \
- ourmach_hostServer.o ourmachServer.o ourmach_portServer.o
-OBJS = boot.o mach_host_impl.o mach_impl.o mach_port_impl.o \
- list.o mach_proxy.o $(COMMON-OBJS)
-UX-OBJS = mach-crt0.o uxboot.o sigvec.o syscall.o ux.o $(COMMON-OBJS)
+ termServer.o boot_script.o userland-boot.o
+MIGSTUBS = machServer.o mach_hostServer.o gnumachServer.o task_notifyServer.o
+OBJS = boot.o $(COMMON-OBJS) $(MIGSTUBS)
target = boot
-io-MIGSFLAGS=-DREPLY_PORTS
-HURDLIBS = store shouldbeinlibc
+MIGSFLAGS=-imacros $(srcdir)/mig-mutate.h -DHURD_DEFAULT_PAYLOAD_TO_PORT=1
+io-MIGSFLAGS=-DREPLY_PORTS -DHURD_DEFAULT_PAYLOAD_TO_PORT=1
+HURDLIBS = store shouldbeinlibc ihash
LDLIBS += -lpthread
include ../Makeconf
-
-#install: /usr/local/bin/uxboot
-#
-#/usr/local/bin/uxboot: uxboot
-# cp $< $@
-
-MIGSFLAGS = -DHURD_DEFAULT_PAYLOAD_TO_PORT=1
-
-all: boot # uxboot
-
-uxboot.o: boot.c
- $(COMPILE.c) -DUX $< -o $@
-
-uxboot.0: $(UX-OBJS)
- $(LINK.o) -o $@ -static -nostartfiles -Wl,-T -Wl,$(srcdir)/frank1.ld $^
-uxboot.1: frankemul.ld uxboot.0
- $(LD) -o $@ -T $^
-uxboot: uxboot.1
- -$(OBJCOPY) -S --remove-section=.comment -O a.out-mach3 $< $@
diff --git a/boot/boot.c b/boot/boot.c
index e158fceaa..35577a89f 100644
--- a/boot/boot.c
+++ b/boot/boot.c
@@ -1,6 +1,6 @@
/* Load a task using the single server, and then run it
as if we were the kernel.
- Copyright (C) 1993,94,95,96,97,98,99,2000,01,02,2006
+ Copyright (C) 1993,94,95,96,97,98,99,2000,01,02,2006,14,16
Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -24,21 +24,20 @@
#include <mach.h>
#include <mach/notify.h>
#include <device/device.h>
-#include <a.out.h>
#include <mach/message.h>
#include <mach/mig_errors.h>
+#include <mach/task_notify.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <fcntl.h>
-#include <elf.h>
#include <mach/mig_support.h>
#include <mach/default_pager.h>
-#include <mach/machine/vm_param.h> /* For VM_XXX_ADDRESS */
#include <argp.h>
#include <hurd/store.h>
-#include <hurd/ports.h>
+#include <hurd/ihash.h>
+#include <sys/reboot.h>
#include <sys/mman.h>
#include <version.h>
@@ -50,24 +49,15 @@
#include "term_S.h"
#include "bootstrap_S.h"
/* #include "tioctl_S.h" */
-#include "util.h"
+#include "mach_S.h"
+#include "mach_host_S.h"
+#include "gnumach_S.h"
+#include "task_notify_S.h"
+
#include "boot_script.h"
-#include "mach_proxy.h"
#include <hurd/auth.h>
-#ifdef UX
-#undef STORE /* We can't use libstore when under UX. */
-#else
-#define STORE
-#endif
-
-#ifdef UX
-
-#include "ux.h"
-
-#else /* !UX */
-
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
@@ -76,19 +66,22 @@
#include <termios.h>
#include <error.h>
#include <hurd.h>
-#include <assert.h>
+#include <assert-backtrace.h>
+
+#include "private.h"
+
+/* We support two modes of operation. Traditionally, Subhurds were
+ privileged, i.e. they had the privileged kernel ports. This has a
+ few drawbacks. Privileged subhurds can manipulate all tasks on the
+ system and halt the system. Nowadays we allow an unprivileged
+ mode. */
+static int privileged;
+static int want_privileged;
static struct termios orig_tty_state;
static int isig;
static char *kernel_command_line;
-struct port_bucket *port_bucket;
-struct port_class *task_portclass;
-struct port_class *priv_host_portclass;
-struct port_class *other_portclass;
-
-void destroy_priv_host (void *pi);
-
static void
init_termstate ()
{
@@ -114,17 +107,30 @@ restore_termstate ()
#define host_fstat fstat
typedef struct stat host_stat_t;
-#define host_exit exit
-#endif /* UX */
+void __attribute__ ((__noreturn__))
+host_exit (int status)
+{
+ restore_termstate ();
+ exit (status);
+}
+
+int verbose;
mach_port_t privileged_host_port, master_device_port;
+mach_port_t pseudo_privileged_host_port;
mach_port_t 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;
-struct port_info *pseudo_priv_host_pi;
+/* The proc server registers for new task notifications which we will
+ send to this port. */
+mach_port_t new_task_notification;
struct store *root_store;
@@ -150,37 +156,13 @@ char bootstrap_args[100] = "-";
char *bootdevice = 0;
char *bootscript = 0;
-boolean_t is_user = 0;
-
void safe_gets (char *buf, int buf_len)
{
fgets (buf, buf_len, stdin);
}
-char *useropen_dir;
-
-int
-useropen (const char *name, int flags, int mode)
-{
- if (useropen_dir)
- {
- static int dlen;
- if (!dlen) dlen = strlen (useropen_dir);
- {
- int len = strlen (name);
- char try[dlen + 1 + len + 1];
- int fd;
- memcpy (try, useropen_dir, dlen);
- try[dlen] = '/';
- memcpy (&try[dlen + 1], name, len + 1);
- fd = open (try, flags, mode);
- if (fd >= 0)
- return fd;
- }
- }
- return open (name, flags, mode);
-}
+extern char *useropen_dir;
/* XXX: glibc should provide mig_reply_setup but does not. */
/* Fill in default response. */
@@ -214,16 +196,74 @@ mig_reply_setup (
#undef OutP
}
+error_t
+mach_msg_forward (mach_msg_header_t *inp,
+ mach_port_t destination, mach_msg_type_name_t destination_type)
+{
+ /* Put the reply port back at the correct position, insert new
+ destination. */
+ inp->msgh_local_port = inp->msgh_remote_port;
+ inp->msgh_remote_port = destination;
+ inp->msgh_bits =
+ MACH_MSGH_BITS (destination_type, MACH_MSGH_BITS_REMOTE (inp->msgh_bits))
+ | MACH_MSGH_BITS_OTHER (inp->msgh_bits);
+
+ /* A word about resources carried in complex messages.
+
+ "In a received message, msgt_deallocate is TRUE in type
+ descriptors for out-of-line memory". Therefore, "[the
+ out-of-line memory] is implicitly deallocated from the sender
+ [when we resend the message], as if by vm_deallocate".
+
+ Similarly, rights in messages will be either
+ MACH_MSG_TYPE_PORT_SEND, MACH_MSG_TYPE_PORT_SEND_ONCE, or
+ MACH_MSG_TYPE_PORT_RECEIVE. These types are aliases for,
+ respectively, MACH_MSG_TYPE_MOVE_SEND,
+ MACH_MSG_TYPE_MOVE_SEND_ONCE, and MACH_MSG_TYPE_MOVE_RECEIVE.
+ Therefore, the rights are moved when we resend the message. */
+
+ return mach_msg (inp, MACH_SEND_MSG, inp->msgh_size,
+ 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+}
+
int
boot_demuxer (mach_msg_header_t *inp,
mach_msg_header_t *outp)
{
+ error_t err;
mig_routine_t routine;
mig_reply_setup (inp, outp);
+
+ if (inp->msgh_local_port == task_notification_port
+ && MACH_PORT_VALID (new_task_notification)
+ && 24000 <= inp->msgh_id && inp->msgh_id < 24100)
+ {
+ /* This is a message of the Process subsystem. We relay this to
+ allow the "outer" proc servers to communicate with the "inner"
+ one. */
+ mig_reply_header_t *reply = (mig_reply_header_t *) outp;
+
+ if (MACH_PORT_VALID (new_task_notification))
+ err = mach_msg_forward (inp, new_task_notification, MACH_MSG_TYPE_COPY_SEND);
+ else
+ err = EOPNOTSUPP;
+
+ if (err)
+ reply->RetCode = err;
+ else
+ reply->RetCode = MIG_NO_REPLY;
+
+ return TRUE;
+ }
+
if ((routine = io_server_routine (inp)) ||
(routine = device_server_routine (inp)) ||
(routine = notify_server_routine (inp)) ||
- (routine = term_server_routine (inp))
+ (routine = term_server_routine (inp)) ||
+ (routine = mach_server_routine (inp)) ||
+ (routine = mach_host_server_routine (inp)) ||
+ (routine = gnumach_server_routine (inp)) ||
+ (routine = task_notify_server_routine (inp))
/* (routine = tioctl_server_routine (inp)) */)
{
(*routine) (inp, outp);
@@ -233,252 +273,70 @@ boot_demuxer (mach_msg_header_t *inp,
return FALSE;
}
-int
-mach_proxy_demuxer (mach_msg_header_t *inp,
- mach_msg_header_t *outp)
-{
- extern boolean_t mach_server
- (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
- extern boolean_t mach_host_server
- (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
- extern boolean_t mach_port_server
- (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
- extern int notify_server (mach_msg_header_t *, mach_msg_header_t *);
- return (mach_server (inp, outp)
- || mach_host_server (inp, outp)
- || mach_port_server (inp, outp)
- || notify_server (inp, outp));
-}
-
-void
-mach_proxy_thread ()
-{
- ports_manage_port_operations_multithread (port_bucket,
- mach_proxy_demuxer,
- 30 * 1000, 0, 0);
-}
-
-vm_address_t
-load_image (task_t t,
- char *file)
-{
- int fd;
- union
- {
- struct exec a;
- Elf32_Ehdr e;
- } hdr;
- char msg[] = ": cannot open bootstrap file\n";
-
- fd = useropen (file, O_RDONLY, 0);
-
- if (fd == -1)
- {
- write (2, file, strlen (file));
- write (2, msg, sizeof msg - 1);
- task_terminate (t);
- host_exit (1);
- }
-
- read (fd, &hdr, sizeof hdr);
- /* File must have magic ELF number. */
- if (hdr.e.e_ident[0] == 0177 && hdr.e.e_ident[1] == 'E' &&
- hdr.e.e_ident[2] == 'L' && hdr.e.e_ident[3] == 'F')
- {
- Elf32_Phdr phdrs[hdr.e.e_phnum], *ph;
- lseek (fd, hdr.e.e_phoff, SEEK_SET);
- read (fd, phdrs, sizeof phdrs);
- for (ph = phdrs; ph < &phdrs[sizeof phdrs/sizeof phdrs[0]]; ++ph)
- if (ph->p_type == PT_LOAD)
- {
- vm_address_t buf;
- vm_size_t offs = ph->p_offset & (ph->p_align - 1);
- vm_size_t bufsz = round_page (ph->p_filesz + offs);
-
- buf = (vm_address_t) mmap (0, bufsz,
- PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
-
- lseek (fd, ph->p_offset, SEEK_SET);
- read (fd, (void *)(buf + offs), ph->p_filesz);
-
- ph->p_memsz = ((ph->p_vaddr + ph->p_memsz + ph->p_align - 1)
- & ~(ph->p_align - 1));
- ph->p_vaddr &= ~(ph->p_align - 1);
- ph->p_memsz -= ph->p_vaddr;
-
- vm_allocate (t, (vm_address_t*)&ph->p_vaddr, ph->p_memsz, 0);
- vm_write (t, ph->p_vaddr, buf, bufsz);
- munmap ((caddr_t) buf, bufsz);
- vm_protect (t, ph->p_vaddr, ph->p_memsz, 0,
- ((ph->p_flags & PF_R) ? VM_PROT_READ : 0) |
- ((ph->p_flags & PF_W) ? VM_PROT_WRITE : 0) |
- ((ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0));
- }
- return hdr.e.e_entry;
- }
- else
- {
- /* a.out */
- int magic = N_MAGIC (hdr.a);
- int headercruft;
- vm_address_t base = 0x10000;
- int rndamount, amount;
- vm_address_t bsspagestart, bssstart;
- char *buf;
-
- headercruft = sizeof (struct exec) * (magic == ZMAGIC);
-
- amount = headercruft + hdr.a.a_text + hdr.a.a_data;
- rndamount = round_page (amount);
- buf = mmap (0, rndamount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
- lseek (fd, sizeof hdr.a - headercruft, SEEK_SET);
- read (fd, buf, amount);
- vm_allocate (t, &base, rndamount, 0);
- vm_write (t, base, (vm_address_t) buf, rndamount);
- if (magic != OMAGIC)
- vm_protect (t, base, trunc_page (headercruft + hdr.a.a_text),
- 0, VM_PROT_READ | VM_PROT_EXECUTE);
- munmap ((caddr_t) buf, rndamount);
-
- bssstart = base + hdr.a.a_text + hdr.a.a_data + headercruft;
- bsspagestart = round_page (bssstart);
- vm_allocate (t, &bsspagestart,
- hdr.a.a_bss - (bsspagestart - bssstart), 0);
-
- return hdr.a.a_entry;
- }
-}
-
-
void read_reply ();
void * msg_thread (void *);
-/* Callbacks for boot_script.c; see boot_script.h. */
-int
-boot_script_exec_cmd (void *hook,
- mach_port_t task, char *path, int argc,
- char **argv, char *strings, int stringlen)
-{
- char *args, *p;
- int arg_len, i;
- size_t reg_size;
- void *arg_pos;
- vm_offset_t stack_start, stack_end;
- vm_address_t startpc, str_start;
- thread_t thread;
-
- write (2, path, strlen (path));
- for (i = 1; i < argc; ++i)
- {
- write (2, " ", 1);
- write (2, argv[i], strlen (argv[i]));
- }
- write (2, "\r\n", 2);
-
- startpc = load_image (task, path);
- arg_len = stringlen + (argc + 2) * sizeof (char *) + sizeof (integer_t);
- arg_len += 5 * sizeof (int);
- stack_end = VM_MAX_ADDRESS;
- stack_start = VM_MAX_ADDRESS - 16 * 1024 * 1024;
- vm_allocate (task, &stack_start, stack_end - stack_start, FALSE);
- arg_pos = (void *) ((stack_end - arg_len) & ~(sizeof (natural_t) - 1));
- args = mmap (0, stack_end - trunc_page ((vm_offset_t) arg_pos),
- PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
- str_start = ((vm_address_t) arg_pos
- + (argc + 2) * sizeof (char *) + sizeof (integer_t));
- p = args + ((vm_address_t) arg_pos & (vm_page_size - 1));
- *(int *) p = argc;
- p = (void *) p + sizeof (int);
- for (i = 0; i < argc; i++)
- {
- *(char **) p = argv[i] - strings + (char *) str_start;
- p = (void *) p + sizeof (char *);
- }
- *(char **) p = 0;
- p = (void *) p + sizeof (char *);
- *(char **) p = 0;
- p = (void *) p + sizeof (char *);
- memcpy (p, strings, stringlen);
- memset (args, 0, (vm_offset_t)arg_pos & (vm_page_size - 1));
- vm_write (task, trunc_page ((vm_offset_t) arg_pos), (vm_address_t) args,
- stack_end - trunc_page ((vm_offset_t) arg_pos));
- munmap ((caddr_t) args,
- stack_end - trunc_page ((vm_offset_t) arg_pos));
-
- thread_create (task, &thread);
-#ifdef i386_THREAD_STATE_COUNT
- {
- struct i386_thread_state regs;
- reg_size = i386_THREAD_STATE_COUNT;
- thread_get_state (thread, i386_THREAD_STATE,
- (thread_state_t) &regs, &reg_size);
- regs.eip = (int) startpc;
- regs.uesp = (int) arg_pos;
- thread_set_state (thread, i386_THREAD_STATE,
- (thread_state_t) &regs, reg_size);
- }
-#elif defined(ALPHA_THREAD_STATE_COUNT)
- {
- struct alpha_thread_state regs;
- reg_size = ALPHA_THREAD_STATE_COUNT;
- thread_get_state (thread, ALPHA_THREAD_STATE,
- (thread_state_t) &regs, &reg_size);
- regs.r30 = (natural_t) arg_pos;
- regs.pc = (natural_t) startpc;
- thread_set_state (thread, ALPHA_THREAD_STATE,
- (thread_state_t) &regs, reg_size);
- }
-#else
-# error needs to be ported
-#endif
-
- thread_resume (thread);
- mach_port_deallocate (mach_task_self (), thread);
- return 0;
-}
-
const char *argp_program_version = STANDARD_HURD_VERSION (boot);
+#define OPT_PRIVILEGED -1
+#define OPT_BOOT_SCRIPT -2
+
static struct argp_option options[] =
{
+ { NULL, 0, NULL, 0, "Boot options:" },
+ { "boot-script", OPT_BOOT_SCRIPT, "BOOT-SCRIPT", 0,
+ "boot script to execute" },
{ "boot-root", 'D', "DIR", 0,
"Root of a directory tree in which to find files specified in BOOT-SCRIPT" },
{ "single-user", 's', 0, 0,
"Boot in single user mode" },
{ "kernel-command-line", 'c', "COMMAND LINE", 0,
"Simulated multiboot command line to supply" },
+ { "verbose", 'v', 0, 0,
+ "Be verbose" },
{ "pause" , 'd', 0, 0,
"Pause for user confirmation at various times during booting" },
{ "isig", 'I', 0, 0,
- "Do not disable terminal signals, so you can suspend and interrupt boot."},
- { "device", 'f', "device_name=device_file", 0,
- "Specify a device file used by subhurd and its virtual name."},
- { "defpager", 'p', "PAGER TRANSLATOR", 0,
- "Specify the default pager for subhurd."},
- { "user", 'u', 0, 0, "For normal user."},
+ "Do not disable terminal signals, so you can suspend and interrupt boot"},
+ { "device", 'f', "SUBHURD_NAME=DEVICE_FILE", 0,
+ "Pass the given DEVICE_FILE to the Subhurd as device SUBHURD_NAME"},
+ { "privileged", OPT_PRIVILEGED, NULL, 0,
+ "Allow the subhurd to access privileged kernel ports"},
{ 0 }
};
-static char args_doc[] = "BOOT-SCRIPT";
static char doc[] = "Boot a second hurd";
-struct dev_map
+
+
+/* Device pass through. */
+
+struct dev_map
{
- char *name;
- mach_port_t port;
+ char *device_name; /* The name of the device in the Subhurd. */
+ char *file_name; /* The filename outside the Subhurd. */
struct dev_map *next;
};
static struct dev_map *dev_map_head;
-static struct dev_map *add_dev_map (char *dev_name, char *dev_file)
+static struct dev_map *
+add_dev_map (const char *dev_name, const char *dev_file)
{
- struct dev_map *map = malloc (sizeof (*map));
+ file_t node;
+ struct dev_map *map;
- assert (map);
- map->name = dev_name;
- map->port = file_name_lookup (dev_file, 0, 0);
- if (map->port == MACH_PORT_NULL)
- error (1, errno, "file_name_lookup: %s", dev_file);
+ /* See if we can open the file. */
+ node = file_name_lookup (dev_file, 0, 0);
+ if (! MACH_PORT_VALID (node))
+ error (1, errno, "%s", dev_file);
+ mach_port_deallocate (mach_task_self (), node);
+
+ map = malloc (sizeof *map);
+ if (map == NULL)
+ return NULL;
+
+ map->device_name = strdup (dev_name);
+ map->file_name = strdup (dev_file);
map->next = dev_map_head;
dev_map_head = map;
return map;
@@ -490,14 +348,12 @@ static struct dev_map *lookup_dev (char *dev_name)
for (map = dev_map_head; map; map = map->next)
{
- if (strcmp (map->name, dev_name) == 0)
+ if (strcmp (map->device_name, dev_name) == 0)
return map;
}
return NULL;
}
-char *pager_file;
-
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
@@ -513,6 +369,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
case 'I': isig = 1; break;
+ case 'v':
+ verbose += 1;
+ break;
+
case 's': case 'd':
len = strlen (bootstrap_args);
if (len >= sizeof bootstrap_args - 1)
@@ -529,20 +389,16 @@ parse_opt (int key, char *arg, struct argp_state *state)
add_dev_map (arg, dev_file+1);
break;
- case 'p':
- pager_file = arg;
+ case OPT_PRIVILEGED:
+ want_privileged = 1;
break;
- case 'u':
- is_user = 1;
+ case OPT_BOOT_SCRIPT:
+ bootscript = arg;
break;
case ARGP_KEY_ARG:
- if (state->arg_num == 0)
- bootscript = arg;
- else
- return ARGP_ERR_UNKNOWN;
- break;
+ return ARGP_ERR_UNKNOWN;
case ARGP_KEY_INIT:
state->child_inputs[0] = state->input; break;
@@ -553,67 +409,131 @@ parse_opt (int key, char *arg, struct argp_state *state)
return 0;
}
-static void
-sigint (int signo)
+static error_t
+allocate_pseudo_ports (void)
{
- int kill_task (struct task_info *task_pi)
- {
- task_terminate (task_pi->task_port);
- return 0;
- }
+ mach_port_t old;
- info ("receives an INT");
- foreach_task (kill_task);
- exit (0);
-}
+ /* Allocate a port that we hand out as the privileged host port. */
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &pseudo_privileged_host_port);
+ mach_port_insert_right (mach_task_self (),
+ pseudo_privileged_host_port,
+ pseudo_privileged_host_port,
+ MACH_MSG_TYPE_MAKE_SEND);
+ mach_port_move_member (mach_task_self (), pseudo_privileged_host_port,
+ receive_set);
+ mach_port_request_notification (mach_task_self (),
+ pseudo_privileged_host_port,
+ MACH_NOTIFY_NO_SENDERS, 1,
+ pseudo_privileged_host_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE, &old);
+ assert_backtrace (old == MACH_PORT_NULL);
-void
-init_signal ()
-{
- struct sigaction sa;
- sa.sa_handler = sigint;
- sa.sa_flags = 0; /* No SA_RESTART! */
- sigemptyset(&sa.sa_mask);
- if (sigaction (SIGINT, &sa, NULL))
- error (2, errno, "cannot set SIGHUP handler");
-}
+ /* Allocate a port that we hand out as the privileged processor set
+ port. */
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &pseudo_pset);
+ mach_port_move_member (mach_task_self (), pseudo_pset,
+ receive_set);
+ /* Make one send right that we copy when handing it out. */
+ mach_port_insert_right (mach_task_self (),
+ pseudo_pset,
+ pseudo_pset,
+ MACH_MSG_TYPE_MAKE_SEND);
-void
-init_kernel_task ()
-{
- error_t err;
- task_t pseudo_task;
- task_t pseudo_kernel_task;
- process_t real_kernel_task_proc;
- process_t proc;
- extern int create_pseudo_task (task_t real_task, task_t *ret_pseudo_task);
+ /* 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);
- err = task_create (mach_task_self (), 0, &pseudo_kernel_task);
- if (err)
- error (4, err, "cannot create the pseudo kernel task.");
+ /* 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);
- err = proc_task2proc (getproc (), pseudo_kernel_task, &proc);
- if (err)
- error (4, err, "cannot get the proc port for the pseudo kernel task.");
+ return 0;
+}
- err = task_set_bootstrap_port (pseudo_kernel_task, proc);
- if (err)
- error (4, err, "cannot set the pseudo kernel task's bootstrap port");
+void
+read_boot_script (char **buffer, size_t *length)
+{
+ char *p, *buf;
+ static const char filemsg[] = "Can't open boot script\n";
+ static const char memmsg[] = "Not enough memory\n";
+ int i, fd;
+ size_t amt, len;
- err = proc_pid2proc (getproc (), 2, &real_kernel_task_proc);
- if (err)
- error (4, err, "cannot get the kernel task's proc port");
+ fd = open (bootscript, O_RDONLY, 0);
+ if (fd < 0)
+ {
+ write (2, filemsg, sizeof (filemsg));
+ host_exit (1);
+ }
+ p = buf = malloc (500);
+ if (!buf)
+ {
+ write (2, memmsg, sizeof (memmsg));
+ host_exit (1);
+ }
+ len = 500;
+ amt = 0;
+ while (1)
+ {
+ i = read (fd, p, len - (p - buf));
+ if (i <= 0)
+ break;
+ p += i;
+ amt += i;
+ if (p == buf + len)
+ {
+ char *newbuf;
+
+ len += 500;
+ newbuf = realloc (buf, len);
+ if (!newbuf)
+ {
+ write (2, memmsg, sizeof (memmsg));
+ host_exit (1);
+ }
+ p = newbuf + (p - buf);
+ buf = newbuf;
+ }
+ }
- vm_address_t kargv, kenvp;
- err = proc_get_arg_locations (real_kernel_task_proc, &kargv, &kenvp);
- if (err)
- error (4, err, "cannot get the kernel task's argument");
- proc_set_arg_locations (proc, kargv, kenvp);
- create_pseudo_task (pseudo_kernel_task, &pseudo_task);
- // TODO the pseudo kernel task has to been destroyed after subhurd exits.
-}
+ close (fd);
+ *buffer = buf;
+ *length = amt;
+}
+
+
+/* Boot script file for booting contemporary GNU Hurd systems. Each
+ line specifies a file to be loaded by the boot loader (the first
+ word), and actions to be done with it. */
+const char *default_boot_script =
+ /* First, the bootstrap filesystem. It needs several ports as
+ arguments, as well as the user flags from the boot loader. */
+ "/hurd/ext2fs.static"
+ " --readonly"
+ " --multiboot-command-line=${kernel-command-line}"
+ " --host-priv-port=${host-port}"
+ " --device-master-port=${device-port}"
+ " --kernel-task=${kernel-task}"
+ " --exec-server-task=${exec-task}"
+ " -T device ${root-device} $(task-create) $(task-resume)"
+ "\n"
+
+ /* Now the exec server; to load the dynamically-linked exec server
+ program, we have the boot loader in fact load and run ld.so,
+ which in turn loads and runs /hurd/exec. This task is created,
+ and its task port saved in ${exec-task} to be passed to the fs
+ above, but it is left suspended; the fs will resume the exec task
+ once it is ready. */
+ "/lib/ld.so /hurd/exec $(exec-task=task-create)"
+ "\n";
-FILE *logfile;
int
main (int argc, char **argv, char **envp)
@@ -621,15 +541,12 @@ main (int argc, char **argv, char **envp)
error_t err;
mach_port_t foo;
char *buf = 0;
- int i, len;
pthread_t pthread_id;
char *root_store_name;
- const struct argp_child kids[] = { { &store_argp }, { 0 }};
- struct argp argp = { options, parse_opt, args_doc, doc, kids };
+ const struct argp_child kids[] = { { &store_argp, 0, "Store options:", -2 },
+ { 0 }};
+ struct argp argp = { options, parse_opt, NULL, doc, kids };
struct store_argp_params store_argp_params = { 0 };
- mach_port_t subhurd_privileged_host_port = MACH_PORT_NULL;
-
- LOG_START ();
argp_parse (&argp, argc, argv, 0, 0, &store_argp_params);
err = store_parsed_name (store_argp_params.result, &root_store_name);
@@ -640,46 +557,26 @@ main (int argc, char **argv, char **envp)
if (err)
error (4, err, "%s", root_store_name);
- init_signal ();
- if (!is_user)
+ if (want_privileged)
{
get_privileged_ports (&privileged_host_port, &master_device_port);
- defpager = MACH_PORT_NULL;
- subhurd_privileged_host_port = privileged_host_port;
- }
- else
- {
- port_bucket = ports_create_bucket ();
- task_portclass = ports_create_class (clean_pseudo_task, 0);
- priv_host_portclass = ports_create_class (destroy_priv_host, 0);
- other_portclass = ports_create_class (0, 0);
- init_kernel_task ();
- cthread_detach (cthread_fork ((cthread_fn_t) mach_proxy_thread,
- (any_t) 0));
-// if (pager_file == NULL)
-// error (4, 0, "The default pager must be specified for subhurd.");
-// defpager = file_name_lookup (pager_file, O_EXEC, 0);
-// if (defpager == MACH_PORT_NULL)
-// error (4, errno, "file_name_look: %s", pager_file);
-
- /* Initialize the pseudo privileged host port. */
- err = ports_create_port (priv_host_portclass, port_bucket,
- sizeof (struct port_info),
- &pseudo_priv_host_pi);
- if (err)
- error (4, err, "fail to create the pseudo privileged host port");
- subhurd_privileged_host_port = ports_get_send_right (pseudo_priv_host_pi);
- ports_port_deref (pseudo_priv_host_pi);
+ privileged = MACH_PORT_VALID (master_device_port);
+
+ if (! privileged)
+ error (1, 0, "Must be run as root for privileged subhurds");
}
- strcat (bootstrap_args, "f");
+ if (privileged)
+ strcat (bootstrap_args, "f");
mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET,
&receive_set);
if (root_store->class == &store_device_class && root_store->name
&& (root_store->flags & STORE_ENFORCED)
- && root_store->num_runs == 1 && root_store->runs[0].start == 0)
+ && root_store->num_runs == 1
+ && root_store->runs[0].start == 0
+ && privileged)
/* Let known device nodes pass through directly. */
bootdevice = root_store->name;
else
@@ -691,7 +588,6 @@ main (int argc, char **argv, char **envp)
mach_port_move_member (mach_task_self (), pseudo_root, receive_set);
}
- /* Initialize the pseudo master device port. */
mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
&pseudo_master_device_port);
mach_port_insert_right (mach_task_self (),
@@ -707,7 +603,6 @@ main (int argc, char **argv, char **envp)
if (foo != MACH_PORT_NULL)
mach_port_deallocate (mach_task_self (), foo);
- /* Initialize the pseudo console port. */
mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
&pseudo_console);
mach_port_move_member (mach_task_self (), pseudo_console, receive_set);
@@ -726,15 +621,37 @@ main (int argc, char **argv, char **envp)
if (foo != MACH_PORT_NULL)
mach_port_deallocate (mach_task_self (), foo);
+ if (! privileged)
+ {
+ err = allocate_pseudo_ports ();
+ if (err)
+ error (1, err, "Allocating pseudo ports");
+
+ /* Create a new task namespace for us. */
+ err = proc_make_task_namespace (getproc (), 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)
+ error (1, err, "task_create");
+ }
+
if (kernel_command_line == 0)
asprintf (&kernel_command_line, "%s %s root=%s",
argv[0], bootstrap_args, bootdevice);
/* Initialize boot script variables. */
if (boot_script_set_variable ("host-port", VAL_PORT,
- (int) subhurd_privileged_host_port)
+ privileged
+ ? (int) privileged_host_port
+ : (int) pseudo_privileged_host_port)
|| boot_script_set_variable ("device-port", VAL_PORT,
(integer_t) pseudo_master_device_port)
+ || boot_script_set_variable ("kernel-task", VAL_PORT,
+ (integer_t) pseudo_kernel)
|| boot_script_set_variable ("kernel-command-line", VAL_STR,
(integer_t) kernel_command_line)
|| boot_script_set_variable ("root-device",
@@ -767,7 +684,7 @@ main (int argc, char **argv, char **envp)
char *msg;
asprintf (&msg, "cannot set boot-script variable %s: %s\n",
word, boot_script_error_string (err));
- assert (msg);
+ assert_backtrace (msg);
write (2, msg, strlen (msg));
free (msg);
host_exit (1);
@@ -778,46 +695,12 @@ main (int argc, char **argv, char **envp)
/* Parse the boot script. */
{
char *p, *line;
- static const char filemsg[] = "Can't open boot script\n";
- static const char memmsg[] = "Not enough memory\n";
- int amt, fd, err;
+ size_t amt;
+ if (bootscript)
+ read_boot_script (&buf, &amt);
+ else
+ buf = strdup (default_boot_script), amt = strlen (default_boot_script);
- fd = open (bootscript, O_RDONLY, 0);
- if (fd < 0)
- {
- write (2, filemsg, sizeof (filemsg));
- host_exit (1);
- }
- p = buf = malloc (500);
- if (!buf)
- {
- write (2, memmsg, sizeof (memmsg));
- host_exit (1);
- }
- len = 500;
- amt = 0;
- while (1)
- {
- i = read (fd, p, len - (p - buf));
- if (i <= 0)
- break;
- p += i;
- amt += i;
- if (p == buf + len)
- {
- char *newbuf;
-
- len += 500;
- newbuf = realloc (buf, len);
- if (!newbuf)
- {
- write (2, memmsg, sizeof (memmsg));
- host_exit (1);
- }
- p = newbuf + (p - buf);
- buf = newbuf;
- }
- }
line = p = buf;
while (1)
{
@@ -857,8 +740,6 @@ main (int argc, char **argv, char **envp)
/* The boot script has now been parsed into internal data structures.
Now execute its directives. */
{
- int err;
-
err = boot_script_exec ();
if (err)
{
@@ -873,8 +754,6 @@ main (int argc, char **argv, char **envp)
}
mach_port_deallocate (mach_task_self (), pseudo_master_device_port);
- if (is_user)
- mach_port_deallocate (mach_task_self (), subhurd_privileged_host_port);
err = pthread_create (&pthread_id, NULL, msg_thread, NULL);
if (!err)
@@ -892,7 +771,8 @@ main (int argc, char **argv, char **envp)
FD_SET (0, &rmask);
if (select (1, &rmask, 0, 0, 0) == 1)
read_reply ();
- else /* We hosed */
+ else if (errno != EINTR)
+ /* We hosed */
error (5, errno, "select");
}
}
@@ -1053,14 +933,9 @@ do_bootstrap_privileged_ports(bootstrap, hostp, devicep)
mach_port_t bootstrap;
mach_port_t *hostp, *devicep;
{
- if (is_user)
- /* I cannot use ports_get_right() here,
- * because the port will be copied to the client. */
- *hostp = pseudo_priv_host_pi->port_right;
- else
- *hostp = privileged_host_port;
- *devicep = pseudo_master_device_port;
- return KERN_SUCCESS;
+ *hostp = privileged_host_port;
+ *devicep = pseudo_master_device_port;
+ return KERN_SUCCESS;
}
/* Implementation of device interface */
@@ -1079,7 +954,9 @@ ds_device_open (mach_port_t master_port,
if (master_port != pseudo_master_device_port)
return D_INVALID_OPERATION;
- debug ("open %s", name);
+ if (verbose > 1)
+ fprintf (stderr, "Device '%s' being opened.\r\n", name);
+
if (!strcmp (name, "console"))
{
#if 0
@@ -1109,17 +986,24 @@ ds_device_open (mach_port_t master_port,
map = lookup_dev (name);
if (map)
{
+ error_t err;
+ file_t node;
+
+ node = file_name_lookup (map->file_name, 0, 0);
+ if (! MACH_PORT_VALID (node))
+ return D_NO_SUCH_DEVICE;
+
*devicetype = MACH_MSG_TYPE_MOVE_SEND;
- return device_open (map->port, mode, "", device);
+ err = device_open (node, mode, "", device);
+ mach_port_deallocate (mach_task_self (), node);
+ return err;
}
- if (is_user)
+ if (! privileged)
return D_NO_SUCH_DEVICE;
- else
- {
- *devicetype = MACH_MSG_TYPE_MOVE_SEND;
- return device_open (master_device_port, mode, name, device);
- }
+
+ *devicetype = MACH_MSG_TYPE_MOVE_SEND;
+ return device_open (master_device_port, mode, name, device);
}
kern_return_t
@@ -1314,7 +1198,7 @@ ds_device_read_inband (device_t device,
{
if (returned != data)
{
- bcopy (returned, (void *)data, *datalen);
+ memcpy ((void *)data, returned, *datalen);
munmap ((caddr_t) returned, *datalen);
}
return D_SUCCESS;
@@ -1436,55 +1320,23 @@ do_mach_notify_port_destroyed (mach_port_t notify,
return EOPNOTSUPP;
}
-boolean_t pseudo_priv_host_destroyed = FALSE;
-
-void
-destroy_priv_host (void *pi)
-{
- pseudo_priv_host_destroyed = TRUE;
- info ("pseudo privileged host port is destroyed");
-}
-
kern_return_t
do_mach_notify_no_senders (mach_port_t notify,
mach_port_mscount_t mscount)
{
static int no_console;
mach_port_t foo;
- error_t err = EOPNOTSUPP;
-
if (notify == pseudo_master_device_port)
{
- info ("pseudo master device port has no senders");
- /* for the root */
- if (no_console && !is_user)
- goto bye;
- /* for the normal user */
- if (no_console && is_user && pseudo_priv_host_destroyed)
+ if (no_console)
goto bye;
pseudo_master_device_port = MACH_PORT_NULL;
return 0;
}
- if (pseudo_priv_host_pi->port_right == notify && is_user)
- {
- if (no_console && pseudo_master_device_port == MACH_PORT_NULL)
- goto bye;
- pseudo_priv_host_destroyed = TRUE;
- return 0;
- }
if (notify == pseudo_console)
{
- info ("pseudo console has no senders");
- if (
- /* for the root */
- (mscount == console_mscount &&
- pseudo_master_device_port == MACH_PORT_NULL &&
- !is_user) ||
- /* for the normal user */
- (mscount == console_mscount &&
- pseudo_master_device_port == MACH_PORT_NULL &&
- pseudo_priv_host_destroyed &&
- is_user))
+ if (mscount == console_mscount &&
+ pseudo_master_device_port == MACH_PORT_NULL)
{
bye:
restore_termstate ();
@@ -1494,7 +1346,6 @@ do_mach_notify_no_senders (mach_port_t notify,
else
{
no_console = (mscount == console_mscount);
- info ("no console: %d", no_console);
mach_port_request_notification (mach_task_self (), pseudo_console,
MACH_NOTIFY_NO_SENDERS,
@@ -1507,10 +1358,8 @@ do_mach_notify_no_senders (mach_port_t notify,
mach_port_deallocate (mach_task_self (), foo);
}
}
-
- err = ports_do_mach_notify_no_senders (notify, mscount);
- return err;
+ return EOPNOTSUPP;
}
kern_return_t
@@ -1519,6 +1368,8 @@ do_mach_notify_send_once (mach_port_t notify)
return EOPNOTSUPP;
}
+static void task_died (mach_port_t name);
+
kern_return_t
do_mach_notify_dead_name (mach_port_t notify,
mach_port_t name)
@@ -1527,7 +1378,11 @@ 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);
+ mach_port_deallocate (mach_task_self (), name);
+ return 0;
}
@@ -1793,9 +1648,11 @@ S_io_reauthenticate (mach_port_t object,
size_t gulen = 0, aulen = 0, gglen = 0, aglen = 0;
error_t err;
+ /* XXX: This cannot possibly work, authserver is 0. */
+
err = mach_port_insert_right (mach_task_self (), object, object,
MACH_MSG_TYPE_MAKE_SEND);
- assert_perror (err);
+ assert_perror_backtrace (err);
do
err = auth_server_authenticate (authserver,
@@ -2085,3 +1942,164 @@ kern_return_t S_term_on_pty
io_t *ptymaster
)
{ return EOPNOTSUPP; }
+
+/* Mach host emulation. */
+
+kern_return_t
+S_vm_set_default_memory_manager (mach_port_t host_priv,
+ mach_port_t *default_manager)
+{
+ if (host_priv != pseudo_privileged_host_port)
+ return KERN_INVALID_HOST;
+
+ if (*default_manager != MACH_PORT_NULL)
+ return KERN_INVALID_ARGUMENT;
+
+ *default_manager = MACH_PORT_NULL;
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+S_host_reboot (mach_port_t host_priv,
+ int flags)
+{
+ fprintf (stderr, "Would %s the system. Bye.\r\n",
+ flags & 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)
+{
+ if (host_priv != pseudo_privileged_host_port)
+ return KERN_INVALID_HOST;
+
+ *set = pseudo_pset;
+ return KERN_SUCCESS;
+}
+
+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;
+}
+
+
+/* Managing tasks. */
+
+static void
+task_ihash_cleanup (hurd_ihash_value_t value, void *cookie)
+{
+ (void) cookie;
+ mach_port_deallocate (mach_task_self (), (mach_port_t) value);
+}
+
+static struct hurd_ihash task_ihash =
+ HURD_IHASH_INITIALIZER_GKI (HURD_IHASH_NO_LOCP, task_ihash_cleanup, NULL,
+ NULL, NULL);
+
+static void
+task_died (mach_port_t name)
+{
+ if (verbose > 1)
+ fprintf (stderr, "Task '%u' died.\r\n", name);
+
+ hurd_ihash_remove (&task_ihash, (hurd_ihash_key_t) name);
+}
+
+/* Handle new task notifications from proc. */
+error_t
+S_mach_notify_new_task (mach_port_t notify,
+ mach_port_t task,
+ mach_port_t parent)
+{
+ error_t err;
+ mach_port_t previous;
+
+ if (notify != task_notification_port)
+ return EOPNOTSUPP;
+
+ if (verbose > 1)
+ fprintf (stderr, "Task '%u' created by task '%u'.\r\n", task, parent);
+
+ err = 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 (err)
+ goto fail;
+ assert_backtrace (! MACH_PORT_VALID (previous));
+
+ mach_port_mod_refs (mach_task_self (), task, MACH_PORT_RIGHT_SEND, +1);
+ err = hurd_ihash_add (&task_ihash,
+ (hurd_ihash_key_t) task, (hurd_ihash_value_t) task);
+ if (err)
+ {
+ mach_port_deallocate (mach_task_self (), task);
+ goto fail;
+ }
+
+ 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;
+
+ fail:
+ task_terminate (task);
+ return err;
+}
+
+kern_return_t
+S_processor_set_tasks(mach_port_t processor_set,
+ task_array_t *task_list,
+ mach_msg_type_number_t *task_listCnt)
+{
+ error_t err;
+ size_t i;
+
+ if (!task_ihash.nr_items)
+ {
+ *task_listCnt = 0;
+ return 0;
+ }
+
+ err = vm_allocate (mach_task_self (), (vm_address_t *) task_list,
+ task_ihash.nr_items * sizeof **task_list, 1);
+ if (err)
+ return err;
+
+ /* The first task has to be the kernel. */
+ (*task_list)[0] = pseudo_kernel;
+
+ i = 1;
+ HURD_IHASH_ITERATE (&task_ihash, value)
+ {
+ task_t task = (task_t) value;
+ if (task == pseudo_kernel)
+ continue;
+
+ (*task_list)[i] = task;
+ i += 1;
+ }
+
+ *task_listCnt = task_ihash.nr_items;
+ return 0;
+}
diff --git a/boot/frank1.ld b/boot/frank1.ld
deleted file mode 100644
index 9de827ae7..000000000
--- a/boot/frank1.ld
+++ /dev/null
@@ -1,94 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386",
- "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
- SEARCH_DIR(/usr/local/i386-gnuelf/lib);
-/* Do we need any of these for elf?
- __DYNAMIC = 0; */
-SECTIONS
-{
- /* Read-only sections, merged into text segment: */
- . = 0x10020;
- .text :
- {
- *(.text)
- *(.interp)
- *(.hash)
- *(.dynsym)
- *(.dynstr)
- *(.rel.text)
- *(.rela.text)
- *(.rel.data)
- *(.rela.data)
- *(.rel.rodata)
- *(.rela.rodata)
- *(.rel.got)
- *(.rela.got)
- *(.rel.ctors)
- *(.rela.ctors)
- *(.rel.dtors)
- *(.rela.dtors)
- *(.rel.init)
- *(.rela.init)
- *(.rel.fini)
- *(.rela.fini)
- *(.rel.bss)
- *(.rela.bss)
- *(.rel.plt)
- *(.rela.plt)
- *(.init)
- *(.plt)
- /* .gnu.warning sections are handled specially by elf32.em. */
- *(.gnu.warning)
- *(.fini)
- *(.rodata)
- *(.rodata1)
- _etext = .;
- PROVIDE (etext = .);
- . = ALIGN(0x1000);
- } =0x9090
- . = ALIGN(0x1000);
- .data :
- {
- *(.data)
- CONSTRUCTORS
-
- *(.data1)
- *(.ctors)
- *(.dtors)
- *(.got.plt) *(.got)
- *(.dynamic)
- /* We want the small data sections together, so single-instruction offsets
- can access them all, and initialized data all before uninitialized, so
- we can shorten the on-disk segment size. */
- *(.sdata)
- _edata = .;
- PROVIDE (edata = .);
- . = ALIGN(0x10);
-}
- __bss_start = .;
- .bss :
- {
- *(.sbss) *(.scommon)
- *(.dynbss)
- *(.bss)
- *(COMMON)
- _end = ALIGN(4) ;
- PROVIDE (end = ALIGN(4));
- }
- /* These are needed for ELF backends which have not yet been
- converted to the new style linker. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- /* DWARF debug sections.
- Symbols in the .debug DWARF section are relative to the beginning of the
- section so we begin .debug at 0. It's not clear yet what needs to happen
- for the others. */
- .debug 0 : { *(.debug) }
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- .line 0 : { *(.line) }
- /* These must appear regardless of . */
-}
diff --git a/boot/frankemul.ld b/boot/frankemul.ld
deleted file mode 100644
index 413953efa..000000000
--- a/boot/frankemul.ld
+++ /dev/null
@@ -1,107 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386",
- "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
- SEARCH_DIR(/usr/local/i386-gnuelf/lib);
-/* Do we need any of these for elf?
- __DYNAMIC = 0; */
-SECTIONS
-{
- /* Read-only sections, merged into text segment: */
- . = 0x10020;
- .text :
- {
- *(.text)
- *(.interp)
- *(.hash)
- *(.dynsym)
- *(.dynstr)
- *(.rel.text)
- *(.rela.text)
- *(.rel.data)
- *(.rela.data)
- *(.rel.rodata)
- *(.rela.rodata)
- *(.rel.got)
- *(.rela.got)
- *(.rel.ctors)
- *(.rela.ctors)
- *(.rel.dtors)
- *(.rela.dtors)
- *(.rel.init)
- *(.rela.init)
- *(.rel.fini)
- *(.rela.fini)
- *(.rel.bss)
- *(.rela.bss)
- *(.rel.plt)
- *(.rela.plt)
- *(.init)
- *(.plt)
- /* .gnu.warning sections are handled specially by elf32.em. */
- *(.gnu.warning)
- *(.fini)
- *(.rodata)
- *(.rodata1)
-*(_hurd_ioctl_handler_lists)
-*(_hurd_pgrp_changed_hook)
-*(_hurd_fork_locks)
-*(_hurd_subinit)
-*(__libc_atexit)
-*(_hurd_fd_subinit)
-*(_hurd_preinit_hook)
-*(_hurd_fork_child_hook)
-*(_hurd_fork_parent_hook)
-*(_hurd_fork_prepare_hook)
-*(_hurd_reauth_hook)
-*(_hurd_proc_subinit)
-*(__libc_subinit)
- _etext = .;
- PROVIDE (etext = .);
- . = ALIGN(0x1000);
- } =0x9090
- . = ALIGN(0x1000);
- .data :
- {
- *(.data)
- CONSTRUCTORS
-
- *(.data1)
- *(.ctors)
- *(.dtors)
- *(.got.plt) *(.got)
- *(.dynamic)
- /* We want the small data sections together, so single-instruction offsets
- can access them all, and initialized data all before uninitialized, so
- we can shorten the on-disk segment size. */
- *(.sdata)
- _edata = .;
- PROVIDE (edata = .);
- . = ALIGN(0x10);
-}
- __bss_start = .;
- .bss :
- {
- *(.sbss) *(.scommon)
- *(.dynbss)
- *(.bss)
- *(COMMON)
- _end = ALIGN(4) ;
- PROVIDE (end = ALIGN(4));
- }
- /* These are needed for ELF backends which have not yet been
- converted to the new style linker. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- /* DWARF debug sections.
- Symbols in the .debug DWARF section are relative to the beginning of the
- section so we begin .debug at 0. It's not clear yet what needs to happen
- for the others. */
- .debug 0 : { *(.debug) }
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- .line 0 : { *(.line) }
- /* These must appear regardless of . */
-}
diff --git a/boot/mach-crt0.c b/boot/mach-crt0.c
deleted file mode 100644
index 0469424ef..000000000
--- a/boot/mach-crt0.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that: (1) source distributions retain this entire copyright
- * notice and comment, and (2) distributions including binaries display
- * the following acknowledgement: ``This product includes software
- * developed by the University of California, Berkeley and its contributors''
- * in the documentation or other materials provided with the distribution
- * and in all advertising materials mentioning features or use of this
- * software. Neither the name of the University nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)crt0.c 5.2 (Berkeley) 5/14/90";
-#endif /* not lint */
-
-/*
- * C start up routine.
- * Robert Henry, UCB, 20 Oct 81
- *
- * We make the following (true) assumptions:
- * 1) when the kernel calls start, it does a jump to location 2,
- * and thus avoids the register save mask. We are NOT called
- * with a calls! see sys1.c:setregs().
- * 2) The only register variable that we can trust is sp,
- * which points to the base of the kernel calling frame.
- * Do NOT believe the documentation in exec(2) regarding the
- * values of fp and ap.
- * 3) We can allocate as many register variables as we want,
- * and don't have to save them for anybody.
- * 4) Because of the ways that asm's work, we can't have
- * any automatic variables allocated on the stack, because
- * we must catch the value of sp before any automatics are
- * allocated.
- */
-
-#include <mach/machine/asm.h>
-
-int __data_start = 0;
-char **environ = (char **)0;
-#ifdef paranoid
-static int fd;
-#endif paranoid
-
-int (*mach_init_routine)();
-int (*_cthread_init_routine)();
-int (*_cthread_exit_routine)();
-int (*_monstartup_routine)();
-int (*_StrongBox_init_routine)();
-int errno = 0;
-int exit();
-
-extern int main();
-
-extern unsigned char etext;
-int _start()
-{
- __label__ eprol;
- struct kframe {
- int kargc;
- char *kargv[1]; /* size depends on kargc */
- char kargstr[1]; /* size varies */
- char kenvstr[1]; /* size varies */
- };
- /*
- * ALL REGISTER VARIABLES!!!
- */
- register struct kframe *kfp; /* r10 */
- register char **targv;
- register char **argv;
-
-#ifdef lint
- kfp = 0;
- initcode = initcode = 0;
-#else not lint
-#define Entry_sp() \
-({ int _spl__, _tmp1__; \
- asm volatile("leal 4(%%ebp), %0" : "=r" (_spl__) : "r" (_tmp1__)); \
- _spl__; })
-
- kfp = (struct kframe *)Entry_sp();
-#endif not lint
- for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
- /* void */ ;
- if (targv >= (char **)(*argv))
- --targv;
- environ = targv;
- if (mach_init_routine)
- (void) mach_init_routine();
-
- eprol:
-#ifdef paranoid
- /*
- * The standard I/O library assumes that file descriptors 0, 1, and 2
- * are open. If one of these descriptors is closed prior to the start
- * of the process, I/O gets very confused. To avoid this problem, we
- * insure that the first three file descriptors are open before calling
- * main(). Normally this is undefined, as it adds two unnecessary
- * system calls.
- */
- do {
- fd = open("/dev/null", 2);
- } while (fd >= 0 && fd < 3);
- close(fd);
-#endif paranoid
-
-
- if (_cthread_init_routine) {
- int new_sp;
- new_sp = (*_cthread_init_routine)();
- if (new_sp) {
- asm volatile("movl %0, %%esp" : : "g" (new_sp) );
- }
- }
- if (_StrongBox_init_routine) (*_StrongBox_init_routine)();
-
- if (_monstartup_routine) {
- _monstartup_routine(&&eprol, &etext);
- }
-
- (* (_cthread_exit_routine ? _cthread_exit_routine : exit))
- (main(kfp->kargc, argv, targv));
-}
diff --git a/boot/mig-decls.h b/boot/mig-decls.h
new file mode 100644
index 000000000..d539659b8
--- /dev/null
+++ b/boot/mig-decls.h
@@ -0,0 +1,27 @@
+/*
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Written by Justus Winter.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef __BOOT_MIG_DECLS_H__
+#define __BOOT_MIG_DECLS_H__
+
+#include <hurd.h>
+
+#define MIG_EOPNOTSUPP EOPNOTSUPP
+
+#endif /* __BOOT_MIG_DECLS_H__ */
diff --git a/boot/mig-mutate.h b/boot/mig-mutate.h
new file mode 100644
index 000000000..ef90b7347
--- /dev/null
+++ b/boot/mig-mutate.h
@@ -0,0 +1,25 @@
+/*
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Written by Justus Winter.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
+
+#define MACH_IMPORTS \
+ import "mig-decls.h";
+#define MACH_HOST_IMPORTS \
+ import "mig-decls.h";
+#define GNUMACH_IMPORTS \
+ import "mig-decls.h";
diff --git a/boot/private.h b/boot/private.h
new file mode 100644
index 000000000..463625211
--- /dev/null
+++ b/boot/private.h
@@ -0,0 +1,25 @@
+/* Boot boots Subhurds.
+
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef BOOT_PRIVATE_H
+#define BOOT_PRIVATE_H
+
+int verbose;
+
+#endif /* BOOT_PRIVATE_H */
diff --git a/boot/sigvec.S b/boot/sigvec.S
deleted file mode 100644
index cc7bb94e9..000000000
--- a/boot/sigvec.S
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <i386/asm.h>
-
-.text
-ENTRY(sigreturn)
- movl $0x67,%eax
- lcall $0x7,$0x0
- jb error
- ret
-ENTRY(_sigreturn)
- addl $0xc,%esp
- call EXT(sigreturn)
- ret
-ENTRY(sigvec)
- movl $0x6c,%eax
- movl $EXT(_sigreturn),%edx
- orl $0x80000000,%edx
- lcall $0x7,$0x0
- jb error
- ret
-error:
- movl %eax,EXT(errno)
- movl $-1,%eax
- ret
diff --git a/boot/syscall.S b/boot/syscall.S
deleted file mode 100644
index a04ab28d9..000000000
--- a/boot/syscall.S
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Temporary....
- Copyright (C) 1993, 1995 Free Software Foundation
-
-This file is part of the GNU Hurd.
-
-The GNU Hurd is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-The GNU Hurd is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with the GNU Hurd; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include <i386/asm.h>
-
-/* .globl EXT(errno)*/
-.text
-ENTRY(syscall)
- pop %ecx
- pop %eax
- push %ecx
- lcall $7, $0
- push %ecx /* Restore stack position. */
- jb error
- ret
-error:
- movl %eax,EXT(errno)
- movl $-1,%eax
- ret
diff --git a/boot/userland-boot.c b/boot/userland-boot.c
index 20c818ff9..2f9bd8cde 100644
--- a/boot/userland-boot.c
+++ b/boot/userland-boot.c
@@ -17,16 +17,21 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+#include <a.out.h>
+#include <elf.h>
+#include <fcntl.h>
#include <mach.h>
+#include <mach/machine/vm_param.h> /* For VM_XXX_ADDRESS */
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
#include <errno.h>
#include <error.h>
-#include "boot_script.h"
-#include "mach_proxy.h"
-#include "util.h"
-extern boolean_t is_user;
+#include "boot_script.h"
+#include "private.h"
void *
boot_script_malloc (unsigned int size)
@@ -40,27 +45,25 @@ boot_script_free (void *ptr, unsigned int size)
free (ptr);
}
+
int
boot_script_task_create (struct cmd *cmd)
{
- error_t err = task_create (mach_task_self (), 0, &cmd->task);
+ error_t err;
+
+ if (verbose)
+ fprintf (stderr, "Creating task '%s'.\r\n", cmd->path);
+
+ err = task_create (mach_task_self (), 0, &cmd->task);
if (err)
{
error (0, err, "%s: task_create", cmd->path);
return BOOT_SCRIPT_MACH_ERROR;
}
- debug ("creating task: %s, task port: %d", cmd->path, cmd->task);
- if (is_user)
- {
- task_t pseudo_task = 0;
- create_pseudo_task (cmd->task, &pseudo_task);
- /* now it is the pseudo task port. */
- cmd->task = pseudo_task;
- }
err = task_suspend (cmd->task);
if (err)
{
- error (0, err, "%s: task_suspend", cmd->path);
+ error (0, err, "%s: task_resume", cmd->path);
return BOOT_SCRIPT_MACH_ERROR;
}
return 0;
@@ -69,8 +72,12 @@ boot_script_task_create (struct cmd *cmd)
int
boot_script_task_resume (struct cmd *cmd)
{
- debug ("resume task %s: %d", cmd->path, cmd->task);
- error_t err = task_resume (cmd->task);
+ error_t err;
+
+ if (verbose)
+ fprintf (stderr, "Resuming task '%s'.\r\n", cmd->path);
+
+ err = task_resume (cmd->task);
if (err)
{
error (0, err, "%s: task_resume", cmd->path);
@@ -95,23 +102,30 @@ boot_script_free_task (task_t task, int aborting)
{
if (aborting)
task_terminate (task);
- else if (!is_user)
+ else
mach_port_deallocate (mach_task_self (), task);
- /* For the normal user, the task port will still be used,
- * so we cannot deallocate the task port here.*/
}
int
boot_script_insert_right (struct cmd *cmd, mach_port_t port, mach_port_t *name)
{
- error_t err = mach_port_insert_right (cmd->task,
- port, port, MACH_MSG_TYPE_COPY_SEND);
+ error_t err;
+
+ *name = MACH_PORT_NULL;
+ do
+ {
+ *name += 1;
+ err = mach_port_insert_right (cmd->task,
+ *name, port, MACH_MSG_TYPE_COPY_SEND);
+ }
+ while (err == KERN_NAME_EXISTS);
+
if (err)
{
error (0, err, "%s: mach_port_insert_right", cmd->path);
return BOOT_SCRIPT_MACH_ERROR;
}
- *name = port;
+
return 0;
}
@@ -120,3 +134,206 @@ boot_script_insert_task_port (struct cmd *cmd, task_t task, mach_port_t *name)
{
return boot_script_insert_right (cmd, task, name);
}
+
+char *useropen_dir;
+
+static int
+useropen (const char *name, int flags, int mode)
+{
+ if (useropen_dir)
+ {
+ static int dlen;
+ if (!dlen) dlen = strlen (useropen_dir);
+ {
+ int len = strlen (name);
+ char try[dlen + 1 + len + 1];
+ int fd;
+ memcpy (try, useropen_dir, dlen);
+ try[dlen] = '/';
+ memcpy (&try[dlen + 1], name, len + 1);
+ fd = open (try, flags, mode);
+ if (fd >= 0)
+ return fd;
+ }
+ }
+ return open (name, flags, mode);
+}
+
+static vm_address_t
+load_image (task_t t,
+ char *file)
+{
+ int fd;
+ union
+ {
+ struct exec a;
+ Elf32_Ehdr e;
+ } hdr;
+ char msg[] = ": cannot open bootstrap file\n";
+
+ fd = useropen (file, O_RDONLY, 0);
+
+ if (fd == -1)
+ {
+ write (2, file, strlen (file));
+ write (2, msg, sizeof msg - 1);
+ task_terminate (t);
+ exit (1);
+ }
+
+ read (fd, &hdr, sizeof hdr);
+ /* File must have magic ELF number. */
+ if (hdr.e.e_ident[0] == 0177 && hdr.e.e_ident[1] == 'E' &&
+ hdr.e.e_ident[2] == 'L' && hdr.e.e_ident[3] == 'F')
+ {
+ Elf32_Phdr phdrs[hdr.e.e_phnum], *ph;
+ lseek (fd, hdr.e.e_phoff, SEEK_SET);
+ read (fd, phdrs, sizeof phdrs);
+ for (ph = phdrs; ph < &phdrs[sizeof phdrs/sizeof phdrs[0]]; ++ph)
+ if (ph->p_type == PT_LOAD)
+ {
+ vm_address_t buf;
+ vm_size_t offs = ph->p_offset & (ph->p_align - 1);
+ vm_size_t bufsz = round_page (ph->p_filesz + offs);
+
+ buf = (vm_address_t) mmap (0, bufsz,
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+
+ lseek (fd, ph->p_offset, SEEK_SET);
+ read (fd, (void *)(buf + offs), ph->p_filesz);
+
+ ph->p_memsz = ((ph->p_vaddr + ph->p_memsz + ph->p_align - 1)
+ & ~(ph->p_align - 1));
+ ph->p_vaddr &= ~(ph->p_align - 1);
+ ph->p_memsz -= ph->p_vaddr;
+
+ vm_allocate (t, (vm_address_t*)&ph->p_vaddr, ph->p_memsz, 0);
+ vm_write (t, ph->p_vaddr, buf, bufsz);
+ munmap ((caddr_t) buf, bufsz);
+ vm_protect (t, ph->p_vaddr, ph->p_memsz, 0,
+ ((ph->p_flags & PF_R) ? VM_PROT_READ : 0) |
+ ((ph->p_flags & PF_W) ? VM_PROT_WRITE : 0) |
+ ((ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0));
+ }
+ return hdr.e.e_entry;
+ }
+ else
+ {
+ /* a.out */
+ int magic = N_MAGIC (hdr.a);
+ int headercruft;
+ vm_address_t base = 0x10000;
+ int rndamount, amount;
+ vm_address_t bsspagestart, bssstart;
+ char *buf;
+
+ headercruft = sizeof (struct exec) * (magic == ZMAGIC);
+
+ amount = headercruft + hdr.a.a_text + hdr.a.a_data;
+ rndamount = round_page (amount);
+ buf = mmap (0, rndamount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ lseek (fd, sizeof hdr.a - headercruft, SEEK_SET);
+ read (fd, buf, amount);
+ vm_allocate (t, &base, rndamount, 0);
+ vm_write (t, base, (vm_address_t) buf, rndamount);
+ if (magic != OMAGIC)
+ vm_protect (t, base, trunc_page (headercruft + hdr.a.a_text),
+ 0, VM_PROT_READ | VM_PROT_EXECUTE);
+ munmap ((caddr_t) buf, rndamount);
+
+ bssstart = base + hdr.a.a_text + hdr.a.a_data + headercruft;
+ bsspagestart = round_page (bssstart);
+ vm_allocate (t, &bsspagestart,
+ hdr.a.a_bss - (bsspagestart - bssstart), 0);
+
+ return hdr.a.a_entry;
+ }
+}
+
+int
+boot_script_exec_cmd (void *hook,
+ mach_port_t task, char *path, int argc,
+ char **argv, char *strings, int stringlen)
+{
+ char *args, *p;
+ int arg_len, i;
+ size_t reg_size;
+ void *arg_pos;
+ vm_offset_t stack_start, stack_end;
+ vm_address_t startpc, str_start;
+ thread_t thread;
+
+ write (2, path, strlen (path));
+ for (i = 1; i < argc; ++i)
+ {
+ int quote = !! index (argv[i], ' ') || !! index (argv[i], '\t');
+ write (2, " ", 1);
+ if (quote)
+ write (2, "\"", 1);
+ write (2, argv[i], strlen (argv[i]));
+ if (quote)
+ write (2, "\"", 1);
+ }
+ write (2, "\r\n", 2);
+
+ startpc = load_image (task, path);
+ arg_len = stringlen + (argc + 2) * sizeof (char *) + sizeof (integer_t);
+ arg_len += 5 * sizeof (int);
+ stack_end = VM_MAX_ADDRESS;
+ stack_start = VM_MAX_ADDRESS - 16 * 1024 * 1024;
+ vm_allocate (task, &stack_start, stack_end - stack_start, FALSE);
+ arg_pos = (void *) ((stack_end - arg_len) & ~(sizeof (natural_t) - 1));
+ args = mmap (0, stack_end - trunc_page ((vm_offset_t) arg_pos),
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ str_start = ((vm_address_t) arg_pos
+ + (argc + 2) * sizeof (char *) + sizeof (integer_t));
+ p = args + ((vm_address_t) arg_pos & (vm_page_size - 1));
+ *(int *) p = argc;
+ p = (void *) p + sizeof (int);
+ for (i = 0; i < argc; i++)
+ {
+ *(char **) p = argv[i] - strings + (char *) str_start;
+ p = (void *) p + sizeof (char *);
+ }
+ *(char **) p = 0;
+ p = (void *) p + sizeof (char *);
+ *(char **) p = 0;
+ p = (void *) p + sizeof (char *);
+ memcpy (p, strings, stringlen);
+ memset (args, 0, (vm_offset_t)arg_pos & (vm_page_size - 1));
+ vm_write (task, trunc_page ((vm_offset_t) arg_pos), (vm_address_t) args,
+ stack_end - trunc_page ((vm_offset_t) arg_pos));
+ munmap ((caddr_t) args,
+ stack_end - trunc_page ((vm_offset_t) arg_pos));
+
+ thread_create (task, &thread);
+#ifdef i386_THREAD_STATE_COUNT
+ {
+ struct i386_thread_state regs;
+ reg_size = i386_THREAD_STATE_COUNT;
+ thread_get_state (thread, i386_THREAD_STATE,
+ (thread_state_t) &regs, &reg_size);
+ regs.eip = (int) startpc;
+ regs.uesp = (int) arg_pos;
+ thread_set_state (thread, i386_THREAD_STATE,
+ (thread_state_t) &regs, reg_size);
+ }
+#elif defined(ALPHA_THREAD_STATE_COUNT)
+ {
+ struct alpha_thread_state regs;
+ reg_size = ALPHA_THREAD_STATE_COUNT;
+ thread_get_state (thread, ALPHA_THREAD_STATE,
+ (thread_state_t) &regs, &reg_size);
+ regs.r30 = (natural_t) arg_pos;
+ regs.pc = (natural_t) startpc;
+ thread_set_state (thread, ALPHA_THREAD_STATE,
+ (thread_state_t) &regs, reg_size);
+ }
+#else
+# error needs to be ported
+#endif
+
+ thread_resume (thread);
+ mach_port_deallocate (mach_task_self (), thread);
+ return 0;
+}
diff --git a/boot/ux.c b/boot/ux.c
deleted file mode 100644
index 7239762cc..000000000
--- a/boot/ux.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/* Hacks to make boot work under UX
-
- Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
- This file is part of the GNU Hurd.
-
- The GNU Hurd is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- The GNU Hurd is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with the GNU Hurd; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include <mach.h>
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <pthread.h>
-
-#include "ux.h"
-
-#if 0
-static int (* const _sc)(int, ...) = &syscall;
-int _sc_print = 1;
-
-#define syscall(num, args...) \
- ({ int _rv, _num = (num), _pr = _sc_print; \
- _sc_print = 0; \
- if (_pr) printf ("syscall (%d) start\r\n", _num); \
- _rv = (*_sc) (_num , ##args); \
- if (_pr) printf ("syscall (%d) end\r\n", _num); \
- _sc_print = _pr; \
- _rv; \
- })
-#endif
-
-extern void __mach_init ();
-void (*mach_init_routine)() = __mach_init;
-
-/* These will prevent the Hurd-ish versions from being used */
-
-struct free_reply_port
-{
- mach_port_t port;
- struct free_reply_port *next;
-};
-static struct free_reply_port *free_reply_ports = NULL;
-static pthread_spinlock_t free_reply_ports_lock = PTHREAD_SPINLOCK_INITIALIZER;
-
-mach_port_t __mig_get_reply_port ()
-{
- pthread_spin_lock (&free_reply_ports_lock);
- if (free_reply_ports == NULL)
- {
- pthread_spin_unlock (&free_reply_ports_lock);
- return __mach_reply_port ();
- }
- else
- {
- struct free_reply_port *frp = free_reply_ports;
- mach_port_t reply_port = frp->port;
- free_reply_ports = free_reply_ports->next;
- pthread_spin_unlock (&free_reply_ports_lock);
- free (frp);
- return reply_port;
- }
-}
-mach_port_t mig_get_reply_port ()
-{
- return __mig_get_reply_port ();
-}
-void __mig_put_reply_port (mach_port_t port)
-{
- struct free_reply_port *frp = malloc (sizeof (struct free_reply_port));
- frp->port = port;
- pthread_spin_lock (&free_reply_ports_lock);
- frp->next = free_reply_ports;
- free_reply_ports = frp;
- pthread_spin_unlock (&free_reply_ports_lock);
-}
-void mig_put_reply_port (mach_port_t port)
-{
- __mig_put_reply_port (port);
-}
-void __mig_dealloc_reply_port (mach_port_t port)
-{
- mach_port_mod_refs (__mach_task_self (), port,
- MACH_PORT_RIGHT_RECEIVE, -1);
-}
-void mig_dealloc_reply_port (mach_port_t port)
-{
- __mig_dealloc_reply_port (port);
-}
-void __mig_init (void *stack) {}
-void mig_init (void *stack) {}
-
-int
-task_by_pid (int pid)
-{
- return syscall (-33, pid);
-}
-
-int
-write (int fd,
- const void *buf,
- int buflen)
-{
- return syscall (4, fd, buf, buflen);
-}
-
-int
-read (int fd,
- void *buf,
- int buflen)
-{
- return syscall (3, fd, buf, buflen);
-}
-
-int
-open (const char *name,
- int flags,
- int mode)
-{
- return syscall (5, name, flags, mode);
-}
-
-int
-uxfstat (int fd, struct uxstat *buf)
-{
- return syscall (62, fd, buf);
-}
-
-int
-close (int fd)
-{
- return syscall (6, fd);
-}
-
-int
-lseek (int fd,
- int off,
- int whence)
-{
- return syscall (19, fd, off, whence);
-}
-
-int
-uxexit (int code)
-{
- return syscall (1, code);
-}
-
-int
-getpid ()
-{
- return syscall (20);
-}
-
-int
-ioctl (int fd, int code, void *buf)
-{
- return syscall (54, fd, code, buf);
-}
-
-int
-sigblock (int mask)
-{
- return syscall (109, mask);
-}
-
-int
-sigsetmask (int mask)
-{
- return syscall (110, mask);
-}
-
-int
-sigpause (int mask)
-{
- return syscall (111, mask);
-}
-
-
-#if 0
-void
-sigreturn ()
-{
- asm volatile ("movl $0x67,%eax\n"
- "lcall $0x7, $0x0\n"
- "ret");
-}
-
-void
-_sigreturn ()
-{
- asm volatile ("addl $0xc, %%esp\n"
- "call %0\n"
- "ret"::"m" (sigreturn));
-}
-
-int
-sigvec (int sig, struct sigvec *vec, struct sigvec *ovec)
-{
- asm volatile ("movl $0x6c,%%eax\n"
- "movl %0, %%edx\n"
- "orl $0x80000000, %%edx\n"
- "lcall $0x7,$0x0\n"
- "ret"::"g" (_sigreturn));
-}
-#else
-int sigvec ();
-#endif
-
-void get_privileged_ports (mach_port_t *host_port, mach_port_t *device_port)
-{
- *host_port = task_by_pid (-1);
- *device_port = task_by_pid (-2);
-}
-
-/* A *really* stupid printf that only understands %s & %d. */
-int
-printf (const char *fmt, ...)
-{
- va_list ap;
- const char *p = fmt, *q = p;
-
- void flush (const char *new)
- {
- if (p > q)
- write (1, q, p - q);
- q = p = new;
- }
-
- va_start (ap, fmt);
- while (*p)
- if (*p == '%' && p[1] == 's')
- {
- char *str = va_arg (ap, char *);
- flush (p + 2);
- write (1, str, strlen (str));
- }
- else if (*p == '%' && p[1] == 'd')
- {
- int i = va_arg (ap, int);
- char rbuf[20], *e = rbuf + sizeof (rbuf), *b = e;
-
- if (i == 0)
- *--b = '0';
- else
- while (i)
- {
- *--b = i % 10 + '0';
- i /= 10;
- }
-
- flush (p + 2);
- write (1, b, e - b);
- }
- else
- p++;
- va_end (ap);
-
- flush (0);
-
- return 0;
-}
-
-static struct sgttyb term_sgb;
-static int localbits;
-
-void
-init_termstate ()
-{
- struct sgttyb sgb;
- int bits;
- ioctl (0, TIOCGETP, &term_sgb);
- ioctl (0, TIOCLGET, &localbits);
- /* Enter raw made. Rather than try and interpret these bits,
- we just do what emacs does in .../emacs/src/sysdep.c for
- an old style terminal driver. */
- bits = localbits | LDECCTQ | LLITOUT | LPASS8 | LNOFLSH;
- ioctl (0, TIOCLSET, &bits);
- sgb = term_sgb;
- sgb.sg_flags &= ~ECHO;
- sgb.sg_flags |= RAW | ANYP;
- ioctl (0, TIOCSETN, &sgb);
-}
-
-void
-restore_termstate ()
-{
- ioctl (0, TIOCLSET, &localbits);
- ioctl (0, TIOCSETN, &term_sgb);
-}
diff --git a/boot/ux.h b/boot/ux.h
deleted file mode 100644
index d3787c548..000000000
--- a/boot/ux.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Hacks to make boot work under UX
-
- Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
- This file is part of the GNU Hurd.
-
- The GNU Hurd is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- The GNU Hurd is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with the GNU Hurd; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#define sigmask(m) (1 << ((m)-1))
-
-#define IOCPARM_MASK 0x7f
-#define IOC_OUT 0x40000000
-#define IOC_IN 0x80000000
-#define _IOR(x,y,t) (IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
-#define _IOW(x,y,t) (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
-#define FIONREAD _IOR('f', 127, int)
-#define FIOASYNC _IOW('f', 125, int)
-#define TIOCGETP _IOR('t', 8, struct sgttyb)
-#define TIOCLGET _IOR('t', 124, int)
-#define TIOCLSET _IOW('t', 125, int)
-#define TIOCSETN _IOW('t', 10, struct sgttyb)
-#define LDECCTQ 0x4000
-#define LLITOUT 0x0020
-#define LPASS8 0x0800
-#define LNOFLSH 0x8000
-#define RAW 0x0020
-#define ANYP 0x00c0
-#define ECHO 8
-
-
-struct sgttyb
-{
- char unused[4];
- short sg_flags;
-};
-
-#define SIGIO 23
-
-struct sigvec
-{
- void (*sv_handler)();
- int sv_mask;
- int sv_flags;
-};
-
-struct uxstat
- {
- short int st_dev; /* Device containing the file. */
- __ino_t st_ino; /* File serial number. */
- unsigned short int st_mode; /* File mode. */
- __nlink_t st_nlink; /* Link count. */
- unsigned short int st_uid; /* User ID of the file's owner. */
- unsigned short int st_gid; /* Group ID of the file's group.*/
- short int st_rdev; /* Device number, if device. */
- __off_t st_size; /* Size of file, in bytes. */
- __time_t st_atime; /* Time of last access. */
- unsigned long int st_atime_usec;
- __time_t st_mtime; /* Time of last modification. */
- unsigned long int st_mtime_usec;
- __time_t st_ctime; /* Time of last status change. */
- unsigned long int st_ctime_usec;
- unsigned long int st_blksize; /* Optimal block size for I/O. */
- unsigned long int st_blocks; /* Number of 512-byte blocks allocated. */
- long int st_spare[2];
- };
-
-void get_privileged_ports (mach_port_t *host_port, mach_port_t *device_port);
-
-/* We can't include <unistd.h> for this, because that will fight witho
- our definitions of syscalls below. */
-int syscall (int, ...);
-
-int open (const char *name, int flags, int mode);
-int write (int fd, const void *buf, int len);
-int read (int fd, void *buf, int len);
-int uxfstat (int fd, struct uxstat *buf);
-int close (int fd);
-int lseek (int fd, int off, int whence);
-int uxexit (int code);
-int getpid ();
-int ioctl (int fd, int code, void *buf);
-int sigblock (int mask);
-int sigsetmask (int mask);
-int sigpause (int mask);
-int sigvec (int sig, struct sigvec *vec, struct sigvec *ovec);
-
-#undef O_RDONLY
-#undef O_WRONLY
-#undef O_RDWR
-#define O_RDONLY 0
-#define O_WRONLY 1
-#define O_RDWR 2
-
-#define host_exit(c) uxexit(c)
-
-typedef struct uxstat host_stat_t;
-#define host_fstat(fd, st) uxfstat (fd, st)
-
-void init_stdio ();
-
-#undef errno
-int errno;