diff options
Diffstat (limited to 'boot/boot.c')
-rw-r--r-- | boot/boot.c | 852 |
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 (), ®ion, 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) ®s, ®_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) ®s, 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) ®s, ®_size); + regs.eip = (int) startpc; + regs.uesp = (int) arg_pos; + thread_set_state (thread, i386_THREAD_STATE, + (thread_state_t) ®s, 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) ®s, ®_size); + regs.r30 = (natural_t) arg_pos; + regs.pc = (natural_t) startpc; + thread_set_state (thread, ALPHA_THREAD_STATE, + (thread_state_t) ®s, 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)®s, - ®_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)®s, - 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, |