aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/ChangeLog722
-rw-r--r--boot/Makefile54
-rw-r--r--boot/boot.c1964
-rw-r--r--boot/boot_script.c822
-rw-r--r--boot/boot_script.h90
-rw-r--r--boot/frank1.ld94
-rw-r--r--boot/frankemul.ld107
-rw-r--r--boot/mach-crt0.c158
-rw-r--r--boot/sigvec.S23
-rw-r--r--boot/syscall.S35
-rw-r--r--boot/tcattr.c592
-rw-r--r--boot/ux.c303
-rw-r--r--boot/ux.h114
13 files changed, 5078 insertions, 0 deletions
diff --git a/boot/ChangeLog b/boot/ChangeLog
new file mode 100644
index 00000000..ddafdd82
--- /dev/null
+++ b/boot/ChangeLog
@@ -0,0 +1,722 @@
+1999-09-13 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot.c: Reverted changes related to io_map_segment.
+
+1999-09-07 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * boot.c (S_io_map_segment): New function.
+
+1999-07-11 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot.c (ds_device_read, S_io_read): Fix sloppy bugs in last change.
+
+1999-07-06 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * boot.c (load_image): Use mmap instead of vm_allocate, when
+ allocating in mach_task_self ().
+ (boot_script_exec_cmd): Likewise.
+ (set_mach_stack_args): Likewise.
+ (read_reply): Likewise.
+ (S_io_read): Likewise.
+
+1999-07-10 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot.c: Add #include <sys/mman.h> for munmap decl.
+
+Mon Jul 5 20:04:06 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * boot.c (load_image): Fix typo in cast. Reported by Yamashita
+ TAKAO <jargon@lares.dti.ne.jp>.
+
+1999-07-03 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * boot.c (load_image): Use munmap instead of vm_deallocate when
+ it's from our own task.
+ (boot_script_read_file): Likewise.
+ (boot_script_exec_cmd): Likewise.
+ (set_mach_stack_args): Likewise.
+ (ds_device_read_inband): Likewise.
+
+1999-03-20 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot.c (S_term_get_peername): New function.
+
+1999-03-14 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot.c: Fix typo in last change.
+
+1999-03-10 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot.c (main): Only use real device name if root_store is for an
+ enforced single run starting at the beginning of the device.
+
+1999-03-09 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot.c (main): Add newline to error msg.
+ Patch by Marcus Brinkmann <Marcus.Brinkmann@ruhr-uni-bochum.de>.
+
+1999-02-16 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot.c (S_io_revoke): Add reply, replyPoly args.
+
+Tue Feb 16 05:06:12 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * boot.c (S_io_revoke): New (unsupported) routine.
+
+1998-12-26 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot.c (isig): New variable.
+ (init_termstate): If it's set, set ISIG flag in c_lflag.
+ (options): New option -I/--isig.
+ (parse_opt): Make -I set `isig'.
+ (boot_script_exec_cmd): Print out args as well as file name.
+
+1998-09-04 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot_script.c: Include <string.h> instead of declaring memset here.
+ Include <stdlib.h> instead of declaring malloc, free here.
+
+1997-07-08 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * boot_script.c (prompt_resume_task): Pass more than a single
+ character buffer to safe_gets.
+
+Mon Jul 7 16:25:49 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * boot.c: Include <fcntl.h> instead of <fcntlbits.h>. Suggested
+ by Marcus G. Daniels (marcus@cathcart.sysc.pdx.edu).
+
+1997-06-20 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * boot.c (bootscript): Made global.
+ (parse_opt): New function.
+ (options, doc, args_doc): New variables.
+ (bootscript_args): Now an array.
+ (ds_device_open, ds_device_close, ds_device_write,
+ ds_device_write_inband, ds_device_read, ds_device_read_inband,
+ ds_device_get_status, ds_device_set_status, ds_device_map,
+ ds_xxx_device_set_filter, ds_xxx_device_get_status,
+ ds_xxx_device_set_status, ds_device_set_filter):
+ Handle "pseudo-root" device.
+ (pseudo_root, root_store): New variables.
+ (main): Use argp to parse args, and implement the pseudo-root device.
+ Include <argp.h> & <hurd/store.h>
+ * Makefile (HURDLIBS): Include libstore & libshouldbeinlibc.
+
+Thu Apr 10 11:53:57 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * boot.c: Don't include varargs.h.
+ (set_mach_stack_args): Use stdarg instead of vararg.
+
+Mon Mar 17 13:12:45 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * boot_script.c (boot_script_parse_line): Don't print gratuitous
+ output noise.
+
+Thu Sep 12 16:28:47 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * Makefile (HURDLIBS): New variable.
+ (boot): Delete special depedencies.
+
+Tue Aug 13 16:57:22 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * Makefile (device.defs): Rule removed.
+ (ourdevice.defs): Fix rule to work with Makeconf-generated device.defs.
+
+Tue Aug 13 15:09:45 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * Makefile (ourdevice.defs): Depend on local device.defs.
+ (device.defs): New rule.
+
+Mon Aug 12 11:11:08 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * Makefile (ourdevice.defs): Find device.defs under
+ install_includedir now.
+
+ * Makefile (all): No longer build uxboot by default.
+
+Thu Aug 1 14:38:38 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * boot_script.h (safe_gets): Declare second parm as type `int'.
+ * boot.c (safe_gets): Likewise.
+
+Sun Jul 7 21:10:08 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * boot.c (S_io_reauthenticate): Don't use unsafe MOVE_SEND in
+ auth_server_authenticate.
+
+Fri May 10 16:11:49 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * boot.c (S_io_identity): Typo.
+
+Fri May 10 09:18:53 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * boot.c (S_io_identity): New function.
+
+Thu May 9 18:57:34 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * boot.c (S_io_select): No longer has TAG parm.
+
+ * boot.c (S_io_reauthenticate): Use new interface.
+
+Sun Apr 28 22:50:38 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * boot.c (main): Use select instead of SIGIO.
+
+Mon Apr 15 12:57:29 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * Makefile (uxboot): Permit errors because people might not have
+ the a.out-mach3 target installed, and that's OK for many users.
+
+ * Makefile (uxboot.0): Find frank1.ld in #(srcdir).
+
+ * boot_script.h (safe_gets): Add decl.
+ * boot_script.c: Include <stdio.h>.
+
+Wed Apr 3 18:54:22 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * ux.c (printf): Add %d.
+
+Wed Mar 27 11:30:29 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * boot.c [notanymore] (S_tioctl_tiocgeta, S_tioctl_tiocseta,
+ S_tioctl_tiocsetaf, term_modes, term_ccs, term_speeds):
+ Functions & variables removed.
+ * Makefile (COMMON-OBJS): Remove tcattr.o.
+ (SRCS): Remove tcattr.c.
+
+Thu Mar 14 10:10:20 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu>
+
+ * Makefile (boot): Depend on libthreads.so, nothing wrong with shared
+ libs.
+ (uxboot.0, uxboot.1): Use automatic vars in cmds instead of gratuitous
+ redundancy.
+ (LDFLAGS-uxboot.0): Remove useless indirection through variable.
+
+Wed Feb 14 16:50:05 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * boot.c [!UX]
+ (orig_tty_state): New variable.
+ (init_termstate, restore_termstate): New hurd versions of these funcs.
+ * ux.c (init_termstate, restore_termstate, term_sgb, localbits):
+ Moved here from boot.c
+
+Tue Feb 13 18:49:26 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * boot.c (load_image, boot_script_read_file, main): Use O_RDONLY,
+ not 0 (kind of ironic, this...).
+ (load_image): Give the filename with the error message (and a newline).
+
+ * ux.h (O_RDONLY, O_WRONLY, O_RDWR): New macros.
+
+ * ux.c, ux.h: New files.
+ * boot.c: Move all the ux-specific grot into ux.c & ux.h.
+ If UX is defined, include "ux.h", else define hurdish stuff.
+ (main): Use get_privileged_ports instead of task_by_pid.
+ (load_image, boot_script_read_file, main, do_mach_notify_no_senders,
+ do_mach_notify_dead_name): Use host_exit instead of uxexit.
+ (boot_script_read_file): Use host_stat instead of uxstat.
+ (init_termstate, S_tioctl_tiocseta): Use sg_flags fld in struct sgttyb.
+
+ * Makefile (all): Depend on `boot' and `uxboot'.
+ (COMMON-OBJS, UX-OBJS): New macros.
+ (OBJS): Inherit most names from $(COMMON-OBJS).
+ (LCLHDRS): Add ux.h.
+ (LDFLAGS): Use target-specific value.
+ (uxboot.0-LDFLAGS): New macro (with contents from old LDFLAGS).
+ (uxboot.o, uxboot.0): New targets.
+ (uxboot): Target renamed from boot.a.
+
+Sun Dec 10 18:05:14 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * boot.c (read_reply): Don't call clear_should_read(), just do
+ things ourselves.
+ (should_read_lock): Variable deleted.
+ (service_sigio): Function deleted.
+ (main): Use read_reply to service SIGIO again, not service_sigio.
+
+ * boot.c (service_sigio): New function, replacing set_should_read.
+ Calls read_reply() itself too.
+ (unlock_readlock): New function.
+ (ds_device_read, ds_device_read_inband, S_io_read): Call
+ unlock_readlock instead of directly unlocking READLOCK.
+ (request_server, main): Don't call read_reply() anymore.
+
+ * boot.c (should_read): New variable.
+ (main): SIGIO uses set_should_read instead of read_reply.
+ Call read_reply() after sigpause() returns.
+ (read_reply): Call clear_should_read(), and don't do anything if
+ SHOULD_READ wasn't set.
+ (set_should_read): New function.
+ (clear_should_read): New function.
+ (request_server): Call read_reply() before returning.
+
+Sat Dec 9 19:01:10 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * boot.c (S_io_read, ds_device_read_inband, ds_device_read): Don't
+ block SIGIO.
+ (main): Don't trap SIGMSG & SIGEMSG.
+
+Mon Dec 4 23:54:18 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot.c (main): Request no-senders notification on
+ pseudo_master_device_port.
+ Deallocate our send right to it when we no longer need it.
+ (do_mach_notify_no_senders): Exit only when both pseudo_console and
+ pseudo_master_device_port have no senders.
+ (ds_device_read_inband): Unlock readlock properly.
+
+Thu Nov 30 15:58:47 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * boot.c (readlock): New variable.
+ (read_reply): Check FIONREAD before dequeueing QR so that we don't
+ abandon requests. Lock READLOCK around FIONREAD/read pair.
+ (ds_device_read): Lock READLOCK around FIONREAD/read pair.
+ (ds_device_read_inband): Likewise.
+ (S_io_read): Likewise.
+
+Nov 22 16:25:01 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot.c (request_server): Don't call exec_server.
+ (S_exec_*): Functions removed.
+ (boot_script_task_port): Variable removed.
+ (boot_script_task_*, boot_script_port_*): Functions removed.
+
+Tue Nov 14 12:07:24 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * Makefile (OBJS): Remove execServer.o.
+
+Thu Sep 28 14:47:46 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot_script.c (read_file): Pass CMD->path for file name.
+ (CHECK_CMDLINE_LEN): Update ARGV pointers after reallocating the line
+ buffer.
+
+Wed Sep 27 14:01:03 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot.c (struct uxstat): New type.
+ (uxfstat): Renamed from fstat; use struct uxstat * for arg.
+ (boot_script_read_file): Use those.
+ Return the memory object port, not zero.
+
+ * boot.c (fstat): New syscall function.
+
+ * boot_script.c (read_file): New function.
+ (builtin_symbols): Add $(read-file) builtin.
+ * boot_script.h (boot_script_read_file): Declare it.
+ * boot.c (close): New syscall function.
+ (defpager): New variable.
+ (main): Set it up.
+ (boot_script_read_file): New function.
+ (useropen_dir): New variable.
+ (useropen): New function.
+ (load_image): Call it instead of open.
+ (main): Grok -D arg to set useropen_dir.
+
+Sat Sep 23 00:53:51 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * syscall.S: Restore entry SP before return.
+
+ * boot.c (main): Use static const for constant strings.
+ On boot script error, write script line with error msg.
+
+ * boot_script.c (boot_script_parse_line): Ignore line beginning
+ with #.
+
+ * boot.c (S_io_pathconf): New function.
+
+ * Makefile (LDFLAGS): Add -static.
+
+Fri Sep 22 14:14:23 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * mach-crt0.c (__data_start): New variable.
+
+Tue Aug 29 10:41:29 1995 Michael I. Bushnell, p/BSG <mib@duality.gnu.ai.mit.edu>
+
+ * boot.c (mig_dealloc_reply_port): Remove __ from call to
+ mach_port_mod_refs.
+ (main): Look for -d in bootstrap_args, not (nonexistent)
+ boot_args. Remove `const' keyword from decl of MSG.
+
+ * boot.c (sigblock, sigsetmask): New functions.
+ (sigmask): New macro.
+ (ds_device_read): Block SIGIO around critical section.
+ (ds_device_read_inband): Likewise.
+ (S_io_read): Likewise.
+
+Mon Aug 28 17:16:48 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot_script.h, boot_script.c: Updated by Shantanu Goel, to
+ accept action keywords only inside $(...) and only variable values
+ inside ${...}.
+ * boot.c: Updated for changes in boot_script.h protocol by
+ Shantanu Goel.
+ (main): Use boot_script_set_variable instead of magic variables.
+ Under -d, pause between parsing bootscript and executing it.
+
+Wed Aug 23 16:08:04 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ New script-driven boot mechanism, mostly implemented by Shantanu Goel.
+ * Makefile (SRCS): Add boot_script.c.
+ (OBJS): Add boot_script.o.
+ (LCLHDRS): New variable.
+ (HURDLIBS): Variable removed.
+ (boot): Depend on ../libthreads/libthreads.a.
+ * boot_script.c, boot_script.h: New files.
+ * boot.c (boot_like_kernel, boot_like_cmudef, boot_like_hurd):
+ Variables removed.
+ (main): Don't interpret switches. Instead of servers, take
+ command line argument of boot script file name. Read the file and
+ use boot_script functions to parse and execute its directives.
+ (boot_script_*): New variables and functions for boot_script callbacks.
+
+Sun Jul 30 23:50:53 1995 Michael I. Bushnell, p/BSG <mib@geech.gnu.ai.mit.edu>
+
+ * Makefile: DISTFILES -> DIST_FILES.
+
+Sat Jul 8 11:37:32 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * boot.c (free_reply_ports, free_reply_ports_lock): New variables.
+ (__mig_get_reply_port, __mig_put_reply_port, __mig_dealloc_reply_port,
+ mig_get_reply_port, mig_put_reply_port, mig_dealloc_reply_port):
+ Provide better versions of these routines that won't leak reply ports.
+
+Fri Jul 7 15:55:18 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * mach-crt0.c: New file, from mach4-i386/libmach/standalone.
+ * boot.c (mach_init_routine): New variable, wanted by mach-crt0.o.
+ (__mig_get_reply_port, __mig_dealloc_reply_port, __mig_put_reply_port):
+ New functions, to avoid using hurdish versions.
+ * Makefile (OBJS): Add mach-crt0.o.
+ (SRCS): Add mach-crt0.c.
+ (LDFLAGS): Add -nostartfiles (as we now use mach-crt0.o).
+
+Thu Jul 6 15:30:18 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * Makefile (boot.1, boot.a): Use $(LD) and $(OBJCOPY) instead of
+ explicit names.
+
+ * boot.c: Include <mach/mig_support.h>.
+ (S_io_reauthenticate): Cast first arg to mig_deallocate.
+ (load_image): Cast second arg to read.
+ * tcattr.c: Undo last change; add private decl of ioctl.
+
+ * boot.c (bootdevice): Initialize to hard-coded `sd0a' instead of
+ DEFAULT_BOOTDEVICE.
+
+ * Makefile (all): Depend on boot.a too.
+
+ * Makefile: Removed dependencies that are now automatically
+ generated.
+
+Wed May 31 10:02:11 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * Makefile (DISTFILES): New variable; include frank1.ld and
+ frankemul.ld.
+ (CPPFLAGS): Variable removed.
+ (LDFLAGS): Append -T frank1.ld.
+ (boot.1, boot.a): New targets.
+
+ * syscall.S: Omit .globl decl for errno; it caused some as
+ complaint.
+
+Mon May 22 11:48:58 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * sigvec.S: Remove copyright notice.
+
+Wed May 17 13:10:27 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * boot.c (load_image): Make sure we actually allocate enough
+ memory to read into, including the offset into the buffer at which
+ the segment is read.
+
+ * sigvec.S (sigreturn, _sigreturn, sigvec): Remove the explicit
+ underscore prefixes from these names, now that we're using elf.
+ Instead we use the various macros from <i386/asm.h>. Also, return
+ errors correctly. [Also added a copyright notice]
+
+Sat May 13 03:37:24 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot.c (load_image): Fixed alignment calculation in ELF segment
+ loading.
+
+ * syscall.S: Include i386/asm.h and use ENTRY and EXT macros,
+ instead of explicit _s.
+
+Fri May 12 18:36:39 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot.c (load_image): Grok ELF executables as well as a.out.
+ (main): Load multiple servers. Suspend all but the first.
+ The first gets an extra arg, its name for the task port of the
+ second.
+
+Wed Apr 12 09:18:50 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * Makefile: Don't try and install boot in /usr/local/bin.
+
+Wed Apr 5 17:25:19 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot.c: Don't include <errno.h>. Define `errno' variable.
+ * Makefile (SRCS): Add syscall.S.
+ (OBJS): Add syscall.o.
+ * syscall.S: Check for errors.
+
+Thu Jan 19 01:21:24 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot.c (S_io_select): Updated to new io_select protocol.
+
+Fri Dec 9 01:23:22 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot.c: Use mach_msg_type_number_t in place of unsigned int and
+ int.
+
+Fri Nov 11 14:05:43 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * boot.c (main): Always set `f' flag (signifying "fake" because we
+ aren't a real native bootstrap).
+
+Thu Nov 3 17:26:37 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * Makefile (boot.o): Depend on bootstrap_S.h.
+
+Fri Oct 28 17:08:12 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot.c (main): Create the thread before setting it up.
+ (bootstrap_compat): Make a send right for psuedo_master_device_port.
+ (main): Explicitly clear NEWTASK's bootstrap port for boot_like_kernel.
+ (main): Format strings for port names for boot_like_kernel.
+
+Fri Oct 28 15:26:48 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * boot.c (boot_like_kernel, boot_like_cmudef, boot_like_hurd): New
+ global vars.
+ (set_mach_stack_args): New function.
+ (main): If the -k flag is given, set BOOT_LIKE_KERNEL.
+ If the -p flag is given, set BOOT_LIKE_CMUDEF. If neither is
+ given, set BOOT_LIKE_HURD.
+ Only set a bootstrap port if BOOT_LIKE_CMUDEF or BOOT_LIKE_HURD.
+ If BOOT_LIKE_KERNEL or BOOT_LIKE_CMUDEF, set up the stack the
+ Mach way using set_mach_stack_args.
+ (request_server): Declare and call bootstrap_server.
+ (do_bootstrap_priveleged_ports, bootstrap_compat): New functions.
+ * Makefile (OBJS): Require bootstrapServer.o.
+ * bootstrap.defs: New file.
+
+Tue Aug 30 11:41:33 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * boot.c (S_io_reauthenticate): Use new authentication protocol.
+
+Mon Aug 22 13:43:32 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * boot.c: Include <cthreads.h>.
+ (main): Run msg_thread fork; don't call
+ mach_msg_server_timeout here. Use sigpause instead of getpid.
+ (msg_thread): New function.
+ (queuelock): New variable.
+ (queue_read): Acquire queuelock.
+ (read_reply): Acquire queuelock.
+ * Makefile (HURDLIBS): New var to get threads.
+
+Thu Aug 18 18:04:36 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * boot.c (restore_termstate): New function.
+ (do_mach_notify_no_senders): Call restore_termstate before exiting.
+
+ * boot.c (main): New var `usagemsg'; print it if args are wrong.
+ Allow flags and disk device to be given on command line.
+ New var `bootfile'.
+ (bootdevice, bootstrap_args): New vars.
+ (load_image): Exit nicely if the startup file can't be found.
+ (S_exec_startup): Use `bootdevice' instead of hardcoded name.
+ Use `bootstrap_args' instead of hardcoded "-x".
+ (main): Only do `pausing' hack if -d was provided.
+
+ * Makefile (CPPFLAGS): Define DEFAULT_BOOTDEVICE.
+
+ * Makefile (/usr/local/bin/boot): Depend on boot.
+
+ * boot.c (S_termctty_open_terminal): New "function".
+ (S_io_select): Added `rettype' arg.
+
+Sat Jul 23 02:58:05 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * Makefile (io-MIGSFLAGS): Renamed from ioMIGSFLAGS.
+
+Fri Jul 22 15:10:45 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * boot.c (request_server): Remove S_ from io_server and
+ term_server.
+
+Thu Jul 21 19:00:36 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * Makefile: Rewritten to use new scheme.
+ * boot.c: Include io_reply_U.h and device_reply_U.h instead
+ of io_repl.h and device_reply.h.
+
+Wed Jul 20 13:19:45 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * boot.c: Comment out bits relating to tioctl interface.
+ * Makefile: Likewise.
+
+Tue Jul 19 12:41:46 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * Makefile (boot): Don't use variable $(link) anymore.
+
+Tue Jul 5 14:19:36 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * Makefile (SRCS): New variable.
+
+Sun Jul 3 17:20:07 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * tcattr.c: New file.
+ * boot.c (S_tioctl_tiocgeta): Call tcgetattr.
+ (S_tioctl_tiocseta): Call tcsetattr.
+ * Makefile (OBJS): Add tcattr.o.
+ (DIST_FILES): Add tcattr.c.
+
+Fri Jul 1 11:16:27 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * boot.c (init_termstate): Enter raw mode here.
+
+Fri Jun 24 14:27:56 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * boot.c (S_term_open_ctty): Renamed from term_become_ctty.
+ Deleted SIGPT arg. Add msg type arg for NEWTTY.
+
+Fri Jun 17 13:46:07 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * boot.c (request_server): Remove S_ prefix from exec_server
+ and notify_server.
+
+Fri Jun 17 00:12:16 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu)
+
+ * Makefile (boot.o): Depend on term_S.h.
+
+Tue Jun 14 01:28:10 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu)
+
+ * boot.c (request_server): Add S_ prefix to demuxer functions.
+
+Wed Jun 8 18:02:19 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu)
+
+ * boot.c (S_tioctl_tiocseta): Turn off ECHO.
+ (S_io_select): Implement.
+
+Tue Jun 7 04:33:42 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu)
+
+ * Makefile (tioctlServer.o): Depend on ../hurd/ioctl_types.h.
+
+Mon Jun 6 20:33:39 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu)
+
+ * boot.c (authserver): New variable.
+ (S_io_reauthenticate): Do auth_server_authenticate and throw away
+ the returned info.
+ (S_exec_init): Set authserver to the passed port.
+
+Sat Jun 4 02:32:03 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu)
+
+ * boot.c: Include term_S.h and tioctl_S.h.
+ (S_term_getctty): New function.
+ (S_term_*): Stub functions.
+ (request_server): Use S_term_server.
+
+ * Makefile (termServer.c term_S.h): New rule.
+ (OBJS): Add termServer.o.
+
+ * boot.c (S_exec_setexecdata, S_exec_exec): Fix prototypes.
+
+Tue May 17 18:44:29 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * boot.c (ds_device_write): DATA arg is char *; don't dereference
+ it in call to write.
+
+Mon May 16 14:34:15 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * boot.c (fsname): New variable.
+ (main): Set fsname to argv[1].
+ (S_exec_startup): Include fsname in child's argv[0].
+
+ * boot.c (init_termstate): Add forward declaration.
+ (struct sigvec): Make SV_HANDLER member void (*)().
+ (sigvec): Add declaration to avoid warning.
+
+Tue May 10 18:14:39 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * boot.c (tioctl_tiocseta, tioctl_tiocsetw, tioctl_tiocsetf,
+ tioctl_tiocgeta, init_termstate): New functions.
+ (term_modes, term_ccs, term_speeds, term_sgb, localbits): Nev
+ vars.
+ Also added new bits from ioctl.h.
+ (main): Call init_termstate.
+ (request_server): Call tioctl_server.
+ * Makefile (tioctlServer.c tioctl_S.h): New targets.
+ (OBJS): Include tioctlServer.o.
+ (boot.o): Depend on tioctl_S.h
+
+Fri May 6 13:56:58 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * boot.c (main): Restore braindamage of yesterday relating to
+ signals; that is, restore declaration of VEC and calls to sigvec.
+ * Makefile (DIST_FILES): Add sigvec.S.
+
+Thu May 5 13:16:42 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * Makefile (device_replyUser.c): Mention that this build
+ device_reply.h as well.
+ (boot.o): Add dependency on device_reply.h and io_repl.h.
+
+ * boot.c: Include <stdlib.h> for malloc and free prototypes.
+ Include <string.h> for bcopy and bzero prototypes.
+ Include <stdio.h> for sprintf prototype.
+ Include "device_reply.h" for its prototypes.
+ Include "io_reply.h" for its prototypes.
+ Declare return type for all the server functions that were lacking
+ such.
+ (sigpause): Declare type of MASK.
+ (ioctl): Declare third arg to be generic pointer, not char *.
+ (request_server): Declare MiG functions we call.
+ (load_image): Delete unused variable STACKADDR.
+ (main): Comment out declaration of VEC.
+ Comment out calls to sigvec.
+ Cast STARTPC in call to __mach_setup_thread.
+ Delete unused variable TIMEOUT.
+ (read_reply): Cast BUF correctly in call to ds_device_read_reply.
+ (S_exec_startup): Delete unused variable DTABLE.
+ (ds_device_write): Double cast arg to write to avoid warning.
+ (S_io_read): Order args to vm_allocate properly; cast DATA arg.
+ Check *datalen properly for unsigned type.
+
+ * boot.c: Renamed _exit to uxexit to avoid library name clash.
+ (do_mach_notify_dead_name, do_mach_notify_no_senders):
+ Call uxexit instead of _exit.
+
+ * boot.c (S_io_async, S_io_get_icky_async_id, S_io_map_cntl):
+ Expect new type arg for returned port.
+ (S_io_prenotify, S_io_postnotify): START and END args are now
+ vm_offset_t.
+
+ * boot.c: Change error_t to kern_return_t because error_t
+ is now unsigned and conflicts with MiG's use of kern_return_t.
+
+ * Makefile (io_S.h, ioServer.c): Punt mungio hack; use
+ -DREPLY_PORTS.
+ * boot.c: Changed all io server stubs to expect reply ports.
+
+ * mungio: removed file.
+ * Makefile (DIST_FILES): Removed mungio.
+
+ * boot.c (load_image): Only read from the image file the actual
+ amount being read, not that amount rounded to the nearest page.
+ Otherwise, the first bit of the BSS will not be zero, but will be
+ whatever is in the front of the symbol section of the a.out.
+
+Thu May 5 07:43:06 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * Makefile: Change uses of $(headers) to $(includedir).
+
+Mon May 2 16:47:49 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * boot.c (S_io_readable): Implement io_readable fully.
+
+Fri Apr 1 17:55:38 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * Makefile (OBJS): Remove boot_machdep.o.
diff --git a/boot/Makefile b/boot/Makefile
new file mode 100644
index 00000000..37593f68
--- /dev/null
+++ b/boot/Makefile
@@ -0,0 +1,54 @@
+# Copyright (C) 1993, 1994, 1995, 1996, 1997 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.
+
+dir := boot
+makemode := utility
+
+SRCS = mach-crt0.c boot.c ux.c sigvec.S syscall.S boot_script.c
+COMMON-OBJS = notifyServer.o ourdeviceServer.o \
+ ioServer.o io_replyUser.o device_replyUser.o \
+ termServer.o bootstrapServer.o boot_script.o
+OBJS = boot.o $(COMMON-OBJS)
+UX-OBJS = mach-crt0.o uxboot.o sigvec.o syscall.o ux.o $(COMMON-OBJS)
+LCLHDRS = boot_script.h ux.h
+target = boot
+io-MIGSFLAGS=-DREPLY_PORTS
+DIST_FILES=frank1.ld frankemul.ld
+HURDLIBS=store shouldbeinlibc threads
+
+include ../Makeconf
+
+#install: /usr/local/bin/uxboot
+#
+#/usr/local/bin/uxboot: uxboot
+# cp $< $@
+
+all: boot # uxboot
+
+ourdevice.defs: device.defs
+ $(CPP) $(CPPFLAGS) -x c $< | sed -e '/out device : device_t/s/device_t/mach_port_send_t/' > $@
+
+
+uxboot.o: boot.c
+ $(COMPILE.c) -DUX $< -o $@
+
+uxboot.0: $(UX-OBJS) ../libthreads/libthreads.a
+ $(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
new file mode 100644
index 00000000..859dae25
--- /dev/null
+++ b/boot/boot.c
@@ -0,0 +1,1964 @@
+/* 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 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. */
+
+/* Written by Michael I. Bushnell. */
+
+#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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <cthreads.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 "notify_S.h"
+#include "exec_S.h"
+#include "ourdevice_S.h"
+#include "io_S.h"
+#include "device_reply_U.h"
+#include "io_reply_U.h"
+#include "term_S.h"
+#include "bootstrap_S.h"
+/* #include "tioctl_S.h" */
+
+#include "boot_script.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>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <error.h>
+#include <hurd.h>
+
+static struct termios orig_tty_state;
+static int isig;
+
+static void
+init_termstate ()
+{
+ struct termios tty_state;
+
+ if (tcgetattr (0, &tty_state) < 0)
+ error (10, errno, "tcgetattr");
+
+ 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");
+}
+
+static void
+restore_termstate ()
+{
+ tcsetattr (0, 0, &orig_tty_state);
+}
+
+#define host_fstat fstat
+typedef struct stat host_stat_t;
+#define host_exit exit
+
+#endif /* UX */
+
+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, pseudo_root;
+auth_t authserver;
+
+struct store *root_store;
+
+spin_lock_t queuelock = SPIN_LOCK_INITIALIZER;
+spin_lock_t readlock = SPIN_LOCK_INITIALIZER;
+
+mach_port_t php_child_name, psmdp_child_name, taskname;
+
+task_t child_task;
+mach_port_t bootport;
+
+int console_mscount;
+
+vm_address_t fs_stack_base;
+vm_size_t fs_stack_size;
+
+void init_termstate ();
+void restore_termstate ();
+
+char *fsname;
+
+char bootstrap_args[100] = "-";
+char *bootdevice = 0;
+char *bootscript = 0;
+
+void set_mach_stack_args (task_t, thread_t, char *, ...);
+
+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);
+}
+
+int
+request_server (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+{
+ extern int io_server (mach_msg_header_t *, mach_msg_header_t *);
+ extern int device_server (mach_msg_header_t *, mach_msg_header_t *);
+ extern int notify_server (mach_msg_header_t *, mach_msg_header_t *);
+ extern int term_server (mach_msg_header_t *, mach_msg_header_t *);
+/* extern int tioctl_server (mach_msg_header_t *, mach_msg_header_t *); */
+ extern int bootstrap_server (mach_msg_header_t *, mach_msg_header_t *);
+ extern void bootstrap_compat ();
+
+#if 0
+ if (inp->msgh_local_port == bootport && boot_like_cmudef)
+ {
+ if (inp->msgh_id == 999999)
+ {
+ bootstrap_compat (inp, outp);
+ return 1;
+ }
+ else
+ return bootstrap_server (inp, outp);
+ }
+ else
+#endif
+ return (io_server (inp, outp)
+ || device_server (inp, outp)
+ || notify_server (inp, outp)
+ || term_server (inp, outp)
+ /* || tioctl_server (inp, outp) */);
+}
+
+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);
+ if (*(Elf32_Word *) hdr.e.e_ident == *(Elf32_Word *) "\177ELF")
+ {
+ 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, (u_int) 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 ();
+
+/* 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)
+{
+ static const char msg[] = ": cannot open\n";
+ int fd = useropen (filename, O_RDONLY, 0);
+ host_stat_t st;
+ error_t err;
+ mach_port_t memobj;
+ vm_address_t region;
+
+ write (2, filename, strlen (filename));
+ if (fd < 0)
+ {
+ write (2, msg, sizeof msg - 1);
+ host_exit (1);
+ }
+ else
+ write (2, msg + sizeof msg - 2, 1);
+
+ host_fstat (fd, &st);
+
+ err = default_pager_object_create (defpager, &memobj,
+ round_page (st.st_size));
+ if (err)
+ {
+ static const char msg[] = "cannot create default-pager object\n";
+ write (2, msg, sizeof msg - 1);
+ host_exit (1);
+ }
+
+ region = 0;
+ vm_map (mach_task_self (), &region, round_page (st.st_size),
+ 0, 1, memobj, 0, 0, VM_PROT_ALL, VM_PROT_ALL, VM_INHERIT_NONE);
+ read (fd, (char *) region, st.st_size);
+ 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,
+ char **argv, char *strings, int stringlen)
+{
+ char *args, *p;
+ int arg_len, i;
+ unsigned reg_size;
+ void *arg_pos;
+ vm_offset_t stack_start, stack_end;
+ vm_address_t startpc, str_start;
+ thread_t thread;
+ struct i386_thread_state regs;
+
+ write (2, path, strlen (path));
+ for (i = 1; i < argc; ++i)
+ {
+ write (2, " ", 1);
+ write (2, argv[i], strlen (argv[i]));
+ }
+ write (2, "\r\n", 2);
+
+ startpc = load_image (task, path);
+ thread_create (task, &thread);
+ arg_len = stringlen + (argc + 2) * sizeof (char *) + sizeof (integer_t);
+ arg_len += 5 * sizeof (int);
+ stack_end = VM_MAX_ADDRESS;
+ stack_start = VM_MAX_ADDRESS - 16 * 1024 * 1024;
+ vm_allocate (task, &stack_start, stack_end - stack_start, FALSE);
+ reg_size = i386_THREAD_STATE_COUNT;
+ thread_get_state (thread, i386_THREAD_STATE,
+ (thread_state_t) &regs, &reg_size);
+ regs.eip = (int) startpc;
+ regs.uesp = (int) ((stack_end - arg_len) & ~(sizeof (int) - 1));
+ thread_set_state (thread, i386_THREAD_STATE,
+ (thread_state_t) &regs, reg_size);
+ arg_pos = (void *) regs.uesp;
+ 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;
+ for (i = 0; i < argc; i++)
+ *((char **) p)++ = argv[i] - strings + (char *) str_start;
+ *((char **) p)++ = 0;
+ *((char **) p)++ = 0;
+ 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));
+ munmap ((caddr_t) args,
+ stack_end - trunc_page ((vm_offset_t) arg_pos));
+ thread_resume (thread);
+ mach_port_deallocate (mach_task_self (), thread);
+ return 0;
+}
+
+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" },
+ { "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."},
+ { 0 }
+};
+static char args_doc[] = "BOOT-SCRIPT";
+static char doc[] = "Boot a second hurd";
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ size_t len;
+
+ 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 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;
+ char *buf = 0;
+ int i, len;
+ 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);
+
+ 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)
+ /* 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. */
+ {
+ 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);
+ }
+
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &pseudo_master_device_port);
+ mach_port_insert_right (mach_task_self (),
+ pseudo_master_device_port,
+ pseudo_master_device_port,
+ MACH_MSG_TYPE_MAKE_SEND);
+ mach_port_move_member (mach_task_self (), pseudo_master_device_port,
+ receive_set);
+ mach_port_request_notification (mach_task_self (), pseudo_master_device_port,
+ MACH_NOTIFY_NO_SENDERS, 1,
+ pseudo_master_device_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo);
+ if (foo != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), foo);
+
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &pseudo_console);
+ mach_port_move_member (mach_task_self (), pseudo_console, receive_set);
+ mach_port_request_notification (mach_task_self (), pseudo_console,
+ MACH_NOTIFY_NO_SENDERS, 1, pseudo_console,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo);
+ if (foo != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), foo);
+
+ /* 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))
+ {
+ static const char msg[] = "error setting variable";
+
+ write (2, msg, strlen (msg));
+ host_exit (1);
+ }
+
+ /* Parse the boot script. */
+ {
+ char *p, *line;
+ static const char filemsg[] = "Can't open boot script\n";
+ int amt, fd, err;
+
+ fd = open (bootscript, O_RDONLY, 0);
+ if (fd < 0)
+ {
+ write (2, filemsg, sizeof (filemsg));
+ host_exit (1);
+ }
+ p = buf = malloc (500);
+ 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);
+ p = newbuf + (p - buf);
+ buf = newbuf;
+ }
+ }
+ line = p = buf;
+ while (1)
+ {
+ while (p < buf + amt && *p != '\n')
+ p++;
+ *p = '\0';
+ err = boot_script_parse_line (line);
+ if (err)
+ {
+ char *str;
+ int i;
+
+ str = boot_script_error_string (err);
+ i = strlen (str);
+ write (2, str, i);
+ write (2, " in `", 5);
+ write (2, line, strlen (line));
+ write (2, "'\n", 2);
+ host_exit (1);
+ }
+ if (p == buf + amt)
+ break;
+ line = ++p;
+ }
+ }
+
+ if (index (bootstrap_args, 'd'))
+ {
+ static const char msg[] = "Pausing. . .";
+ char c;
+ write (2, msg, sizeof (msg) - 1);
+ read (0, &c, 1);
+ }
+
+ init_termstate ();
+
+ /* The boot script has now been parsed into internal data structures.
+ Now execute its directives. */
+ {
+ int err;
+
+ err = boot_script_exec ();
+ if (err)
+ {
+ char *str = boot_script_error_string (err);
+ int i = strlen (str);
+
+ write (2, str, i);
+ host_exit (1);
+ }
+ free (buf);
+ }
+
+ mach_port_deallocate (mach_task_self (), pseudo_master_device_port);
+
+ cthread_detach (cthread_fork ((cthread_fn_t) msg_thread, (any_t) 0));
+
+ for (;;)
+ {
+ fd_set rmask;
+ FD_ZERO (&rmask);
+ FD_SET (0, &rmask);
+ if (select (1, &rmask, 0, 0, 0) == 1)
+ read_reply ();
+ else
+ { /* We hosed */
+ perror ("select");
+ exit (5);
+ }
+ }
+
+/* mach_msg_server (request_server, __vm_page_size * 2, receive_set); */
+}
+
+/* Set up stack args the Mach way */
+void
+set_mach_stack_args (task_t user_task,
+ thread_t user_thread,
+ char *startpc, ...)
+{
+ /* 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, startpc);
+ arg_len = 0;
+ arg_count = 0;
+ for (;;) {
+ arg_ptr = va_arg(argv_ptr, char *);
+ if (arg_ptr == (char *)0)
+ break;
+ arg_count++;
+ arg_len += strlen(arg_ptr) + 1; /* space for '\0' */
+ }
+ va_end(argv_ptr);
+ /*
+ * Add space for:
+ * arg_count
+ * pointers to arguments
+ * trailing 0 pointer
+ * dummy 0 pointer to environment variables
+ * and align to integer boundary
+ */
+ arg_len += sizeof(integer_t) + (2 + arg_count) * sizeof(char *);
+ arg_len = (arg_len + (sizeof(integer_t) - 1)) & ~(sizeof(integer_t)-1);
+
+
+ /* This small piece is from .../mk/bootstrap/i386/exec.c. */
+ {
+ vm_offset_t stack_start;
+ vm_offset_t stack_end;
+ struct i386_thread_state regs;
+ unsigned int reg_size;
+
+#define STACK_SIZE (1024 * 1024 * 16)
+
+ /*
+ * Add space for 5 ints to arguments, for
+ * PS program. XXX
+ */
+ arg_len += 5 * sizeof(int);
+
+ /*
+ * Allocate stack.
+ */
+ stack_end = VM_MAX_ADDRESS;
+ stack_start = VM_MAX_ADDRESS - STACK_SIZE;
+ (void)vm_allocate(user_task,
+ &stack_start,
+ (vm_size_t)(stack_end - stack_start),
+ FALSE);
+
+ reg_size = i386_THREAD_STATE_COUNT;
+ (void)thread_get_state(user_thread,
+ i386_THREAD_STATE,
+ (thread_state_t)&regs,
+ &reg_size);
+
+ regs.eip = (int) startpc;
+ regs.uesp = (int)((stack_end - arg_len) & ~(sizeof(int)-1));
+
+ (void)thread_set_state(user_thread,
+ i386_THREAD_STATE,
+ (thread_state_t)&regs,
+ reg_size);
+
+ arg_pos = (void *) regs.uesp;
+ }
+
+ /*
+ * Copy out the arguments.
+ */
+ {
+ vm_offset_t u_arg_start;
+ /* user start of argument list block */
+ vm_offset_t k_arg_start;
+ /* kernel start of argument list block */
+ vm_offset_t u_arg_page_start;
+ /* user start of args, page-aligned */
+ vm_size_t arg_page_size;
+ /* page_aligned size of args */
+ vm_offset_t k_arg_page_start;
+ /* kernel start of args, page-aligned */
+
+ register
+ char ** k_ap; /* kernel arglist address */
+ char * u_cp; /* user argument string address */
+ register
+ char * k_cp; /* kernel argument string address */
+ register
+ int i;
+
+ /*
+ * Get address of argument list in user space
+ */
+ u_arg_start = (vm_offset_t)arg_pos;
+
+ /*
+ * Round to page boundaries, and allocate kernel copy
+ */
+ u_arg_page_start = trunc_page(u_arg_start);
+ arg_page_size = (vm_size_t)(round_page(u_arg_start + arg_len)
+ - u_arg_page_start);
+
+ k_arg_page_start = (vm_address_t) mmap (0, arg_page_size,
+ PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
+
+ /*
+ * 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, startpc);
+ 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) munmap ((caddr_t) k_arg_page_start,
+ arg_page_size);
+ }
+}
+
+
+void
+msg_thread()
+{
+ while (1)
+ mach_msg_server (request_server, 0, receive_set);
+}
+
+
+enum read_type
+{
+ DEV_READ,
+ DEV_READI,
+ IO_READ,
+};
+struct qr
+{
+ enum read_type type;
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_type;
+ int amount;
+ struct qr *next;
+};
+struct qr *qrhead, *qrtail;
+
+/* Queue a read for later reply. */
+void
+queue_read (enum read_type type,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ int amount)
+{
+ struct qr *qr;
+
+ spin_lock (&queuelock);
+
+ qr = malloc (sizeof (struct qr));
+ qr->type = type;
+ qr->reply_port = reply_port;
+ qr->reply_type = reply_type;
+ qr->amount = amount;
+ qr->next = 0;
+ if (qrtail)
+ qrtail->next = qr;
+ else
+ qrhead = qrtail = qr;
+
+ spin_unlock (&queuelock);
+}
+
+/* TRUE if there's data available on stdin, which should be used to satisfy
+ console read requests. */
+static int should_read = 0;
+
+/* Reply to a queued read. */
+void
+read_reply ()
+{
+ int avail;
+ struct qr *qr;
+ char * buf;
+ int amtread;
+
+ /* By forcing SHOULD_READ to true before trying the lock, we ensure that
+ either we get the lock ourselves or that whoever currently holds the
+ lock will service this read when he unlocks it. */
+ should_read = 1;
+ if (! spin_try_lock (&readlock))
+ return;
+
+ /* Since we're commited to servicing the read, no one else need do so. */
+ should_read = 0;
+
+ ioctl (0, FIONREAD, &avail);
+ if (!avail)
+ {
+ spin_unlock (&readlock);
+ return;
+ }
+
+ spin_lock (&queuelock);
+
+ if (!qrhead)
+ {
+ spin_unlock (&queuelock);
+ spin_unlock (&readlock);
+ return;
+ }
+
+ qr = qrhead;
+ qrhead = qr->next;
+ if (qr == qrtail)
+ qrtail = 0;
+
+ spin_unlock (&queuelock);
+
+ if (qr->type == DEV_READ)
+ buf = mmap (0, qr->amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ else
+ buf = alloca (qr->amount);
+ amtread = read (0, buf, qr->amount);
+
+ spin_unlock (&readlock);
+
+ switch (qr->type)
+ {
+ case DEV_READ:
+ if (amtread >= 0)
+ ds_device_read_reply (qr->reply_port, qr->reply_type, 0,
+ (io_buf_ptr_t) buf, amtread);
+ else
+ ds_device_read_reply (qr->reply_port, qr->reply_type, errno, 0, 0);
+ break;
+
+ case DEV_READI:
+ if (amtread >= 0)
+ ds_device_read_reply_inband (qr->reply_port, qr->reply_type, 0,
+ buf, amtread);
+ else
+ ds_device_read_reply_inband (qr->reply_port, qr->reply_type, errno,
+ 0, 0);
+ break;
+
+ case IO_READ:
+ if (amtread >= 0)
+ io_read_reply (qr->reply_port, qr->reply_type, 0,
+ buf, amtread);
+ else
+ io_read_reply (qr->reply_port, qr->reply_type, errno, 0, 0);
+ break;
+ }
+
+ free (qr);
+}
+
+/* Unlock READLOCK, and also service any new read requests that it was
+ blocking. */
+static void
+unlock_readlock ()
+{
+ spin_unlock (&readlock);
+ while (should_read)
+ read_reply ();
+}
+
+/*
+ * Handle bootstrap requests.
+ */
+/* These two functions from .../mk/bootstrap/default_pager.c. */
+
+kern_return_t
+do_bootstrap_privileged_ports(bootstrap, hostp, devicep)
+ mach_port_t bootstrap;
+ mach_port_t *hostp, *devicep;
+{
+ *hostp = privileged_host_port;
+ *devicep = pseudo_master_device_port;
+ return KERN_SUCCESS;
+}
+
+void
+bootstrap_compat(in, out)
+ mach_msg_header_t *in, *out;
+{
+ mig_reply_header_t *reply = (mig_reply_header_t *) out;
+ mach_msg_return_t mr;
+
+ struct imsg {
+ mach_msg_header_t hdr;
+ mach_msg_type_t port_desc_1;
+ mach_port_t port_1;
+ mach_msg_type_t port_desc_2;
+ mach_port_t port_2;
+ } imsg;
+
+ /*
+ * Send back the host and device ports.
+ */
+
+ imsg.hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX |
+ MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(in->msgh_bits), 0);
+ /* msgh_size doesn't need to be initialized */
+ imsg.hdr.msgh_remote_port = in->msgh_remote_port;
+ imsg.hdr.msgh_local_port = MACH_PORT_NULL;
+ /* msgh_seqno doesn't need to be initialized */
+ imsg.hdr.msgh_id = in->msgh_id + 100; /* this is a reply msg */
+
+ imsg.port_desc_1.msgt_name = MACH_MSG_TYPE_COPY_SEND;
+ imsg.port_desc_1.msgt_size = (sizeof(mach_port_t) * 8);
+ imsg.port_desc_1.msgt_number = 1;
+ imsg.port_desc_1.msgt_inline = TRUE;
+ imsg.port_desc_1.msgt_longform = FALSE;
+ imsg.port_desc_1.msgt_deallocate = FALSE;
+ imsg.port_desc_1.msgt_unused = 0;
+
+ imsg.port_1 = privileged_host_port;
+
+ imsg.port_desc_2 = imsg.port_desc_1;
+
+ imsg.port_desc_2.msgt_name = MACH_MSG_TYPE_MAKE_SEND;
+ imsg.port_2 = pseudo_master_device_port;
+
+ /*
+ * Send the reply message.
+ * (mach_msg_server can not do this, because the reply
+ * is not in standard format.)
+ */
+
+ mr = mach_msg(&imsg.hdr, MACH_SEND_MSG,
+ sizeof imsg, 0, MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if (mr != MACH_MSG_SUCCESS)
+ (void) mach_port_deallocate(mach_task_self (),
+ imsg.hdr.msgh_remote_port);
+
+ /*
+ * Tell mach_msg_server to do nothing.
+ */
+
+ reply->RetCode = MIG_NO_REPLY;
+}
+
+/* Implementation of device interface */
+
+kern_return_t
+ds_device_open (mach_port_t master_port,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ dev_mode_t mode,
+ dev_name_t name,
+ mach_port_t *device,
+ mach_msg_type_name_t *devicetype)
+{
+ if (master_port != pseudo_master_device_port)
+ return D_INVALID_OPERATION;
+
+ if (!strcmp (name, "console"))
+ {
+#if 0
+ mach_port_insert_right (mach_task_self (), pseudo_console,
+ pseudo_console, MACH_MSG_TYPE_MAKE_SEND);
+ console_send_rights++;
+#endif
+ console_mscount++;
+ *device = pseudo_console;
+ *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;
+ }
+
+ *devicetype = MACH_MSG_TYPE_MOVE_SEND;
+ return device_open (master_device_port, mode, name, device);
+}
+
+kern_return_t
+ds_device_close (device_t device)
+{
+ if (device != pseudo_console && device != pseudo_root)
+ return D_NO_SUCH_DEVICE;
+ return 0;
+}
+
+kern_return_t
+ds_device_write (device_t device,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ dev_mode_t mode,
+ recnum_t recnum,
+ io_buf_ptr_t data,
+ unsigned int datalen,
+ int *bytes_written)
+{
+ if (device == pseudo_console)
+ {
+#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);
+
+ return (*bytes_written == -1 ? D_IO_ERROR : D_SUCCESS);
+ }
+ else if (device == pseudo_root)
+ return
+ (store_write (root_store, recnum, data, datalen, bytes_written) == 0
+ ? D_SUCCESS
+ : D_IO_ERROR);
+ else
+ return D_NO_SUCH_DEVICE;
+}
+
+kern_return_t
+ds_device_write_inband (device_t device,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ dev_mode_t mode,
+ recnum_t recnum,
+ io_buf_ptr_inband_t data,
+ unsigned int datalen,
+ int *bytes_written)
+{
+ if (device == pseudo_console)
+ {
+#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);
+
+ return (*bytes_written == -1 ? D_IO_ERROR : D_SUCCESS);
+ }
+ else if (device == pseudo_root)
+ return
+ (store_write (root_store, recnum, data, datalen, bytes_written) == 0
+ ? D_SUCCESS
+ : D_IO_ERROR);
+ else
+ return D_NO_SUCH_DEVICE;
+}
+
+kern_return_t
+ds_device_read (device_t device,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ dev_mode_t mode,
+ recnum_t recnum,
+ int bytes_wanted,
+ io_buf_ptr_t *data,
+ unsigned int *datalen)
+{
+ 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;
+ }
+#endif
+
+ 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
+ {
+ unlock_readlock ();
+ queue_read (DEV_READ, reply_port, reply_type, bytes_wanted);
+ return MIG_NO_REPLY;
+ }
+ }
+ else if (device == pseudo_root)
+ {
+ *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
+ds_device_read_inband (device_t device,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ dev_mode_t mode,
+ recnum_t recnum,
+ int bytes_wanted,
+ io_buf_ptr_inband_t data,
+ unsigned int *datalen)
+{
+ 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;
+ }
+#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);
+ }
+ else
+ {
+ unlock_readlock ();
+ queue_read (DEV_READI, reply_port, reply_type, bytes_wanted);
+ return MIG_NO_REPLY;
+ }
+ }
+ else if (device == pseudo_root)
+ {
+ 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)
+{
+ if (device != pseudo_console)
+ return D_NO_SUCH_DEVICE;
+ return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_xxx_device_get_status (device_t device,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ u_int *statuscnt)
+{
+ if (device != pseudo_console && device != pseudo_root)
+ return D_NO_SUCH_DEVICE;
+ return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_xxx_device_set_filter (device_t device,
+ mach_port_t rec,
+ int pri,
+ filter_array_t filt,
+ unsigned int len)
+{
+ if (device != pseudo_console && device != pseudo_root)
+ return D_NO_SUCH_DEVICE;
+ return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_map (device_t device,
+ vm_prot_t prot,
+ vm_offset_t offset,
+ vm_size_t size,
+ memory_object_t *pager,
+ int unmap)
+{
+ if (device != pseudo_console && device != pseudo_root)
+ return D_NO_SUCH_DEVICE;
+ return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_set_status (device_t device,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ unsigned int statuslen)
+{
+ if (device != pseudo_console && device != pseudo_root)
+ return D_NO_SUCH_DEVICE;
+ return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_get_status (device_t device,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ unsigned int *statuslen)
+{
+ 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;
+ return D_SUCCESS;
+ }
+ else
+ return D_INVALID_OPERATION;
+ else
+ return D_NO_SUCH_DEVICE;
+}
+
+kern_return_t
+ds_device_set_filter (device_t device,
+ mach_port_t receive_port,
+ int priority,
+ filter_array_t filter,
+ unsigned int filterlen)
+{
+ if (device != pseudo_console && device != pseudo_root)
+ return D_NO_SUCH_DEVICE;
+ return D_INVALID_OPERATION;
+}
+
+
+/* Implementation of notify interface */
+kern_return_t
+do_mach_notify_port_deleted (mach_port_t notify,
+ mach_port_t name)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_msg_accepted (mach_port_t notify,
+ mach_port_t name)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_port_destroyed (mach_port_t notify,
+ mach_port_t port)
+{
+ return EOPNOTSUPP;
+}
+
+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;
+ if (notify == pseudo_master_device_port)
+ {
+ if (no_console)
+ goto bye;
+ pseudo_master_device_port = MACH_PORT_NULL;
+ return 0;
+ }
+ if (notify == pseudo_console)
+ {
+ if (mscount == console_mscount &&
+ pseudo_master_device_port == MACH_PORT_NULL)
+ {
+ bye:
+ restore_termstate ();
+ write (2, "bye\n", 4);
+ host_exit (0);
+ }
+ else
+ {
+ no_console = (mscount == console_mscount);
+
+ mach_port_request_notification (mach_task_self (), pseudo_console,
+ MACH_NOTIFY_NO_SENDERS,
+ console_mscount == mscount
+ ? mscount + 1
+ : console_mscount,
+ pseudo_console,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo);
+ if (foo != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), foo);
+ }
+ }
+
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_send_once (mach_port_t notify)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_dead_name (mach_port_t notify,
+ mach_port_t name)
+{
+#if 0
+ if (name == child_task && notify == bootport)
+ host_exit (0);
+#endif
+ return EOPNOTSUPP;
+}
+
+
+/* Implementation of the Hurd I/O interface, which
+ we support for the console port only. */
+
+kern_return_t
+S_io_write (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ char *data,
+ mach_msg_type_number_t datalen,
+ off_t offset,
+ mach_msg_type_number_t *amtwritten)
+{
+ if (object != pseudo_console)
+ return EOPNOTSUPP;
+
+#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
+
+ *amtwritten = write (1, data, datalen);
+ return *amtwritten == -1 ? errno : 0;
+}
+
+kern_return_t
+S_io_read (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ char **data,
+ mach_msg_type_number_t *datalen,
+ off_t offset,
+ mach_msg_type_number_t amount)
+{
+ mach_msg_type_number_t avail;
+
+ if (object != pseudo_console)
+ return EOPNOTSUPP;
+
+#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
+
+ spin_lock (&readlock);
+ ioctl (0, FIONREAD, &avail);
+ if (avail)
+ {
+ if (amount > *datalen)
+ *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
+ {
+ unlock_readlock ();
+ queue_read (IO_READ, reply_port, reply_type, amount);
+ return MIG_NO_REPLY;
+ }
+}
+
+kern_return_t
+S_io_seek (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ off_t offset,
+ int whence,
+ off_t *newp)
+{
+ return object == pseudo_console ? ESPIPE : EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_readable (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ mach_msg_type_number_t *amt)
+{
+ if (object != pseudo_console)
+ return EOPNOTSUPP;
+ ioctl (0, FIONREAD, amt);
+ return 0;
+}
+
+kern_return_t
+S_io_set_all_openmodes (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ int bits)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_get_openmodes (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ int *modes)
+{
+ *modes = O_READ | O_WRITE;
+ return object == pseudo_console ? 0 : EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_set_some_openmodes (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ int bits)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_clear_some_openmodes (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ int bits)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_async (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ mach_port_t notify,
+ mach_port_t *id,
+ mach_msg_type_name_t *idtype)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_mod_owner (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ pid_t owner)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_get_owner (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ pid_t *owner)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_get_icky_async_id (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ mach_port_t *id,
+ mach_msg_type_name_t *idtype)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_select (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ int *type)
+{
+ fd_set r, w, x;
+ int n;
+
+ if (object != pseudo_console)
+ return EOPNOTSUPP;
+
+ FD_ZERO (&r);
+ FD_ZERO (&w);
+ FD_ZERO (&x);
+ FD_SET (0, &r);
+ FD_SET (0, &w);
+ FD_SET (0, &x);
+
+ n = select (1,
+ (*type & SELECT_READ) ? &r : 0,
+ (*type & SELECT_WRITE) ? &w : 0,
+ (*type & SELECT_URG) ? &x : 0,
+ 0);
+ if (n < 0)
+ return errno;
+
+ if (! FD_ISSET (0, &r))
+ *type &= ~SELECT_READ;
+ if (! FD_ISSET (0, &w))
+ *type &= ~SELECT_WRITE;
+ if (! FD_ISSET (0, &x))
+ *type &= ~SELECT_URG;
+
+ return 0;
+}
+
+kern_return_t
+S_io_stat (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ struct stat *st)
+{
+ if (object != pseudo_console)
+ return EOPNOTSUPP;
+
+ bzero (st, sizeof (struct stat));
+ st->st_blksize = 1024;
+ return 0;
+}
+
+kern_return_t
+S_io_reauthenticate (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ mach_port_t rend)
+{
+ uid_t *gu, *au;
+ gid_t *gg, *ag;
+ unsigned int gulen = 0, aulen = 0, gglen = 0, aglen = 0;
+
+ if (! auth_server_authenticate (authserver,
+ rend, MACH_MSG_TYPE_COPY_SEND,
+ object, MACH_MSG_TYPE_MAKE_SEND,
+ &gu, &gulen,
+ &au, &aulen,
+ &gg, &gglen,
+ &ag, &aglen))
+ {
+ mig_deallocate ((vm_address_t) gu, gulen * sizeof *gu);
+ mig_deallocate ((vm_address_t) au, aulen * sizeof *gu);
+ mig_deallocate ((vm_address_t) gg, gglen * sizeof *gu);
+ mig_deallocate ((vm_address_t) au, aulen * sizeof *gu);
+ }
+ mach_port_deallocate (mach_task_self (), rend);
+
+ return 0;
+}
+
+kern_return_t
+S_io_restrict_auth (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ mach_port_t *newobject,
+ mach_msg_type_name_t *newobjtype,
+ uid_t *uids,
+ u_int nuids,
+ uid_t *gids,
+ u_int ngids)
+{
+ if (object != pseudo_console)
+ return EOPNOTSUPP;
+ *newobject = pseudo_console;
+ *newobjtype = MACH_MSG_TYPE_MAKE_SEND;
+ console_mscount++;
+ return 0;
+}
+
+kern_return_t
+S_io_duplicate (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ mach_port_t *newobj,
+ mach_msg_type_name_t *newobjtype)
+{
+ if (object != pseudo_console)
+ return EOPNOTSUPP;
+ *newobj = pseudo_console;
+ *newobjtype = MACH_MSG_TYPE_MAKE_SEND;
+ console_mscount++;
+ return 0;
+}
+
+kern_return_t
+S_io_server_version (mach_port_t object,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ char *name,
+ int *maj,
+ int *min,
+ int *edit)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_map (mach_port_t obj,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ mach_port_t *rd,
+ mach_msg_type_name_t *rdtype,
+ mach_port_t *wr,
+ mach_msg_type_name_t *wrtype)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_map_cntl (mach_port_t obj,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ mach_port_t *mem,
+ mach_msg_type_name_t *memtype)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_get_conch (mach_port_t obj,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_release_conch (mach_port_t obj,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_eofnotify (mach_port_t obj,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type)
+
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_prenotify (mach_port_t obj,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ vm_offset_t start,
+ vm_offset_t end)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_postnotify (mach_port_t obj,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ vm_offset_t start,
+ vm_offset_t end)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_readsleep (mach_port_t obj,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_readnotify (mach_port_t obj,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type)
+{
+ return EOPNOTSUPP;
+}
+
+
+kern_return_t
+S_io_sigio (mach_port_t obj,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type)
+{
+ return EOPNOTSUPP;
+}
+
+
+kern_return_t
+S_io_pathconf (mach_port_t obj,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_type,
+ int name, int *value)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_io_identity (mach_port_t obj,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ mach_port_t *id,
+ mach_msg_type_name_t *idtype,
+ mach_port_t *fsid,
+ mach_msg_type_name_t *fsidtype,
+ int *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;
+}
+
+
+
+/* Implementation of the Hurd terminal driver interface, which we only
+ support on the console device. */
+
+kern_return_t
+S_termctty_open_terminal (mach_port_t object,
+ int flags,
+ mach_port_t *result,
+ mach_msg_type_name_t *restype)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+S_term_getctty (mach_port_t object,
+ mach_port_t *cttyid, mach_msg_type_name_t *cttyPoly)
+{
+ static mach_port_t id = MACH_PORT_NULL;
+
+ if (object != pseudo_console)
+ return EOPNOTSUPP;
+
+ if (id == MACH_PORT_NULL)
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_DEAD_NAME, &id);
+
+ *cttyid = id;
+ *cttyPoly = MACH_MSG_TYPE_COPY_SEND;
+ return 0;
+}
+
+
+kern_return_t S_term_open_ctty
+(
+ io_t terminal,
+ pid_t pid,
+ pid_t pgrp,
+ mach_port_t *newtty,
+ mach_msg_type_name_t *newttytype
+)
+{ return EOPNOTSUPP; }
+
+kern_return_t S_term_set_nodename
+(
+ io_t terminal,
+ string_t name
+)
+{ return EOPNOTSUPP; }
+
+kern_return_t S_term_get_nodename
+(
+ io_t terminal,
+ string_t name
+)
+{ 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,
+ file_t filenode
+)
+{ return EOPNOTSUPP; }
+
+kern_return_t S_term_get_bottom_type
+(
+ io_t terminal,
+ int *ttype
+)
+{ return EOPNOTSUPP; }
+
+kern_return_t S_term_on_machdev
+(
+ io_t terminal,
+ mach_port_t machdev
+)
+{ return EOPNOTSUPP; }
+
+kern_return_t S_term_on_hurddev
+(
+ io_t terminal,
+ io_t hurddev
+)
+{ return EOPNOTSUPP; }
+
+kern_return_t S_term_on_pty
+(
+ io_t terminal,
+ io_t *ptymaster
+)
+{ return EOPNOTSUPP; }
diff --git a/boot/boot_script.c b/boot/boot_script.c
new file mode 100644
index 00000000..04ede101
--- /dev/null
+++ b/boot/boot_script.c
@@ -0,0 +1,822 @@
+/* Boot script parser for Mach. */
+
+/* Written by Shantanu Goel (goel@cs.columbia.edu). */
+
+#include <mach.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "boot_script.h"
+
+
+/* This structure describes a symbol. */
+struct sym
+{
+ /* Symbol name. */
+ const char *name;
+
+ /* Type of value returned by function. */
+ int type;
+
+ /* Symbol value. */
+ int val;
+
+ /* For function symbols; type of value returned by function. */
+ int ret_type;
+
+ /* For function symbols; if set, execute function at the time
+ of command execution, not during parsing. A function with
+ this field set must also have `no_arg' set. Also, the function's
+ `val' argument will always be NULL. */
+ int run_on_exec;
+};
+
+/* Additional values symbols can take.
+ These are only used internally. */
+#define VAL_SYM 3 /* symbol table entry */
+#define VAL_FUNC 4 /* function pointer */
+
+/* This structure describes an argument. */
+struct arg
+{
+ /* Argument text copied verbatim. 0 if none. */
+ char *text;
+
+ /* Type of value assigned. 0 if none. */
+ int type;
+
+ /* Argument value. */
+ int val;
+};
+
+/* List of commands. */
+static struct cmd **cmds = 0;
+
+/* Amount allocated for `cmds'. */
+static int cmds_alloc = 0;
+
+/* Next available slot in `cmds'. */
+static int cmds_index = 0;
+
+/* Symbol table. */
+static struct sym **symtab = 0;
+
+/* Amount allocated for `symtab'. */
+static int symtab_alloc = 0;
+
+/* Next available slot in `symtab'. */
+static int symtab_index = 0;
+
+/* Create a task. */
+static int
+create_task (struct cmd *cmd, int *val)
+{
+ if (task_create (mach_task_self (), 0, (task_t *) &cmd->task) ||
+ task_suspend (cmd->task))
+ {
+ printf ("(bootstrap): %s: Cannot create task\n", cmd->path);
+ return BOOT_SCRIPT_MACH_ERROR;
+ }
+ *val = (int) cmd->task;
+ return 0;
+}
+
+/* Resume a task. */
+static int
+resume_task (struct cmd *cmd, int *val)
+{
+ if (task_resume (cmd->task))
+ {
+ printf ("(bootstrap): %s: Cannot resume task\n", cmd->path);
+ return BOOT_SCRIPT_MACH_ERROR;
+ }
+ return 0;
+}
+
+/* Resume a task when the user hits return. */
+static int
+prompt_resume_task (struct cmd *cmd, int *val)
+{
+ char xx[5];
+
+ printf ("Hit return to resume %s...", cmd->path);
+ safe_gets (xx, sizeof xx);
+
+ if (task_resume (cmd->task))
+ {
+ printf ("(bootstrap): %s: Cannot resume task\n", cmd->path);
+ return BOOT_SCRIPT_MACH_ERROR;
+ }
+
+ return 0;
+}
+
+static int
+read_file (struct cmd *cmd, int *val)
+{
+ *val = boot_script_read_file (cmd->path);
+ if (*val == 0)
+ {
+ printf ("(bootstrap): %s: Cannot read boot script\n", cmd->path);
+ return BOOT_SCRIPT_MACH_ERROR;
+ }
+ return 0;
+}
+
+/* List of builtin symbols. */
+static struct sym builtin_symbols[] =
+{
+ { "task-create", VAL_FUNC, (int) create_task, VAL_PORT, 0 },
+ { "task-resume", VAL_FUNC, (int) resume_task, VAL_NONE, 1 },
+ { "prompt-task-resume", VAL_FUNC, (int) prompt_resume_task, VAL_NONE, 1 },
+ { "read-file", VAL_FUNC, (int) read_file, VAL_PORT, 0 },
+};
+#define NUM_BUILTIN (sizeof (builtin_symbols) / sizeof (builtin_symbols[0]))
+
+/* Free CMD and all storage associated with it.
+ If ABORTING is set, terminate the task associated with CMD,
+ otherwise just deallocate the send right. */
+static void
+free_cmd (struct cmd *cmd, int aborting)
+{
+ if (cmd->task)
+ {
+ if (aborting)
+ task_terminate (cmd->task);
+ else
+ mach_port_deallocate (mach_task_self (), cmd->task);
+ }
+ if (cmd->args)
+ {
+ int i;
+
+ for (i = 0; i < cmd->args_index; i++)
+ free (cmd->args[i]);
+ free (cmd->args);
+ }
+ if (cmd->exec_funcs)
+ free (cmd->exec_funcs);
+ free (cmd);
+}
+
+/* Free all storage allocated by the parser.
+ If ABORTING is set, terminate all tasks. */
+static void
+cleanup (int aborting)
+{
+ int i;
+
+ for (i = 0; i < cmds_index; i++)
+ free_cmd (cmds[i], aborting);
+ free (cmds);
+ cmds = 0;
+ cmds_index = cmds_alloc = 0;
+
+ for (i = 0; i < symtab_index; i++)
+ free (symtab[i]);
+ free (symtab);
+ symtab = 0;
+ symtab_index = symtab_alloc = 0;
+}
+
+/* Add PTR to the list of pointers PTR_LIST, which
+ currently has ALLOC amount of space allocated to it, and
+ whose next available slot is INDEX. If more space
+ needs to to allocated, INCR is the amount by which
+ to increase it. Return 0 on success, non-zero otherwise. */
+static int
+add_list (void *ptr, void ***ptr_list, int *alloc, int *index, int incr)
+{
+ if (*index == *alloc)
+ {
+ void **p;
+
+ *alloc += incr;
+ p = malloc (*alloc * sizeof (void *));
+ if (! p)
+ {
+ *alloc -= incr;
+ return 1;
+ }
+ if (*ptr_list)
+ {
+ memcpy (p, *ptr_list, *index * sizeof (void *));
+ free (*ptr_list);
+ }
+ *ptr_list = p;
+ }
+ *(*ptr_list + *index) = ptr;
+ *index += 1;
+ return 0;
+}
+
+/* Create an argument with TEXT, value type TYPE, and value VAL.
+ Add the argument to the argument list of CMD. */
+static struct arg *
+add_arg (struct cmd *cmd, char *text, int type, int val)
+{
+ struct arg *arg;
+
+ arg = malloc (sizeof (struct arg));
+ if (arg)
+ {
+ arg->text = text;
+ arg->type = type;
+ arg->val = val;
+ if (add_list (arg, (void ***) &cmd->args,
+ &cmd->args_alloc, &cmd->args_index, 5))
+ {
+ free (arg);
+ return 0;
+ }
+ }
+ return arg;
+}
+
+/* Search for the symbol NAME in the symbol table. */
+static struct sym *
+sym_lookup (const char *name)
+{
+ int i;
+
+ for (i = 0; i < symtab_index; i++)
+ if (! strcmp (name, symtab[i]->name))
+ return symtab[i];
+ return 0;
+}
+
+/* Create an entry for symbol NAME in the symbol table. */
+static struct sym *
+sym_enter (const char *name)
+{
+ struct sym *sym;
+
+ sym = malloc (sizeof (struct sym));
+ if (sym)
+ {
+ memset (sym, 0, sizeof (struct sym));
+ sym->name = name;
+ if (add_list (sym, (void ***) &symtab, &symtab_alloc, &symtab_index, 20))
+ {
+ free (sym);
+ return 0;
+ }
+ }
+ return sym;
+}
+
+/* Parse the command line CMDLINE. */
+int
+boot_script_parse_line (char *cmdline)
+{
+ char *p, *q;
+ int error;
+ struct cmd *cmd;
+ struct arg *arg;
+
+ /* Extract command name. Ignore line if it lacks a command. */
+ for (p = cmdline; *p == ' ' || *p == '\t'; p++)
+ ;
+ if (*p == '#')
+ /* Ignore comment line. */
+ return 0;
+
+#if 0
+ if (*p && *p != ' ' && *p != '\t' && *p != '\n')
+ {
+ printf ("(bootstrap): %s\n", cmdline);
+ }
+#endif
+
+ for (q = p; *q && *q != ' ' && *q != '\t' && *q != '\n'; q++)
+ ;
+ if (p == q)
+ return 0;
+
+ *q = '\0';
+
+ /* Allocate a command structure. */
+ cmd = malloc (sizeof (struct cmd));
+ if (! cmd)
+ return BOOT_SCRIPT_NOMEM;
+ memset (cmd, 0, sizeof (struct cmd));
+ cmd->path = p;
+ p = q + 1;
+
+ for (arg = 0;;)
+ {
+ if (! arg)
+ {
+ /* Skip whitespace. */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ /* End of command line. */
+ if (! *p || *p == '\n')
+ {
+ /* Add command to list. */
+ if (add_list (cmd, (void ***) &cmds,
+ &cmds_alloc, &cmds_index, 10))
+ {
+ error = BOOT_SCRIPT_NOMEM;
+ goto bad;
+ }
+ return 0;
+ }
+ }
+
+ /* Look for a symbol. */
+ if (arg || (*p == '$' && (*(p + 1) == '{' || *(p + 1) == '(')))
+ {
+ char end_char = (*(p + 1) == '{') ? '}' : ')';
+ struct sym *sym = 0;
+
+ for (p += 2;;)
+ {
+ char c;
+ int i, val, type;
+ struct sym *s;
+
+ /* Parse symbol name. */
+ for (q = p; *q && *q != '\n' && *q != end_char && *q != '='; q++)
+ ;
+ if (p == q || ! *q || *q == '\n'
+ || (end_char == '}' && *q != '}'))
+ {
+ error = BOOT_SCRIPT_SYNTAX_ERROR;
+ goto bad;
+ }
+ c = *q;
+ *q = '\0';
+
+ /* See if this is a builtin symbol. */
+ for (i = 0; i < NUM_BUILTIN; i++)
+ if (! strcmp (p, builtin_symbols[i].name))
+ break;
+
+ if (i < NUM_BUILTIN)
+ s = &builtin_symbols[i];
+ else
+ {
+ /* Look up symbol in symbol table.
+ If no entry exists, create one. */
+ s = sym_lookup (p);
+ if (! s)
+ {
+ s = sym_enter (p);
+ if (! s)
+ {
+ error = BOOT_SCRIPT_NOMEM;
+ goto bad;
+ }
+ }
+ }
+
+ /* Only values are allowed in ${...} constructs. */
+ if (end_char == '}' && s->type == VAL_FUNC)
+ return BOOT_SCRIPT_INVALID_SYM;
+
+ /* Check that assignment is valid. */
+ if (c == '=' && s->type == VAL_FUNC)
+ {
+ error = BOOT_SCRIPT_INVALID_ASG;
+ goto bad;
+ }
+
+ /* For function symbols, execute the function. */
+ if (s->type == VAL_FUNC)
+ {
+ if (! s->run_on_exec)
+ {
+ (error
+ = ((*((int (*) (struct cmd *, int *)) s->val))
+ (cmd, &val)));
+ if (error)
+ goto bad;
+ type = s->ret_type;
+ }
+ else
+ {
+ if (add_list (s, (void ***) &cmd->exec_funcs,
+ &cmd->exec_funcs_alloc,
+ &cmd->exec_funcs_index, 5))
+ {
+ error = BOOT_SCRIPT_NOMEM;
+ goto bad;
+ }
+ type = VAL_NONE;
+ goto out;
+ }
+ }
+ else if (s->type == VAL_NONE)
+ {
+ type = VAL_SYM;
+ val = (int) s;
+ }
+ else
+ {
+ type = s->type;
+ val = s->val;
+ }
+
+ if (sym)
+ {
+ sym->type = type;
+ sym->val = val;
+ }
+ else if (arg)
+ {
+ arg->type = type;
+ arg->val = val;
+ }
+
+ out:
+ p = q + 1;
+ if (c == end_char)
+ {
+ /* Create an argument if necessary.
+ We create an argument if the symbol appears
+ in the expression by itself.
+
+ NOTE: This is temporary till the boot filesystem
+ servers support arguments. When that happens,
+ symbol values will only be printed if they're
+ associated with an argument. */
+ if (! arg && end_char == '}')
+ {
+ if (! add_arg (cmd, 0, type, val))
+ {
+ error = BOOT_SCRIPT_NOMEM;
+ goto bad;
+ }
+ }
+ arg = 0;
+ break;
+ }
+ if (s->type != VAL_FUNC)
+ sym = s;
+ }
+ }
+ else
+ {
+ char c;
+
+ /* Command argument; just copy the text. */
+ for (q = p;; q++)
+ {
+ if (! *q || *q == ' ' || *q == '\t' || *q == '\n')
+ break;
+ if (*q == '$' && *(q + 1) == '{')
+ break;
+ }
+ c = *q;
+ *q = '\0';
+
+ /* Add argument to list. */
+ arg = add_arg (cmd, p, VAL_NONE, 0);
+ if (! arg)
+ {
+ error = BOOT_SCRIPT_NOMEM;
+ goto bad;
+ }
+ if (c == '$')
+ p = q;
+ else
+ {
+ if (c)
+ p = q + 1;
+ else
+ p = q;
+ arg = 0;
+ }
+ }
+ }
+
+
+ bad:
+ free_cmd (cmd, 1);
+ cleanup (1);
+ return error;
+}
+
+/* Ensure that the command line buffer can accommodate LEN bytes of space. */
+#define CHECK_CMDLINE_LEN(len) \
+{ \
+ if (cmdline_alloc - cmdline_index < len) \
+ { \
+ char *ptr; \
+ int alloc, i; \
+ alloc = cmdline_alloc + len - (cmdline_alloc - cmdline_index) + 100; \
+ ptr = malloc (alloc); \
+ if (! ptr) \
+ { \
+ error = BOOT_SCRIPT_NOMEM; \
+ goto done; \
+ } \
+ memcpy (ptr, cmdline, cmdline_index); \
+ for (i = 0; i < argc; ++i) \
+ argv[i] = ptr + (argv[i] - cmdline); \
+ free (cmdline); \
+ cmdline = ptr; \
+ cmdline_alloc = alloc; \
+ } \
+}
+
+/* Execute commands previously parsed. */
+int
+boot_script_exec ()
+{
+ int cmd_index;
+
+ for (cmd_index = 0; cmd_index < cmds_index; cmd_index++)
+ {
+ char **argv, *cmdline;
+ int i, argc, cmdline_alloc;
+ int cmdline_index, error, arg_index;
+ struct cmd *cmd = cmds[cmd_index];
+
+ /* Skip command if it doesn't have an associated task. */
+ if (cmd->task == 0)
+ continue;
+
+ /* Allocate a command line and copy command name. */
+ cmdline_index = strlen (cmd->path) + 1;
+ cmdline_alloc = cmdline_index + 100;
+ cmdline = malloc (cmdline_alloc);
+ if (! cmdline)
+ {
+ cleanup (1);
+ return BOOT_SCRIPT_NOMEM;
+ }
+ memcpy (cmdline, cmd->path, cmdline_index);
+
+ /* Allocate argument vector. */
+ argv = malloc (sizeof (char *) * (cmd->args_index + 2));
+ if (! argv)
+ {
+ free (cmdline);
+ cleanup (1);
+ return BOOT_SCRIPT_NOMEM;
+ }
+ argv[0] = cmdline;
+ argc = 1;
+
+ /* Build arguments. */
+ for (arg_index = 0; arg_index < cmd->args_index; arg_index++)
+ {
+ struct arg *arg = cmd->args[arg_index];
+
+ /* Copy argument text. */
+ if (arg->text)
+ {
+ int len = strlen (arg->text);
+
+ if (arg->type == VAL_NONE)
+ len++;
+ CHECK_CMDLINE_LEN (len);
+ memcpy (cmdline + cmdline_index, arg->text, len);
+ argv[argc++] = &cmdline[cmdline_index];
+ cmdline_index += len;
+ }
+
+ /* Add value of any symbol associated with this argument. */
+ if (arg->type != VAL_NONE)
+ {
+ char *p, buf[50];
+ int len;
+
+ if (arg->type == VAL_SYM)
+ {
+ struct sym *sym = (struct sym *) arg->val;
+
+ /* Resolve symbol value. */
+ while (sym->type == VAL_SYM)
+ sym = (struct sym *) sym->val;
+ if (sym->type == VAL_NONE)
+ {
+ error = BOOT_SCRIPT_UNDEF_SYM;
+ goto done;
+ }
+ arg->type = sym->type;
+ arg->val = sym->val;
+ }
+
+ /* Print argument value. */
+ switch (arg->type)
+ {
+ case VAL_STR:
+ p = (char *) arg->val;
+ len = strlen (p);
+ break;
+
+ case VAL_PORT:
+ /* Insert send right. */
+ if ((mach_port_insert_right
+ (cmd->task, (mach_port_t) arg->val,
+ (mach_port_t) arg->val, MACH_MSG_TYPE_COPY_SEND)))
+ {
+ printf ("(bootstrap): %s: Cannot insert port right %d\n",
+ cmd->path, arg->val);
+ error = BOOT_SCRIPT_MACH_ERROR;
+ goto done;
+ }
+
+ i = arg->val;
+ p = buf + sizeof (buf);
+ len = 0;
+ do
+ {
+ *--p = i % 10 + '0';
+ len++;
+ }
+ while (i /= 10);
+ break;
+
+ default:
+ error = BOOT_SCRIPT_BAD_TYPE;
+ goto done;
+ }
+ len++;
+ CHECK_CMDLINE_LEN (len);
+ memcpy (cmdline + cmdline_index, p, len - 1);
+ *(cmdline + cmdline_index + len - 1) = '\0';
+ if (! arg->text)
+ argv[argc++] = &cmdline[cmdline_index];
+ cmdline_index += len;
+ }
+ }
+
+ /* Terminate argument vector. */
+ argv[argc] = 0;
+
+ /* Execute the command. */
+ if (boot_script_exec_cmd (cmd->task, cmd->path,
+ argc, argv, cmdline, cmdline_index))
+ {
+ error = BOOT_SCRIPT_EXEC_ERROR;
+ goto done;
+ }
+
+ error = 0;
+
+ done:
+ free (cmdline);
+ free (argv);
+ if (error)
+ {
+ cleanup (1);
+ return error;
+ }
+ }
+
+ for (cmd_index = 0; cmd_index < cmds_index; cmd_index++)
+ {
+ int i;
+ struct cmd *cmd = cmds[cmd_index];
+
+ /* Execute functions that want to be run on exec. */
+ for (i = 0; i < cmd->exec_funcs_index; i++)
+ {
+ struct sym *sym = cmd->exec_funcs[i];
+ int error = ((*((int (*) (struct cmd *, int *)) sym->val))
+ (cmd, 0));
+ if (error)
+ {
+ cleanup (1);
+ return error;
+ }
+ }
+ }
+
+ cleanup (0);
+ return 0;
+}
+
+/* Create an entry for the variable NAME with TYPE and value VAL,
+ in the symbol table. */
+int
+boot_script_set_variable (const char *name, int type, int val)
+{
+ struct sym *sym = sym_enter (name);
+
+ if (sym)
+ {
+ sym->type = type;
+ sym->val = val;
+ }
+ return sym ? 0 : 1;
+}
+
+
+/* Define the function NAME, which will return type RET_TYPE. */
+int
+boot_script_define_function (const char *name, int ret_type,
+ int (*func) (const struct cmd *cmd, int *val))
+{
+ struct sym *sym = sym_enter (name);
+
+ if (sym)
+ {
+ sym->type = VAL_FUNC;
+ sym->val = (int) func;
+ sym->ret_type = ret_type;
+ sym->run_on_exec = ret_type == VAL_NONE;
+ }
+ return sym ? 0 : 1;
+}
+
+
+/* Return a string describing ERR. */
+char *
+boot_script_error_string (int err)
+{
+ switch (err)
+ {
+ case BOOT_SCRIPT_NOMEM:
+ return "no memory";
+
+ case BOOT_SCRIPT_SYNTAX_ERROR:
+ return "syntax error";
+
+ case BOOT_SCRIPT_INVALID_ASG:
+ return "invalid variable in assignment";
+
+ case BOOT_SCRIPT_MACH_ERROR:
+ return "mach error";
+
+ case BOOT_SCRIPT_UNDEF_SYM:
+ return "undefined symbol";
+
+ case BOOT_SCRIPT_EXEC_ERROR:
+ return "exec error";
+
+ case BOOT_SCRIPT_INVALID_SYM:
+ return "invalid variable in expression";
+
+ case BOOT_SCRIPT_BAD_TYPE:
+ return "invalid value type";
+ }
+ return 0;
+}
+
+#ifdef BOOT_SCRIPT_TEST
+#include <stdio.h>
+
+int
+boot_script_exec_cmd (mach_port_t task, char *path, int argc,
+ char **argv, char *strings, int stringlen)
+{
+ int i;
+
+ printf ("port = %d: ", (int) task);
+ for (i = 0; i < argc; i++)
+ printf ("%s ", argv[i]);
+ printf ("\n");
+ return 0;
+}
+
+void
+main (int argc, char **argv)
+{
+ char buf[500], *p;
+ int len;
+ FILE *fp;
+ mach_port_t host_port, device_port;
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "Usage: %s <script>\n", argv[0]);
+ exit (1);
+ }
+ fp = fopen (argv[1], "r");
+ if (! fp)
+ {
+ fprintf (stderr, "Can't open %s\n", argv[1]);
+ exit (1);
+ }
+ host_port = 1;
+ device_port = 2;
+ boot_script_set_variable ("host-port", VAL_PORT, (int) host_port);
+ boot_script_set_variable ("device-port", VAL_PORT, (int) device_port);
+ boot_script_set_variable ("root-device", VAL_STR, (int) "hd0a");
+ boot_script_set_variable ("boot-args", VAL_STR, (int) "-ad");
+ p = buf;
+ len = sizeof (buf);
+ while (fgets (p, len, fp))
+ {
+ int i, err;
+
+ i = strlen (p) + 1;
+ err = boot_script_parse_line (p);
+ if (err)
+ {
+ fprintf (stderr, "error %s\n", boot_script_error_string (err));
+ exit (1);
+ }
+ p += i;
+ len -= i;
+ }
+ boot_script_exec ();
+ exit (0);
+}
+#endif /* BOOT_SCRIPT_TEST */
diff --git a/boot/boot_script.h b/boot/boot_script.h
new file mode 100644
index 00000000..d2db1a14
--- /dev/null
+++ b/boot/boot_script.h
@@ -0,0 +1,90 @@
+/* Definitions for boot script parser for Mach. */
+
+/* Written by Shantanu Goel (goel@cs.columbia.edu). */
+
+/* Error codes returned by boot_script_parse_line()
+ and boot_script_exec_cmd(). */
+#define BOOT_SCRIPT_NOMEM 1
+#define BOOT_SCRIPT_SYNTAX_ERROR 2
+#define BOOT_SCRIPT_INVALID_ASG 3
+#define BOOT_SCRIPT_MACH_ERROR 4
+#define BOOT_SCRIPT_UNDEF_SYM 5
+#define BOOT_SCRIPT_EXEC_ERROR 6
+#define BOOT_SCRIPT_INVALID_SYM 7
+#define BOOT_SCRIPT_BAD_TYPE 8
+
+/* Legal values for argument `type' to function
+ boot_script_set_variable and boot_script_define_function. */
+#define VAL_NONE 0 /* none -- function runs at exec time */
+#define VAL_STR 1 /* string */
+#define VAL_PORT 2 /* port */
+
+/* This structure describes a command. */
+struct cmd
+{
+ /* Path of executable. */
+ char *path;
+
+ /* Task port. */
+ mach_port_t task;
+
+ /* Argument list. */
+ struct arg **args;
+
+ /* Amount allocated for `args'. */
+ int args_alloc;
+
+ /* Next available slot in `args'. */
+ int args_index;
+
+ /* List of functions that want to be run on command execution. */
+ struct sym **exec_funcs;
+
+ /* Amount allocated for `exec_funcs'. */
+ int exec_funcs_alloc;
+
+ /* Next available slot in `exec_funcs'. */
+ int exec_funcs_index;
+};
+
+
+/* The user must define this function. Load the image of the
+ executable specified by PATH in TASK. Create a thread
+ in TASK and point it at the executable's entry point. Initialize
+ TASK's stack with argument vector ARGV of length ARGC whose
+ strings are STRINGS. STRINGS has length STRINGLEN.
+ Return 0 for success, non-zero otherwise. */
+int boot_script_exec_cmd (mach_port_t task, char *path, int argc,
+ char **argv, char *strings, int stringlen);
+
+/* The user must define this function. Load the contents of FILE
+ into a fresh anonymous memory object and return the memory object port. */
+mach_port_t boot_script_read_file (const char *file);
+
+/* Parse the command line LINE. This causes the command line to be
+ converted into an internal format. Returns 0 for success, non-zero
+ otherwise.
+
+ NOTE: The parser writes into the line so it must not be a string constant.
+ It is also the responsibility of the caller not to deallocate the line
+ across calls to the parser. */
+int boot_script_parse_line (char *cmdline);
+
+/* Execute the command lines prevously parsed.
+ Returns 0 for success, non-zero otherwise. */
+int boot_script_exec (void);
+
+/* Create an entry in the symbol table for variable NAME,
+ whose type is TYPE and value is VAL. Returns 0 on success,
+ non-zero otherwise. */
+int boot_script_set_variable (const char *name, int type, int val);
+
+/* Define the function NAME, which will return type RET_TYPE. */
+int boot_script_define_function (const char *name, int ret_type,
+ int (*func) (const struct cmd *cmd, int *val));
+
+/* Returns a string describing the error ERR. */
+char *boot_script_error_string (int err);
+
+
+void safe_gets (char *, int);
diff --git a/boot/frank1.ld b/boot/frank1.ld
new file mode 100644
index 00000000..9de827ae
--- /dev/null
+++ b/boot/frank1.ld
@@ -0,0 +1,94 @@
+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
new file mode 100644
index 00000000..413953ef
--- /dev/null
+++ b/boot/frankemul.ld
@@ -0,0 +1,107 @@
+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
new file mode 100644
index 00000000..0469424e
--- /dev/null
+++ b/boot/mach-crt0.c
@@ -0,0 +1,158 @@
+/*
+ * 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/sigvec.S b/boot/sigvec.S
new file mode 100644
index 00000000..cc7bb94e
--- /dev/null
+++ b/boot/sigvec.S
@@ -0,0 +1,23 @@
+#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
new file mode 100644
index 00000000..a04ab28d
--- /dev/null
+++ b/boot/syscall.S
@@ -0,0 +1,35 @@
+/* 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/tcattr.c b/boot/tcattr.c
new file mode 100644
index 00000000..fcd3293e
--- /dev/null
+++ b/boot/tcattr.c
@@ -0,0 +1,592 @@
+/* Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include <stddef.h>
+#include <termios.h>
+
+#undef B0
+#undef B50
+#undef B75
+#undef B110
+#undef B134
+#undef B150
+#undef B200
+#undef B300
+#undef B600
+#undef B1200
+#undef B1800
+#undef B2400
+#undef B4800
+#undef B9600
+#undef B19200
+#undef B38400
+#undef EXTA
+#undef EXTB
+#undef ECHO
+#undef TOSTOP
+#undef NOFLSH
+#undef MDMBUF
+#undef FLUSHO
+#undef PENDIN
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+#undef CERASE
+#undef CKILL
+#undef CINTR
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CEOF
+#undef CEOT
+#undef CBRK
+#undef CSUSP
+#undef CDSUSP
+#undef CRPRNT
+#undef CFLUSH
+#undef CWERASE
+#undef CLNEXT
+#undef CSTATUS
+
+#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 TIOCSETP _IOW('t', 9,struct sgttyb)/* set parameters -- stty */
+#define TIOCFLUSH _IOW('t', 16, int) /* flush buffers */
+#define TIOCSETC _IOW('t',17,struct tchars)/* set special characters */
+#define TIOCGETC _IOR('t',18,struct tchars)/* get special characters */
+#define TANDEM 0x00000001 /* send stopc on out q full */
+#define CBREAK 0x00000002 /* half-cooked mode */
+#define LCASE 0x00000004 /* simulate lower case */
+#define ECHO 0x00000008 /* echo input */
+#define CRMOD 0x00000010 /* map \r to \r\n on output */
+#define RAW 0x00000020 /* no i/o processing */
+#define ODDP 0x00000040 /* get/send odd parity */
+#define EVENP 0x00000080 /* get/send even parity */
+#define ANYP 0x000000c0 /* get any parity/send none */
+#define PRTERA 0x00020000 /* \ ... / erase */
+#define CRTERA 0x00040000 /* " \b " to wipe out char */
+#define TILDE 0x00080000 /* hazeltine tilde kludge */
+#define MDMBUF 0x00100000 /* start/stop output on carrier intr */
+#define LITOUT 0x00200000 /* literal output */
+#define TOSTOP 0x00400000 /* SIGSTOP on background output */
+#define FLUSHO 0x00800000 /* flush output to terminal */
+#define NOHANG 0x01000000 /* no SIGHUP on carrier drop */
+#define L001000 0x02000000
+#define CRTKIL 0x04000000 /* kill line with " \b " */
+#define PASS8 0x08000000
+#define CTLECH 0x10000000 /* echo control chars as ^X */
+#define PENDIN 0x20000000 /* tp->t_rawq needs reread */
+#define DECCTQ 0x40000000 /* only ^Q starts after ^S */
+#define NOFLSH 0x80000000 /* no output flush on signal */
+#define TIOCLSET _IOW('t', 125, int) /* set entire local mode word */
+#define TIOCLGET _IOR('t', 124, int) /* get local modes */
+#define LCRTBS (CRTBS>>16)
+#define LPRTERA (PRTERA>>16)
+#define LCRTERA (CRTERA>>16)
+#define LTILDE (TILDE>>16)
+#define LMDMBUF (MDMBUF>>16)
+#define LLITOUT (LITOUT>>16)
+#define LTOSTOP (TOSTOP>>16)
+#define LFLUSHO (FLUSHO>>16)
+#define LNOHANG (NOHANG>>16)
+#define LCRTKIL (CRTKIL>>16)
+#define LPASS8 (PASS8>>16)
+#define LCTLECH (CTLECH>>16)
+#define LPENDIN (PENDIN>>16)
+#define LDECCTQ (DECCTQ>>16)
+#define LNOFLSH (NOFLSH>>16)
+#define TIOCSLTC _IOW('t',117,struct ltchars)/* set local special chars */
+#define TIOCGLTC _IOR('t',116,struct ltchars)/* get local special chars */
+
+
+#if defined(TIOCGETC) || defined(TIOCSETC)
+/* Type of ARG for TIOCGETC and TIOCSETC requests. */
+struct tchars
+{
+ char t_intrc; /* Interrupt character. */
+ char t_quitc; /* Quit character. */
+ char t_startc; /* Start-output character. */
+ char t_stopc; /* Stop-output character. */
+ char t_eofc; /* End-of-file character. */
+ char t_brkc; /* Input delimiter character. */
+};
+
+#define _IOT_tchars /* Hurd ioctl type field. */ \
+ _IOT (_IOTS (char), 6, 0, 0, 0, 0)
+#endif
+
+#if defined(TIOCGLTC) || defined(TIOCSLTC)
+/* Type of ARG for TIOCGLTC and TIOCSLTC requests. */
+struct ltchars
+{
+ char t_suspc; /* Suspend character. */
+ char t_dsuspc; /* Delayed suspend character. */
+ char t_rprntc; /* Reprint-line character. */
+ char t_flushc; /* Flush-output character. */
+ char t_werasc; /* Word-erase character. */
+ char t_lnextc; /* Literal-next character. */
+};
+
+#define _IOT_ltchars /* Hurd ioctl type field. */ \
+ _IOT (_IOTS (char), 6, 0, 0, 0, 0)
+#endif
+
+/* Type of ARG for TIOCGETP and TIOCSETP requests (and gtty and stty). */
+struct sgttyb
+{
+ char sg_ispeed; /* Input speed. */
+ char sg_ospeed; /* Output speed. */
+ char sg_erase; /* Erase character. */
+ char sg_kill; /* Kill character. */
+ short int sg_flags; /* Mode flags. */
+};
+
+
+
+
+const speed_t __bsd_speeds[] =
+ {
+ 0,
+ 50,
+ 75,
+ 110,
+ 134,
+ 150,
+ 200,
+ 300,
+ 600,
+ 1200,
+ 1800,
+ 2400,
+ 4800,
+ 9600,
+ 19200,
+ 38400,
+ };
+
+extern int ioctl ();
+
+/* Set the state of FD to *TERMIOS_P. */
+int
+tcsetattr (int fd, int optional_actions, const struct termios *termios_p)
+{
+ struct sgttyb buf;
+ struct tchars tchars;
+ struct ltchars ltchars;
+ int local;
+#ifdef TIOCGETX
+ int extra;
+#endif
+ size_t i;
+
+ if (ioctl(fd, TIOCGETP, &buf) < 0 ||
+ ioctl(fd, TIOCGETC, &tchars) < 0 ||
+ ioctl(fd, TIOCGLTC, &ltchars) < 0 ||
+#ifdef TIOCGETX
+ ioctl(fd, TIOCGETX, &extra) < 0 ||
+#endif
+ ioctl(fd, TIOCLGET, &local) < 0)
+ return -1;
+
+ if (termios_p == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ buf.sg_ispeed = buf.sg_ospeed = -1;
+ for (i = 0; i <= sizeof (__bsd_speeds) / sizeof (__bsd_speeds[0]); ++i)
+ {
+ if (__bsd_speeds[i] == termios_p->__ispeed)
+ buf.sg_ispeed = i;
+ if (__bsd_speeds[i] == termios_p->__ospeed)
+ buf.sg_ospeed = i;
+ }
+ if (buf.sg_ispeed == -1 || buf.sg_ospeed == -1)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ buf.sg_flags &= ~(CBREAK|RAW);
+ if (!(termios_p->c_lflag & ICANON))
+ buf.sg_flags |= (termios_p->c_cflag & ISIG) ? CBREAK : RAW;
+#ifdef LPASS8
+ if (termios_p->c_oflag & CS8)
+ local |= LPASS8;
+ else
+ local &= ~LPASS8;
+#endif
+ if (termios_p->c_lflag & _NOFLSH)
+ local |= LNOFLSH;
+ else
+ local &= ~LNOFLSH;
+ if (termios_p->c_oflag & OPOST)
+ local &= ~LLITOUT;
+ else
+ local |= LLITOUT;
+#ifdef TIOCGETX
+ if (termios_p->c_lflag & ISIG)
+ extra &= ~NOISIG;
+ else
+ extra |= NOISIG;
+ if (termios_p->c_cflag & CSTOPB)
+ extra |= STOPB;
+ else
+ extra &= ~STOPB;
+#endif
+ if (termios_p->c_iflag & ICRNL)
+ buf.sg_flags |= CRMOD;
+ else
+ buf.sg_flags &= ~CRMOD;
+ if (termios_p->c_iflag & IXOFF)
+ buf.sg_flags |= TANDEM;
+ else
+ buf.sg_flags &= ~TANDEM;
+
+ buf.sg_flags &= ~(ODDP|EVENP);
+ if (!(termios_p->c_cflag & PARENB))
+ buf.sg_flags |= ODDP | EVENP;
+ else if (termios_p->c_cflag & PARODD)
+ buf.sg_flags |= ODDP;
+ else
+ buf.sg_flags |= EVENP;
+
+ if (termios_p->c_lflag & _ECHO)
+ buf.sg_flags |= ECHO;
+ else
+ buf.sg_flags &= ~ECHO;
+ if (termios_p->c_lflag & ECHOE)
+ local |= LCRTERA;
+ else
+ local &= ~LCRTERA;
+ if (termios_p->c_lflag & ECHOK)
+ local |= LCRTKIL;
+ else
+ local &= ~LCRTKIL;
+ if (termios_p->c_lflag & _TOSTOP)
+ local |= LTOSTOP;
+ else
+ local &= ~LTOSTOP;
+
+ buf.sg_erase = termios_p->c_cc[VERASE];
+ buf.sg_kill = termios_p->c_cc[VKILL];
+ tchars.t_eofc = termios_p->c_cc[VEOF];
+ tchars.t_intrc = termios_p->c_cc[VINTR];
+ tchars.t_quitc = termios_p->c_cc[VQUIT];
+ ltchars.t_suspc = termios_p->c_cc[VSUSP];
+ tchars.t_startc = termios_p->c_cc[VSTART];
+ tchars.t_stopc = termios_p->c_cc[VSTOP];
+
+ if (ioctl(fd, TIOCSETP, &buf) < 0 ||
+ ioctl(fd, TIOCSETC, &tchars) < 0 ||
+ ioctl(fd, TIOCSLTC, &ltchars) < 0 ||
+#ifdef TIOCGETX
+ ioctl(fd, TIOCSETX, &extra) < 0 ||
+#endif
+ ioctl(fd, TIOCLSET, &local) < 0)
+ return -1;
+ return 0;
+}
+
+
+#undef tcgetattr
+
+/* Put the state of FD into *TERMIOS_P. */
+int
+tcgetattr (int fd, struct termios *termios_p)
+{
+ struct sgttyb buf;
+ struct tchars tchars;
+ struct ltchars ltchars;
+ int local;
+#ifdef TIOCGETX
+ int extra;
+#endif
+
+ if (termios_p == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (ioctl(fd, TIOCGETP, &buf) < 0 ||
+ ioctl(fd, TIOCGETC, &tchars) < 0 ||
+ ioctl(fd, TIOCGLTC, &ltchars) < 0 ||
+#ifdef TIOCGETX
+ ioctl(fd, TIOCGETX, &extra) < 0 ||
+#endif
+ ioctl(fd, TIOCLGET, &local) < 0)
+ return -1;
+
+ termios_p->__ispeed = __bsd_speeds[(unsigned char) buf.sg_ispeed];
+ termios_p->__ospeed = __bsd_speeds[(unsigned char) buf.sg_ospeed];
+
+ termios_p->c_iflag = 0;
+ termios_p->c_oflag = 0;
+ termios_p->c_cflag = 0;
+ termios_p->c_lflag = 0;
+ termios_p->c_oflag |= CREAD | HUPCL;
+#ifdef LPASS8
+ if (local & LPASS8)
+ termios_p->c_oflag |= CS8;
+ else
+#endif
+ termios_p->c_oflag |= CS7;
+ if (!(buf.sg_flags & RAW))
+ {
+ termios_p->c_iflag |= IXON;
+ termios_p->c_cflag |= OPOST;
+#ifndef NOISIG
+ termios_p->c_lflag |= ISIG;
+#endif
+ }
+ if ((buf.sg_flags & (CBREAK|RAW)) == 0)
+ termios_p->c_lflag |= ICANON;
+ if (!(buf.sg_flags & RAW) && !(local & LLITOUT))
+ termios_p->c_oflag |= OPOST;
+ if (buf.sg_flags & CRMOD)
+ termios_p->c_iflag |= ICRNL;
+ if (buf.sg_flags & TANDEM)
+ termios_p->c_iflag |= IXOFF;
+#ifdef TIOCGETX
+ if (!(extra & NOISIG))
+ termios_p->c_lflag |= ISIG;
+ if (extra & STOPB)
+ termios_p->c_cflag |= CSTOPB;
+#endif
+
+ switch (buf.sg_flags & (EVENP|ODDP))
+ {
+ case EVENP|ODDP:
+ break;
+ case ODDP:
+ termios_p->c_cflag |= PARODD;
+ default:
+ termios_p->c_cflag |= PARENB;
+ termios_p->c_iflag |= IGNPAR | INPCK;
+ break;
+ }
+ if (buf.sg_flags & ECHO)
+ termios_p->c_lflag |= _ECHO;
+ if (local & LCRTERA)
+ termios_p->c_lflag |= ECHOE;
+ if (local & LCRTKIL)
+ termios_p->c_lflag |= ECHOK;
+ if (local & LTOSTOP)
+ termios_p->c_lflag |= _TOSTOP;
+ if (local & LNOFLSH)
+ termios_p->c_lflag |= _NOFLSH;
+
+ termios_p->c_cc[VEOF] = tchars.t_eofc;
+ termios_p->c_cc[VEOL] = '\n';
+ termios_p->c_cc[VERASE] = buf.sg_erase;
+ termios_p->c_cc[VKILL] = buf.sg_kill;
+ termios_p->c_cc[VINTR] = tchars.t_intrc;
+ termios_p->c_cc[VQUIT] = tchars.t_quitc;
+ termios_p->c_cc[VSTART] = tchars.t_startc;
+ termios_p->c_cc[VSTOP] = tchars.t_stopc;
+ termios_p->c_cc[VSUSP] = ltchars.t_suspc;
+ termios_p->c_cc[VMIN] = -1;
+ termios_p->c_cc[VTIME] = -1;
+
+ return 0;
+}
diff --git a/boot/ux.c b/boot/ux.c
new file mode 100644
index 00000000..b532f19e
--- /dev/null
+++ b/boot/ux.c
@@ -0,0 +1,303 @@
+/* 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 <cthreads.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 spin_lock_t free_reply_ports_lock = SPIN_LOCK_INITIALIZER;
+
+mach_port_t __mig_get_reply_port ()
+{
+ spin_lock (&free_reply_ports_lock);
+ if (free_reply_ports == NULL)
+ {
+ 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;
+ 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;
+ spin_lock (&free_reply_ports_lock);
+ frp->next = free_reply_ports;
+ free_reply_ports = frp;
+ 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
new file mode 100644
index 00000000..d3787c54
--- /dev/null
+++ b/boot/ux.h
@@ -0,0 +1,114 @@
+/* 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;