aboutsummaryrefslogtreecommitdiff
path: root/boot/boot.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot/boot.c')
-rw-r--r--boot/boot.c852
1 files changed, 478 insertions, 374 deletions
diff --git a/boot/boot.c b/boot/boot.c
index dcf3bccc..2b143844 100644
--- a/boot/boot.c
+++ b/boot/boot.c
@@ -1,6 +1,7 @@
/* Load a task using the single server, and then run it
as if we were the kernel.
- Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1993,94,95,96,97,98,99,2000,01,02,2006
+ Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -30,14 +31,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <string.h>
#include <stdio.h>
#include <cthreads.h>
-#include <varargs.h>
-#include <fcntlbits.h>
+#include <fcntl.h>
#include <elf.h>
#include <mach/mig_support.h>
#include <mach/default_pager.h>
+#include <argp.h>
+#include <hurd/store.h>
+#include <sys/mman.h>
+#include <version.h>
#include "notify_S.h"
-#include "exec_S.h"
#include "ourdevice_S.h"
#include "io_S.h"
#include "device_reply_U.h"
@@ -51,6 +54,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#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"
@@ -64,8 +73,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <termios.h>
#include <error.h>
#include <hurd.h>
+#include <assert.h>
static struct termios orig_tty_state;
+static int isig;
+static char *kernel_command_line;
static void
init_termstate ()
@@ -77,6 +89,8 @@ init_termstate ()
orig_tty_state = tty_state;
cfmakeraw (&tty_state);
+ if (isig)
+ tty_state.c_lflag |= ISIG;
if (tcsetattr (0, 0, &tty_state) < 0)
error (11, errno, "tcsetattr");
@@ -97,9 +111,11 @@ typedef struct stat host_stat_t;
mach_port_t privileged_host_port, master_device_port, defpager;
mach_port_t pseudo_master_device_port;
mach_port_t receive_set;
-mach_port_t pseudo_console;
+mach_port_t pseudo_console, pseudo_root;
auth_t authserver;
+struct store *root_store;
+
spin_lock_t queuelock = SPIN_LOCK_INITIALIZER;
spin_lock_t readlock = SPIN_LOCK_INITIALIZER;
@@ -118,10 +134,10 @@ void restore_termstate ();
char *fsname;
-char *bootstrap_args;
-char *bootdevice = "sd0a";
+char bootstrap_args[100] = "-";
+char *bootdevice = 0;
+char *bootscript = 0;
-void set_mach_stack_args ();
void safe_gets (char *buf, int buf_len)
{
@@ -219,7 +235,8 @@ load_image (task_t t,
vm_size_t offs = ph->p_offset & (ph->p_align - 1);
vm_size_t bufsz = round_page (ph->p_filesz + offs);
- vm_allocate (mach_task_self (), &buf, bufsz, 1);
+ 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);
@@ -231,7 +248,7 @@ load_image (task_t t,
vm_allocate (t, (vm_address_t*)&ph->p_vaddr, ph->p_memsz, 0);
vm_write (t, ph->p_vaddr, buf, bufsz);
- vm_deallocate (mach_task_self (), 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) |
@@ -253,15 +270,15 @@ load_image (task_t t,
amount = headercruft + hdr.a.a_text + hdr.a.a_data;
rndamount = round_page (amount);
- vm_allocate (mach_task_self (), (u_int *)&buf, rndamount, 1);
+ 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, (u_int) buf, rndamount);
+ 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);
- vm_deallocate (mach_task_self (), (u_int)buf, rndamount);
+ munmap ((caddr_t) buf, rndamount);
bssstart = base + hdr.a.a_text + hdr.a.a_data + headercruft;
bsspagestart = round_page (bssstart);
@@ -278,18 +295,6 @@ void msg_thread ();
/* Callbacks for boot_script.c; see boot_script.h. */
-void *
-boot_script_malloc (int size)
-{
- return malloc (size);
-}
-
-void
-boot_script_free (void *ptr, int size)
-{
- free (ptr);
-}
-
mach_port_t
boot_script_read_file (const char *filename)
{
@@ -324,116 +329,243 @@ boot_script_read_file (const char *filename)
vm_map (mach_task_self (), &region, round_page (st.st_size),
0, 1, memobj, 0, 0, VM_PROT_ALL, VM_PROT_ALL, VM_INHERIT_NONE);
read (fd, (char *) region, st.st_size);
- vm_deallocate (mach_task_self (), region, round_page (st.st_size));
+ munmap ((caddr_t) region, round_page (st.st_size));
close (fd);
return memobj;
}
int
-boot_script_exec_cmd (mach_port_t task, char *path, int argc,
+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;
- unsigned reg_size;
+ size_t reg_size;
void *arg_pos;
vm_offset_t stack_start, stack_end;
vm_address_t startpc, str_start;
thread_t thread;
- struct i386_thread_state regs;
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);
- thread_create (task, &thread);
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);
- 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) ((stack_end - arg_len) & ~(sizeof (int) - 1));
- thread_set_state (thread, i386_THREAD_STATE,
- (thread_state_t) &regs, reg_size);
- arg_pos = (void *) regs.uesp;
- vm_allocate (mach_task_self (), (vm_address_t *) &args,
- stack_end - trunc_page ((vm_offset_t) arg_pos), TRUE);
+ 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;
+ *(int *) p = argc;
+ p = (void *) p + sizeof (int);
for (i = 0; i < argc; i++)
- *((char **) p)++ = argv[i] - strings + (char *) str_start;
- *((char **) p)++ = 0;
- *((char **) p)++ = 0;
+ {
+ *(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);
bzero (args, (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));
- vm_deallocate (mach_task_self (), (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);
+
+static struct argp_option options[] =
+{
+ { "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" },
+ { "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."},
+ { 0 }
+};
+static char args_doc[] = "BOOT-SCRIPT";
+static char doc[] = "Boot a second hurd";
+
+struct dev_map
+{
+ char *name;
+ mach_port_t port;
+ struct dev_map *next;
+};
+
+static struct dev_map *dev_map_head;
+
+static struct dev_map *add_dev_map (char *dev_name, char *dev_file)
+{
+ struct dev_map *map = malloc (sizeof (*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);
+ map->next = dev_map_head;
+ dev_map_head = map;
+ return map;
+}
+
+static struct dev_map *lookup_dev (char *dev_name)
+{
+ struct dev_map *map;
+
+ for (map = dev_map_head; map; map = map->next)
+ {
+ if (strcmp (map->name, dev_name) == 0)
+ return map;
+ }
+ return NULL;
+}
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ char *dev_file;
+
+ switch (key)
+ {
+ size_t len;
+
+ case 'c': kernel_command_line = arg; break;
+
+ case 'D': useropen_dir = arg; break;
+
+ case 'I': isig = 1; break;
+
+ case 's': case 'd':
+ len = strlen (bootstrap_args);
+ if (len >= sizeof bootstrap_args - 1)
+ argp_error (state, "Too many bootstrap args");
+ bootstrap_args[len++] = key;
+ bootstrap_args[len] = '\0';
+ break;
+
+ case 'f':
+ dev_file = strchr (arg, '=');
+ if (dev_file == NULL)
+ return ARGP_ERR_UNKNOWN;
+ *dev_file = 0;
+ add_dev_map (arg, dev_file+1);
+ break;
+
+ case ARGP_KEY_ARG:
+ if (state->arg_num == 0)
+ bootscript = arg;
+ else
+ return ARGP_ERR_UNKNOWN;
+ break;
+
+ case ARGP_KEY_INIT:
+ state->child_inputs[0] = state->input; break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
int
main (int argc, char **argv, char **envp)
{
+ error_t err;
mach_port_t foo;
- static const char usagemsg[]
- = "Usage: boot [-D dir] [SWITCHES] SCRIPT ROOT-DEVICE\n";
char *buf = 0;
- char *bootscript;
int i, len;
- char *newargs;
+ char *root_store_name;
+ const struct argp_child kids[] = { { &store_argp }, { 0 }};
+ struct argp argp = { options, parse_opt, args_doc, doc, kids };
+ struct store_argp_params store_argp_params = { 0 };
+
+ argp_parse (&argp, argc, argv, 0, 0, &store_argp_params);
+ err = store_parsed_name (store_argp_params.result, &root_store_name);
+ if (err)
+ error (2, err, "store_parsed_name");
+
+ err = store_parsed_open (store_argp_params.result, 0, &root_store);
+ if (err)
+ error (4, err, "%s", root_store_name);
get_privileged_ports (&privileged_host_port, &master_device_port);
defpager = MACH_PORT_NULL;
vm_set_default_memory_manager (privileged_host_port, &defpager);
- if (argc < 2 || (argv[1][0] == '-' && argc < 3))
- {
- usage:
- write (2, usagemsg, sizeof usagemsg);
- host_exit (1);
- }
+ strcat (bootstrap_args, "f");
- if (!strcmp (argv[1], "-D"))
- {
- if (argc < 4)
- goto usage;
- useropen_dir = argv[2];
- argv += 2;
- }
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET,
+ &receive_set);
- if (argv[1][0] != '-')
- {
- bootstrap_args = "-x";
- bootscript = argv[1];
- bootdevice = argv[2];
- }
+ 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)
+ /* Let known device nodes pass through directly. */
+ bootdevice = root_store->name;
else
+ /* Pass a magic value that we can use to do I/O to ROOT_STORE. */
{
- bootstrap_args = argv[1];
- bootscript = argv[2];
- bootdevice = argv[3];
+ bootdevice = "pseudo-root";
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &pseudo_root);
+ mach_port_move_member (mach_task_self (), pseudo_root, receive_set);
}
- newargs = malloc (strlen (bootstrap_args) + 2);
- strcpy (newargs, bootstrap_args);
- strcat (newargs, "f");
- bootstrap_args = newargs;
-
- mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET,
- &receive_set);
-
mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
&pseudo_master_device_port);
mach_port_insert_right (mach_task_self (),
@@ -458,13 +590,21 @@ main (int argc, char **argv, char **envp)
if (foo != MACH_PORT_NULL)
mach_port_deallocate (mach_task_self (), foo);
+ 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) privileged_host_port)
|| boot_script_set_variable ("device-port", VAL_PORT,
- (int) pseudo_master_device_port)
- || boot_script_set_variable ("root-device", VAL_STR, (int) bootdevice)
- || boot_script_set_variable ("boot-args", VAL_STR, (int) bootstrap_args))
+ (integer_t) pseudo_master_device_port)
+ || boot_script_set_variable ("kernel-command-line", VAL_STR,
+ (integer_t) kernel_command_line)
+ || boot_script_set_variable ("root-device",
+ VAL_STR, (integer_t) bootdevice)
+ || boot_script_set_variable ("boot-args",
+ VAL_STR, (integer_t) bootstrap_args))
{
static const char msg[] = "error setting variable";
@@ -472,10 +612,38 @@ main (int argc, char **argv, char **envp)
host_exit (1);
}
+ /* Turn each `FOO=BAR' word in the command line into a boot script
+ variable ${FOO} with value BAR. */
+ {
+ int len = strlen (kernel_command_line) + 1;
+ char *s = memcpy (alloca (len), kernel_command_line, len);
+ char *word;
+
+ while ((word = strsep (&s, " \t")) != 0)
+ {
+ char *eq = strchr (word, '=');
+ if (eq == 0)
+ continue;
+ *eq++ = '\0';
+ err = boot_script_set_variable (word, VAL_STR, (integer_t) eq);
+ if (err)
+ {
+ char *msg;
+ asprintf (&msg, "cannot set boot-script variable %s: %s\n",
+ word, boot_script_error_string (err));
+ assert (msg);
+ write (2, msg, strlen (msg));
+ free (msg);
+ host_exit (1);
+ }
+ }
+ }
+
/* Parse the boot script. */
{
char *p, *line;
- static const char filemsg[] = "Can't open boot script";
+ static const char filemsg[] = "Can't open boot script\n";
+ static const char memmsg[] = "Not enough memory\n";
int amt, fd, err;
fd = open (bootscript, O_RDONLY, 0);
@@ -485,6 +653,11 @@ main (int argc, char **argv, char **envp)
host_exit (1);
}
p = buf = malloc (500);
+ if (!buf)
+ {
+ write (2, memmsg, sizeof (memmsg));
+ host_exit (1);
+ }
len = 500;
amt = 0;
while (1)
@@ -500,6 +673,11 @@ main (int argc, char **argv, char **envp)
len += 500;
newbuf = realloc (buf, len);
+ if (!newbuf)
+ {
+ write (2, memmsg, sizeof (memmsg));
+ host_exit (1);
+ }
p = newbuf + (p - buf);
buf = newbuf;
}
@@ -510,7 +688,7 @@ main (int argc, char **argv, char **envp)
while (p < buf + amt && *p != '\n')
p++;
*p = '\0';
- err = boot_script_parse_line (line);
+ err = boot_script_parse_line (0, line);
if (err)
{
char *str;
@@ -552,6 +730,7 @@ main (int argc, char **argv, char **envp)
int i = strlen (str);
write (2, str, i);
+ write (2, "\n", 1);
host_exit (1);
}
free (buf);
@@ -568,206 +747,13 @@ main (int argc, char **argv, char **envp)
FD_SET (0, &rmask);
if (select (1, &rmask, 0, 0, 0) == 1)
read_reply ();
- else
- { /* We hosed */
- perror ("select");
- exit (5);
- }
+ else /* We hosed */
+ error (5, errno, "select");
}
/* mach_msg_server (request_server, __vm_page_size * 2, receive_set); */
}
-/* Set up stack args the Mach way */
-void
-set_mach_stack_args (user_task,
- user_thread,
- startpc,
- va_alist)
- task_t user_task;
- thread_t user_thread;
- char *startpc;
- va_dcl
-{
- /* This code is lifted from .../mk/bootstrap/load.c. */
- va_list argv_ptr;
- char * arg_ptr;
-
- int arg_len;
- int arg_count;
- char * arg_pos;
- unsigned int arg_item_len;
-
- /*
- * Calculate the size of the argument list.
- */
- va_start(argv_ptr);
- arg_len = 0;
- arg_count = 0;
- for (;;) {
- arg_ptr = va_arg(argv_ptr, char *);
- if (arg_ptr == (char *)0)
- break;
- arg_count++;
- arg_len += strlen(arg_ptr) + 1; /* space for '\0' */
- }
- va_end(argv_ptr);
- /*
- * Add space for:
- * arg_count
- * pointers to arguments
- * trailing 0 pointer
- * dummy 0 pointer to environment variables
- * and align to integer boundary
- */
- arg_len += sizeof(integer_t) + (2 + arg_count) * sizeof(char *);
- arg_len = (arg_len + (sizeof(integer_t) - 1)) & ~(sizeof(integer_t)-1);
-
-
- /* This small piece is from .../mk/bootstrap/i386/exec.c. */
- {
- vm_offset_t stack_start;
- vm_offset_t stack_end;
- struct i386_thread_state regs;
- unsigned int reg_size;
-
-#define STACK_SIZE (1024 * 1024 * 16)
-
- /*
- * Add space for 5 ints to arguments, for
- * PS program. XXX
- */
- arg_len += 5 * sizeof(int);
-
- /*
- * Allocate stack.
- */
- stack_end = VM_MAX_ADDRESS;
- stack_start = VM_MAX_ADDRESS - STACK_SIZE;
- (void)vm_allocate(user_task,
- &stack_start,
- (vm_size_t)(stack_end - stack_start),
- FALSE);
-
- reg_size = i386_THREAD_STATE_COUNT;
- (void)thread_get_state(user_thread,
- i386_THREAD_STATE,
- (thread_state_t)&regs,
- &reg_size);
-
- regs.eip = (int) startpc;
- regs.uesp = (int)((stack_end - arg_len) & ~(sizeof(int)-1));
-
- (void)thread_set_state(user_thread,
- i386_THREAD_STATE,
- (thread_state_t)&regs,
- reg_size);
-
- arg_pos = (void *) regs.uesp;
- }
-
- /*
- * Copy out the arguments.
- */
- {
- vm_offset_t u_arg_start;
- /* user start of argument list block */
- vm_offset_t k_arg_start;
- /* kernel start of argument list block */
- vm_offset_t u_arg_page_start;
- /* user start of args, page-aligned */
- vm_size_t arg_page_size;
- /* page_aligned size of args */
- vm_offset_t k_arg_page_start;
- /* kernel start of args, page-aligned */
-
- register
- char ** k_ap; /* kernel arglist address */
- char * u_cp; /* user argument string address */
- register
- char * k_cp; /* kernel argument string address */
- register
- int i;
-
- /*
- * Get address of argument list in user space
- */
- u_arg_start = (vm_offset_t)arg_pos;
-
- /*
- * Round to page boundaries, and allocate kernel copy
- */
- u_arg_page_start = trunc_page(u_arg_start);
- arg_page_size = (vm_size_t)(round_page(u_arg_start + arg_len)
- - u_arg_page_start);
-
- vm_allocate(mach_task_self(),
- &k_arg_page_start,
- (vm_size_t)arg_page_size,
- TRUE);
-
- /*
- * Set up addresses corresponding to user pointers
- * in the kernel block
- */
- k_arg_start = k_arg_page_start + (u_arg_start - u_arg_page_start);
-
- k_ap = (char **)k_arg_start;
-
- /*
- * Start the strings after the arg-count and pointers
- */
- u_cp = (char *)u_arg_start + arg_count * sizeof(char *)
- + 2 * sizeof(char *)
- + sizeof(integer_t);
- k_cp = (char *)k_arg_start + arg_count * sizeof(char *)
- + 2 * sizeof(char *)
- + sizeof(integer_t);
-
- /*
- * first the argument count
- */
- *k_ap++ = (char *)(natural_t)arg_count;
-
- /*
- * Then the strings and string pointers for each argument
- */
- va_start(argv_ptr);
- for (i = 0; i < arg_count; i++) {
- arg_ptr = va_arg(argv_ptr, char *);
- arg_item_len = strlen(arg_ptr) + 1; /* include trailing 0 */
-
- /* set string pointer */
- *k_ap++ = u_cp;
-
- /* copy string */
- bcopy(arg_ptr, k_cp, arg_item_len);
- k_cp += arg_item_len;
- u_cp += arg_item_len;
- }
- va_end(argv_ptr);
-
- /*
- * last, the trailing 0 argument and a null environment pointer.
- */
- *k_ap++ = (char *)0;
- *k_ap = (char *)0;
-
- /*
- * Now write all of this to user space.
- */
- (void) vm_write(user_task,
- u_arg_page_start,
- k_arg_page_start,
- arg_page_size);
-
- (void) vm_deallocate(mach_task_self(),
- k_arg_page_start,
- arg_page_size);
- }
-}
-
-
void
msg_thread()
{
@@ -793,7 +779,7 @@ struct qr
struct qr *qrhead, *qrtail;
/* Queue a read for later reply. */
-void
+kern_return_t
queue_read (enum read_type type,
mach_port_t reply_port,
mach_msg_type_name_t reply_type,
@@ -801,9 +787,12 @@ queue_read (enum read_type type,
{
struct qr *qr;
+ qr = malloc (sizeof (struct qr));
+ if (!qr)
+ return D_NO_MEMORY;
+
spin_lock (&queuelock);
- qr = malloc (sizeof (struct qr));
qr->type = type;
qr->reply_port = reply_port;
qr->reply_type = reply_type;
@@ -815,6 +804,7 @@ queue_read (enum read_type type,
qrhead = qrtail = qr;
spin_unlock (&queuelock);
+ return D_SUCCESS;
}
/* TRUE if there's data available on stdin, which should be used to satisfy
@@ -837,7 +827,7 @@ read_reply ()
if (! spin_try_lock (&readlock))
return;
- /* Since we're commited to servicing the read, no one else need do so. */
+ /* Since we're committed to servicing the read, no one else need do so. */
should_read = 0;
ioctl (0, FIONREAD, &avail);
@@ -864,7 +854,7 @@ read_reply ()
spin_unlock (&queuelock);
if (qr->type == DEV_READ)
- vm_allocate (mach_task_self (), (vm_address_t *)&buf, qr->amount, 1);
+ buf = mmap (0, qr->amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
else
buf = alloca (qr->amount);
amtread = read (0, buf, qr->amount);
@@ -1000,6 +990,8 @@ ds_device_open (mach_port_t master_port,
mach_port_t *device,
mach_msg_type_name_t *devicetype)
{
+ struct dev_map *map;
+
if (master_port != pseudo_master_device_port)
return D_INVALID_OPERATION;
@@ -1015,6 +1007,20 @@ ds_device_open (mach_port_t master_port,
*devicetype = MACH_MSG_TYPE_MAKE_SEND;
return 0;
}
+ else if (strcmp (name, "pseudo-root") == 0)
+ /* Magic root device. */
+ {
+ *device = pseudo_root;
+ *devicetype = MACH_MSG_TYPE_MAKE_SEND;
+ return 0;
+ }
+
+ map = lookup_dev (name);
+ if (map)
+ {
+ *devicetype = MACH_MSG_TYPE_MOVE_SEND;
+ return device_open (map->port, mode, "", device);
+ }
*devicetype = MACH_MSG_TYPE_MOVE_SEND;
return device_open (master_device_port, mode, name, device);
@@ -1023,7 +1029,7 @@ ds_device_open (mach_port_t master_port,
kern_return_t
ds_device_close (device_t device)
{
- if (device != pseudo_console)
+ if (device != pseudo_console && device != pseudo_root)
return D_NO_SUCH_DEVICE;
return 0;
}
@@ -1035,24 +1041,34 @@ ds_device_write (device_t device,
dev_mode_t mode,
recnum_t recnum,
io_buf_ptr_t data,
- unsigned int datalen,
+ size_t datalen,
int *bytes_written)
{
- if (device != pseudo_console)
- return D_NO_SUCH_DEVICE;
-
-#if 0
- if (console_send_rights)
+ if (device == pseudo_console)
{
- mach_port_mod_refs (mach_task_self (), pseudo_console,
- MACH_PORT_TYPE_SEND, -console_send_rights);
- console_send_rights = 0;
- }
+#if 0
+ if (console_send_rights)
+ {
+ mach_port_mod_refs (mach_task_self (), pseudo_console,
+ MACH_PORT_TYPE_SEND, -console_send_rights);
+ console_send_rights = 0;
+ }
#endif
- *bytes_written = write (1, data, datalen);
+ *bytes_written = write (1, data, datalen);
- return (*bytes_written == -1 ? D_IO_ERROR : D_SUCCESS);
+ return (*bytes_written == -1 ? D_IO_ERROR : D_SUCCESS);
+ }
+ else if (device == pseudo_root)
+ {
+ size_t wrote;
+ if (store_write (root_store, recnum, data, datalen, &wrote) != 0)
+ return D_IO_ERROR;
+ *bytes_written = wrote;
+ return D_SUCCESS;
+ }
+ else
+ return D_NO_SUCH_DEVICE;
}
kern_return_t
@@ -1062,24 +1078,34 @@ ds_device_write_inband (device_t device,
dev_mode_t mode,
recnum_t recnum,
io_buf_ptr_inband_t data,
- unsigned int datalen,
+ size_t datalen,
int *bytes_written)
{
- if (device != pseudo_console)
- return D_NO_SUCH_DEVICE;
-
-#if 0
- if (console_send_rights)
+ if (device == pseudo_console)
{
- mach_port_mod_refs (mach_task_self (), pseudo_console,
- MACH_PORT_TYPE_SEND, -console_send_rights);
- console_send_rights = 0;
- }
+#if 0
+ if (console_send_rights)
+ {
+ mach_port_mod_refs (mach_task_self (), pseudo_console,
+ MACH_PORT_TYPE_SEND, -console_send_rights);
+ console_send_rights = 0;
+ }
#endif
- *bytes_written = write (1, data, datalen);
+ *bytes_written = write (1, data, datalen);
- return (*bytes_written == -1 ? D_IO_ERROR : D_SUCCESS);
+ return (*bytes_written == -1 ? D_IO_ERROR : D_SUCCESS);
+ }
+ else if (device == pseudo_root)
+ {
+ size_t wrote;
+ if (store_write (root_store, recnum, data, datalen, &wrote) != 0)
+ return D_IO_ERROR;
+ *bytes_written = wrote;
+ return D_SUCCESS;
+ }
+ else
+ return D_NO_SUCH_DEVICE;
}
kern_return_t
@@ -1090,37 +1116,51 @@ ds_device_read (device_t device,
recnum_t recnum,
int bytes_wanted,
io_buf_ptr_t *data,
- unsigned int *datalen)
+ size_t *datalen)
{
- int avail;
-
- if (device != pseudo_console)
- return D_NO_SUCH_DEVICE;
+ if (device == pseudo_console)
+ {
+ int avail;
#if 0
- if (console_send_rights)
- {
- mach_port_mod_refs (mach_task_self (), pseudo_console,
- MACH_PORT_TYPE_SEND, -console_send_rights);
- console_send_rights = 0;
- }
+ if (console_send_rights)
+ {
+ mach_port_mod_refs (mach_task_self (), pseudo_console,
+ MACH_PORT_TYPE_SEND, -console_send_rights);
+ console_send_rights = 0;
+ }
#endif
- spin_lock (&readlock);
- ioctl (0, FIONREAD, &avail);
- if (avail)
- {
- vm_allocate (mach_task_self (), (pointer_t *)data, bytes_wanted, 1);
- *datalen = read (0, *data, bytes_wanted);
- unlock_readlock ();
- return (*datalen == -1 ? D_IO_ERROR : D_SUCCESS);
+ spin_lock (&readlock);
+ ioctl (0, FIONREAD, &avail);
+ if (avail)
+ {
+ *data = mmap (0, bytes_wanted, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ *datalen = read (0, *data, bytes_wanted);
+ unlock_readlock ();
+ return (*datalen == -1 ? D_IO_ERROR : D_SUCCESS);
+ }
+ else
+ {
+ kern_return_t err;
+
+ unlock_readlock ();
+ err = queue_read (DEV_READ, reply_port, reply_type, bytes_wanted);
+ if (err)
+ return err;
+ return MIG_NO_REPLY;
+ }
}
- else
+ else if (device == pseudo_root)
{
- unlock_readlock ();
- queue_read (DEV_READ, reply_port, reply_type, bytes_wanted);
- return MIG_NO_REPLY;
+ *datalen = 0;
+ return
+ (store_read (root_store, recnum, bytes_wanted, (void **)data, datalen) == 0
+ ? D_SUCCESS
+ : D_IO_ERROR);
}
+ else
+ return D_NO_SUCH_DEVICE;
}
kern_return_t
@@ -1131,43 +1171,70 @@ ds_device_read_inband (device_t device,
recnum_t recnum,
int bytes_wanted,
io_buf_ptr_inband_t data,
- unsigned int *datalen)
+ size_t *datalen)
{
- int avail;
-
- if (device != pseudo_console)
- return D_NO_SUCH_DEVICE;
+ if (device == pseudo_console)
+ {
+ int avail;
#if 0
- if (console_send_rights)
- {
- mach_port_mod_refs (mach_task_self (), pseudo_console,
- MACH_PORT_TYPE_SEND, -console_send_rights);
- console_send_rights = 0;
- }
+ if (console_send_rights)
+ {
+ mach_port_mod_refs (mach_task_self (), pseudo_console,
+ MACH_PORT_TYPE_SEND, -console_send_rights);
+ console_send_rights = 0;
+ }
#endif
- spin_lock (&readlock);
- ioctl (0, FIONREAD, &avail);
- if (avail)
- {
- *datalen = read (0, data, bytes_wanted);
- unlock_readlock ();
- return (*datalen == -1 ? D_IO_ERROR : D_SUCCESS);
+ spin_lock (&readlock);
+ ioctl (0, FIONREAD, &avail);
+ if (avail)
+ {
+ *datalen = read (0, data, bytes_wanted);
+ unlock_readlock ();
+ return (*datalen == -1 ? D_IO_ERROR : D_SUCCESS);
+ }
+ else
+ {
+ kern_return_t err;
+
+ unlock_readlock ();
+ err = queue_read (DEV_READI, reply_port, reply_type, bytes_wanted);
+ if (err)
+ return err;
+ return MIG_NO_REPLY;
+ }
}
- else
+ else if (device == pseudo_root)
{
- unlock_readlock ();
- queue_read (DEV_READI, reply_port, reply_type, bytes_wanted);
- return MIG_NO_REPLY;
+ error_t err;
+ void *returned = data;
+
+ *datalen = bytes_wanted;
+ err =
+ store_read (root_store, recnum, bytes_wanted, (void **)&returned, datalen);
+
+ if (! err)
+ {
+ if (returned != data)
+ {
+ bcopy (returned, (void *)data, *datalen);
+ munmap ((caddr_t) returned, *datalen);
+ }
+ return D_SUCCESS;
+ }
+ else
+ return D_IO_ERROR;
}
+ else
+ return D_NO_SUCH_DEVICE;
}
kern_return_t
ds_xxx_device_set_status (device_t device,
dev_flavor_t flavor,
dev_status_t status,
- u_int statu_cnt)
+ size_t statu_cnt)
{
if (device != pseudo_console)
return D_NO_SUCH_DEVICE;
@@ -1178,9 +1245,9 @@ kern_return_t
ds_xxx_device_get_status (device_t device,
dev_flavor_t flavor,
dev_status_t status,
- u_int *statuscnt)
+ size_t *statuscnt)
{
- if (device != pseudo_console)
+ if (device != pseudo_console && device != pseudo_root)
return D_NO_SUCH_DEVICE;
return D_INVALID_OPERATION;
}
@@ -1190,9 +1257,9 @@ ds_xxx_device_set_filter (device_t device,
mach_port_t rec,
int pri,
filter_array_t filt,
- unsigned int len)
+ size_t len)
{
- if (device != pseudo_console)
+ if (device != pseudo_console && device != pseudo_root)
return D_NO_SUCH_DEVICE;
return D_INVALID_OPERATION;
}
@@ -1205,7 +1272,7 @@ ds_device_map (device_t device,
memory_object_t *pager,
int unmap)
{
- if (device != pseudo_console)
+ if (device != pseudo_console && device != pseudo_root)
return D_NO_SUCH_DEVICE;
return D_INVALID_OPERATION;
}
@@ -1214,9 +1281,9 @@ kern_return_t
ds_device_set_status (device_t device,
dev_flavor_t flavor,
dev_status_t status,
- unsigned int statuslen)
+ size_t statuslen)
{
- if (device != pseudo_console)
+ if (device != pseudo_console && device != pseudo_root)
return D_NO_SUCH_DEVICE;
return D_INVALID_OPERATION;
}
@@ -1225,11 +1292,25 @@ kern_return_t
ds_device_get_status (device_t device,
dev_flavor_t flavor,
dev_status_t status,
- unsigned int *statuslen)
+ size_t *statuslen)
{
- if (device != pseudo_console)
+ if (device == pseudo_console)
+ return D_INVALID_OPERATION;
+ else if (device == pseudo_root)
+ if (flavor == DEV_GET_SIZE)
+ if (*statuslen < DEV_GET_SIZE_COUNT)
+ return D_INVALID_SIZE;
+ else
+ {
+ status[DEV_GET_SIZE_DEVICE_SIZE] = root_store->size;
+ status[DEV_GET_SIZE_RECORD_SIZE] = root_store->block_size;
+ *statuslen = DEV_GET_SIZE_COUNT;
+ return D_SUCCESS;
+ }
+ else
+ return D_INVALID_OPERATION;
+ else
return D_NO_SUCH_DEVICE;
- return D_INVALID_OPERATION;
}
kern_return_t
@@ -1237,9 +1318,9 @@ ds_device_set_filter (device_t device,
mach_port_t receive_port,
int priority,
filter_array_t filter,
- unsigned int filterlen)
+ size_t filterlen)
{
- if (device != pseudo_console)
+ if (device != pseudo_console && device != pseudo_root)
return D_NO_SUCH_DEVICE;
return D_INVALID_OPERATION;
}
@@ -1383,15 +1464,18 @@ S_io_read (mach_port_t object,
if (avail)
{
if (amount > *datalen)
- vm_allocate (mach_task_self (), (vm_address_t *) data, amount, 1);
+ *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
*datalen = read (0, *data, amount);
unlock_readlock ();
return *datalen == -1 ? errno : 0;
}
else
{
+ kern_return_t err;
unlock_readlock ();
- queue_read (IO_READ, reply_port, reply_type, amount);
+ err = queue_read (IO_READ, reply_port, reply_type, amount);
+ if (err)
+ return err;
return MIG_NO_REPLY;
}
}
@@ -1554,11 +1638,16 @@ S_io_reauthenticate (mach_port_t object,
{
uid_t *gu, *au;
gid_t *gg, *ag;
- unsigned int gulen = 0, aulen = 0, gglen = 0, aglen = 0;
+ size_t gulen = 0, aulen = 0, gglen = 0, aglen = 0;
+ error_t err;
+
+ err = mach_port_insert_right (mach_task_self (), object, object,
+ MACH_MSG_TYPE_MAKE_SEND);
+ assert_perror (err);
if (! auth_server_authenticate (authserver,
rend, MACH_MSG_TYPE_COPY_SEND,
- object, MACH_MSG_TYPE_MAKE_SEND,
+ object, MACH_MSG_TYPE_COPY_SEND,
&gu, &gulen,
&au, &aulen,
&gg, &gglen,
@@ -1570,6 +1659,7 @@ S_io_reauthenticate (mach_port_t object,
mig_deallocate ((vm_address_t) au, aulen * sizeof *gu);
}
mach_port_deallocate (mach_task_self (), rend);
+ mach_port_deallocate (mach_task_self (), object);
return 0;
}
@@ -1581,9 +1671,9 @@ S_io_restrict_auth (mach_port_t object,
mach_port_t *newobject,
mach_msg_type_name_t *newobjtype,
uid_t *uids,
- u_int nuids,
+ size_t nuids,
uid_t *gids,
- u_int ngids)
+ size_t ngids)
{
if (object != pseudo_console)
return EOPNOTSUPP;
@@ -1730,7 +1820,14 @@ S_io_identity (mach_port_t obj,
mach_msg_type_name_t *idtype,
mach_port_t *fsid,
mach_msg_type_name_t *fsidtype,
- int *fileno)
+ ino_t *fileno)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_revoke (mach_port_t obj,
+ mach_port_t reply, mach_msg_type_name_t replyPoly)
{
return EOPNOTSUPP;
}
@@ -1791,6 +1888,13 @@ kern_return_t S_term_get_nodename
)
{ return EOPNOTSUPP; }
+kern_return_t S_term_get_peername
+(
+ io_t terminal,
+ string_t name
+)
+{ return EOPNOTSUPP; }
+
kern_return_t S_term_set_filenode
(
io_t terminal,