diff options
author | Justus Winter <justus@gnupg.org> | 2017-09-13 14:10:33 +0200 |
---|---|---|
committer | Justus Winter <justus@gnupg.org> | 2017-09-13 14:10:33 +0200 |
commit | 1c5e9b5fd65d2c385f5d3f696eb0d05a86fb2755 (patch) | |
tree | 82a7293c31238d516d12fa25fcddb2e8339598c0 /boot | |
parent | 5018bd32c87250ed3fd4249d050b772750827db0 (diff) | |
parent | 89a49ec8b3a847f3b770cff6a4a80b98b94ad7bf (diff) |
Merge remote-tracking branch 'mainline/master' into dde
Diffstat (limited to 'boot')
-rw-r--r-- | boot/Makefile | 35 | ||||
-rw-r--r-- | boot/boot.c | 976 | ||||
-rw-r--r-- | boot/frank1.ld | 94 | ||||
-rw-r--r-- | boot/frankemul.ld | 107 | ||||
-rw-r--r-- | boot/mach-crt0.c | 158 | ||||
-rw-r--r-- | boot/mig-decls.h | 27 | ||||
-rw-r--r-- | boot/mig-mutate.h | 25 | ||||
-rw-r--r-- | boot/private.h | 25 | ||||
-rw-r--r-- | boot/sigvec.S | 23 | ||||
-rw-r--r-- | boot/syscall.S | 35 | ||||
-rw-r--r-- | boot/userland-boot.c | 261 | ||||
-rw-r--r-- | boot/ux.c | 303 | ||||
-rw-r--r-- | boot/ux.h | 114 |
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) ®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); +#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) ®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; +} 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; |