cvs diff: Diffing .
Index: GNUmakerules
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/GNUmakerules,v
retrieving revision 1.14.2.1
retrieving revision 1.14.2.2
diff -c -r1.14.2.1 -r1.14.2.2
*** GNUmakerules	1998/03/14 03:15:24	1.14.2.1
--- GNUmakerules	1998/03/14 04:14:45	1.14.2.2
***************
*** 44,49 ****
--- 44,53 ----
  	-loskit_memdebug -loskit_c -loskit_lmm
  DEPENDLIBS = $(filter %.a, $(foreach DIR,$(LIBDIRS),$(wildcard $(DIR)/*)))
  
+ ## Debugging hint: set the -Ttext to 3MB or so so you can run GDB and
+ ## trace through the booted kernel (which presumably loads lower than
+ ## 3MB).  Also, you can use the GDB `symbol-file' command to load the booted
+ ## kernel's symbols once you get inside of it.
  netboot: $(OBJDIR)/lib/multiboot.o $(OBJFILES) $(DEPENDLIBS) $(OBJDIR)/lib/crtn.o
  	$(LD) -o $@ -Ttext 100000 -n $(LDFLAGS) $(OSKIT_LDFLAGS) \
  		$(OBJDIR)/lib/multiboot.o \
Index: NEWS
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/NEWS,v
retrieving revision 1.3.2.1
retrieving revision 1.3.2.2
diff -c -r1.3.2.1 -r1.3.2.2
*** NEWS	1998/03/14 03:15:25	1.3.2.1
--- NEWS	1998/03/14 04:16:05	1.3.2.2
***************
*** 15,17 ****
--- 15,26 ----
  	  This simplifies the code and will enable us to work on Linux
  	  in the future.
  
+ 2.01 -> 2.02
+ 	- Made it boot multiboot kernels now, not BSD ones.
+ 	  This is mainly so we can pass them arbitrary command lines, which
+ 	  will eventually include a "return address" so we can regain control
+ 	  after the booted kernel exits.
+ 	  A disadvantage is that thre isn't a multiboot-boot-adaptor yet, so
+ 	  we can't glob a bunch of bmods together into a multiboot image like
+ 	  we can for BSD images.
+ 	- Various cleanup, bugfixes, and reorganization
Index: await.c
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/await.c,v
retrieving revision 1.10.2.1
retrieving revision 1.10.2.2
diff -c -r1.10.2.1 -r1.10.2.2
*** await.c	1998/03/14 03:15:25	1.10.2.1
--- await.c	1998/03/14 04:14:45	1.10.2.2
***************
*** 17,23 ****
  #include "rpc.h"			/* rpc_t */
  #include "netboot.h"			/* TIMEOUT */
  #include "timer.h"			/* currticks */
- #include "boot.h"			/* kerninfo */
  
  #include "await.h"			/* AWAIT_foo */
  
--- 17,22 ----
Index: boot.h
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/boot.h,v
retrieving revision 1.7
retrieving revision 1.7.2.1
diff -c -r1.7 -r1.7.2.1
*** boot.h	1997/10/21 00:06:27	1.7
--- boot.h	1998/03/14 04:14:45	1.7.2.1
***************
*** 21,57 ****
  #ifndef __BOOT_H_INCLUDED__
  #define __BOOT_H_INCLUDED__
  
! #include <oskit/types.h>		/* oskit_ */
! #include "rpc.h"			/* NFS_ */
  
  struct kerninfo {
! 	union {
! 		struct {
! 			char		*dirname;		/* directory to mount */
! 			unsigned char	dirfh[NFS_FHSIZE];	/* file handle of dir */
! 			char		*name;			/* file in dirname */
! 			unsigned char	fh[NFS_FHSIZE];		/* file handle */
! 		} N;
! 		struct {
! 			/* disk stuff */
! 		} D;
! 	} u;
! #define ki_dirname	u.N.dirname
! #define ki_dirfh	u.N.dirfh
! #define ki_name		u.N.name
! #define ki_fh		u.N.fh
! 
! 	void		*ki_imgaddr;	/* where it is in memory */
! 	int		ki_imgsize;	/* how big image is (NOT file size) */
! 
! 	/* These two are always the same right now. */
! 	oskit_addr_t	ki_ldaddr;	/* load address */
! 	oskit_addr_t	ki_entry;	/* entry point */
  };
  
! int getkernel_net(unsigned long myip, unsigned long srvip, unsigned long gwip,
! 		  unsigned long netmask, char *myhostname,
! 		  struct kerninfo *ki /* IN/OUT */);
! void loadkernel(struct kerninfo *kinfo);
  
  #endif /* __BOOT_H_INCLUDED__ */
--- 21,45 ----
  #ifndef __BOOT_H_INCLUDED__
  #define __BOOT_H_INCLUDED__
  
! #include <oskit/x86/multiboot.h>	/* multiboot_header */
! #include <oskit/c/netinet/in.h>		/* in_addr */
  
  struct kerninfo {
! 	struct in_addr ki_ip;		/* ip of server host, in host order */
! 	char *ki_dirname;		/* dir to mount */
! 	char *ki_filename;		/* file within dir */
! 
! 	struct multiboot_header ki_mbhdr; /* things like load address, entry */
! 
! 	void *ki_imgaddr;		  /* where it is in memory */
! 
! 	struct multiboot_info *ki_mbinfo;  /* stuff we are passing to it */
  };
+ 
+ #define kerninfo_imagesize(ki)	(phystokv((ki)->ki_mbhdr.bss_end_addr) \
+ 				 - phystokv((ki)->ki_mbhdr.load_addr))
  
! int getkernel_net(struct kerninfo *ki /* IN/OUT */);
! void loadkernel(struct kerninfo *ki);
  
  #endif /* __BOOT_H_INCLUDED__ */
Index: bootinfo.h
===================================================================
RCS file: bootinfo.h
diff -N bootinfo.h
*** /tmp/cvs011255	Tue Mar  9 00:59:11 1999
--- /dev/null	Mon Mar  8 14:37:46 1999
***************
*** 1,69 ****
- /*-
-  * Copyright (C) 1994 by Rodney W. Grimes, Milwaukie, Oregon  97222
-  * All rights reserved.
-  *
-  * Redistribution and use in source and binary forms, with or without
-  * modification, are permitted provided that the following conditions
-  * are met:
-  * 1. Redistributions of source code must retain the above copyright
-  *    notice, this list of conditions and the following disclaimer as
-  *    the first lines of this file unmodified.
-  * 2. Redistributions in binary form must reproduce the above copyright
-  *    notice, this list of conditions and the following disclaimer in the
-  *    documentation and/or other materials provided with the distribution.
-  * 3. All advertising materials mentioning features or use of this software
-  *    must display the following acknowledgement:
-  *	This product includes software developed by Rodney W. Grimes.
-  * 4. The name of the author may not be used to endorse or promote products
-  *    derived from this software without specific prior written permission.
-  *
-  * THIS SOFTWARE IS PROVIDED BY RODNEY W. GRIMES ``AS IS'' AND
-  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  * ARE DISCLAIMED.  IN NO EVENT SHALL RODNEY W. GRIMES BE LIABLE
-  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-  * SUCH DAMAGE.
-  *
-  *	$\Id: bootinfo.h,v 1.5 1995/05/30 08:00:26 rgrimes Exp $
-  */
- 
- #ifndef	_MACHINE_BOOTINFO_H_
- #define	_MACHINE_BOOTINFO_H_
- 
- /* Only change the version number if you break compatibility. */
- #define	BOOTINFO_VERSION	1
- 
- #define	N_BIOS_GEOM		8
- 
- /*
-  * A zero bootinfo field often means that there is no info available.
-  * Flags are used to indicate the validity of fields where zero is a
-  * normal value.
-  */
- struct bootinfo {
- 	unsigned int		bi_version;
- 	unsigned char		*bi_kernelname;
- 	struct nfs_diskless	*bi_nfs_diskless;
- 				/* End of fields that are always present. */
- #define	bi_endcommon		bi_n_bios_used
- 	unsigned int		bi_n_bios_used;
- 	unsigned long		bi_bios_geom[N_BIOS_GEOM];
- 	unsigned int		bi_size;
- 	unsigned char		bi_memsizes_valid;
- 	unsigned char		bi_pad[3];
- 	unsigned long		bi_basemem;
- 	unsigned long		bi_extmem;
- 	unsigned long		bi_symtab;
- 	unsigned long		bi_esymtab;
- };
- 
- #ifdef KERNEL
- extern struct bootinfo	bootinfo;
- #endif
- 
- #endif	/* !_MACHINE_BOOTINFO_H_ */
--- 0 ----
Index: boottype.h
===================================================================
RCS file: boottype.h
diff -N boottype.h
*** /tmp/cvs011255	Tue Mar  9 00:59:11 1999
--- /dev/null	Mon Mar  8 14:37:46 1999
***************
*** 1,34 ****
- /* 
-  * Copyright (c) 1995,1996,1997 The University of Utah and
-  * the Computer Systems Laboratory at the University of Utah (CSL).
-  * All rights reserved.
-  *
-  * Permission to use, copy, modify and distribute this software is hereby
-  * granted provided that (1) source code retains these copyright, permission,
-  * and disclaimer notices, and (2) redistributions including binaries
-  * reproduce the notices in supporting documentation, and (3) all advertising
-  * materials mentioning features or use of this software display the following
-  * acknowledgement: ``This product includes software developed by the
-  * Computer Systems Laboratory at the University of Utah.''
-  *
-  * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
-  * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
-  * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
-  *
-  * CSL requests users of this software to return to csl-dist@cs.utah.edu any
-  * improvements that they make and grant CSL redistribution rights.
-  */
- 
- #ifndef _BOOT_BSD_BOOTTYPE_H_
- #define _BOOT_BSD_BOOTTYPE_H_
- 
- #define BOOTTYPE_MACH		0
- #define BOOTTYPE_OLDBSD		1
- #define BOOTTYPE_NEWBSD		2
- 
- #ifndef ASSEMBLER
- extern int boottype;
- extern unsigned long boothowto, bootdev;
- #endif
- 
- #endif /* _BOOT_BSD_BOOTTYPE_H_ */
--- 0 ----
Index: do_boot.S
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/do_boot.S,v
retrieving revision 1.4.2.1
retrieving revision 1.4.2.2
diff -c -r1.4.2.1 -r1.4.2.2
*** do_boot.S	1998/03/14 03:15:26	1.4.2.1
--- do_boot.S	1998/03/14 04:14:46	1.4.2.2
***************
*** 24,34 ****
   */
  
  #include <oskit/machine/asm.h>
- #define NODEV -1		/* see freebsd <sys/param.h> */
  
- 	.globl  EXT(boothowto), EXT(bsdbootinfo)
- 	.globl	EXT(kernel_tempstack)
- 
  	.text
  
  /*
--- 24,30 ----
***************
*** 36,41 ****
--- 32,38 ----
   *	%esi	where kernel is
   *	%edi	where kernel wants to be
   *	%ecx	how big kernel is
+  *	%ebx	addr of multiboot_info struct
   *	%edx	segment we should switch to
   */
  ENTRY(do_boot)
***************
*** 44,73 ****
  	movw	%dx,%es
  	movw	%dx,%fs
  	movw	%dx,%gs
- 
- 	/* 
- 	 * Switch to a new stack since the old one will get trashed
- 	 * when we copy the new image in.
- 	 */
  	movw	%dx,%ss
- 	movl	EXT(kernel_tempstack),%esp
- 	
- 	/*
- 	 * Push the kernel args before we copy and trash "boothowto" etc.
- 	 * We call the kernel like this:
- 	 *	(%eax)(boothowto, bootdev, 0, 0, 0, bsdbootinfo)
- 	 * That is what BSD expects.
- 	 */
- 	pushl	EXT(bsdbootinfo)
- 	pushl	$0
- 	pushl	$0
- 	pushl	$0
- 	pushl	$NODEV
- 	pushl	EXT(boothowto)
  
- 	/* Copy the new kernel and jump in. */
  	rep
  	movsb
! 	call	*%eax
  ENTRY(do_boot_end)
  
--- 41,51 ----
  	movw	%dx,%es
  	movw	%dx,%fs
  	movw	%dx,%gs
  	movw	%dx,%ss
  
  	rep
  	movsb
! 
! 	jmp	*%eax
  ENTRY(do_boot_end)
  
Index: getkernel_net.c
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/getkernel_net.c,v
retrieving revision 1.7
retrieving revision 1.7.2.1
diff -c -r1.7 -r1.7.2.1
*** getkernel_net.c	1998/02/05 04:20:48	1.7
--- getkernel_net.c	1998/03/14 04:14:47	1.7.2.1
***************
*** 18,31 ****
   * CSL requests users of this software to return to csl-dist@cs.utah.edu any
   * improvements that they make and grant CSL redistribution rights.
   */
  #include <oskit/x86/base_vm.h>		/* phystokv */
  #include <oskit/x86/types.h>		/* oskit_addr_t */
! 
! #include <oskit/c/malloc.h>		/* malloc_lmm */
  #include <oskit/c/stdio.h>		/* printf */
  #include <oskit/c/assert.h>		/* assert */
  #include <oskit/exec/exec.h>		/* exec_load */
- #include <oskit/lmm.h>			/* lmm_remove_free */
  
  #include "netboot.h"			/* NFS_READ_SIZE */
  #include "ether.h"			/* ARP_ */
--- 18,31 ----
   * CSL requests users of this software to return to csl-dist@cs.utah.edu any
   * improvements that they make and grant CSL redistribution rights.
   */
+ 
  #include <oskit/x86/base_vm.h>		/* phystokv */
  #include <oskit/x86/types.h>		/* oskit_addr_t */
! #include <oskit/x86/pc/phys_lmm.h>	/* phys_mem_max */
  #include <oskit/c/stdio.h>		/* printf */
  #include <oskit/c/assert.h>		/* assert */
+ #include <oskit/c/malloc.h>		/* mustcalloc */
  #include <oskit/exec/exec.h>		/* exec_load */
  
  #include "netboot.h"			/* NFS_READ_SIZE */
  #include "ether.h"			/* ARP_ */
***************
*** 33,47 ****
  
  #include "boot.h"
  
! #ifndef min
  #define min(a,b)	((a) < (b)? (a) : (b))
- #endif
  
  /*
   * Callback to read the kernel image from its src, in this case NFS.
   */
  static int
! kimg_read(void *port,
  	  oskit_addr_t file_ofs, void *buf, oskit_size_t size,
  	  oskit_size_t *out_actual)
  {
--- 33,50 ----
  
  #include "boot.h"
  
! #undef min
  #define min(a,b)	((a) < (b)? (a) : (b))
  
+ static int nfs_port;
+ static unsigned char dirfh[NFS_FHSIZE];		/* file handle of dir */
+ static unsigned char filefh[NFS_FHSIZE];	/* file handle of file */
+ 
  /*
   * Callback to read the kernel image from its src, in this case NFS.
   */
  static int
! kimg_read(void *handle_notused,
  	  oskit_addr_t file_ofs, void *buf, oskit_size_t size,
  	  oskit_size_t *out_actual)
  {
***************
*** 56,62 ****
  	offset = file_ofs;
  	while (size > 0) {
  		chunk_size = min(NFS_READ_SIZE, size);
! 		n = nfs_read(ARP_ROOTSERVER, (int)port, kinfo.ki_fh,
  			     offset, chunk_size, bufp);
  		if (n < 0) {
  			printf("Unable to read text: %s\n", nfs_strerror(n));
--- 59,65 ----
  	offset = file_ofs;
  	while (size > 0) {
  		chunk_size = min(NFS_READ_SIZE, size);
! 		n = nfs_read(ARP_ROOTSERVER, nfs_port, filefh,
  			     offset, chunk_size, bufp);
  		if (n < 0) {
  			printf("Unable to read text: %s\n", nfs_strerror(n));
***************
*** 75,209 ****
  }
  
  /*
!  * Callback to figure out how big the kernel is.
   */
  static int
! kimg_load_1(void *handle,
! 	    oskit_addr_t file_ofs, oskit_size_t file_size,
! 	    oskit_addr_t mem_addr, oskit_size_t mem_size,
! 	    exec_sectype_t section_type)
  {
  #if 0
! 	printf("** 1: file_ofs %x, file_size %x\n", file_ofs, file_size);
! 	printf("-- 1: mem_addr %x, mem_size %x\n", mem_addr, mem_size);
! 	printf("-- 1: sectype = %b\n", section_type, EXEC_SECTYPE_FORMAT);
  #endif
  
          if (!(section_type & EXEC_SECTYPE_ALLOC))
                  return 0;
  
! 	/* We incr by mem_size since we want to include the BSS. */
! 	kinfo.ki_imgsize += mem_size;
  
!         return 0;
  }
  
  /*
!  * Callback to load the kernel for real.
!  * Needs to read file_size bytes from handle at file_ofs and place it
!  * in mem_addr.
!  * If mem_size is greater than file_size, the remaining bytes are
!  * zeroed.
   */
  static int
! kimg_load_2(void *handle,
! 	    oskit_addr_t file_ofs, oskit_size_t file_size,
! 	    oskit_addr_t mem_addr, oskit_size_t mem_size,
! 	    exec_sectype_t section_type)
  {
! 	static int offset = 0;
! 	oskit_size_t got;
! 	int err;
  
  #if 0
! 	printf("** 2: file_ofs %x, file_size %x\n", file_ofs, file_size);
! 	printf("-- 2: mem_addr %x, mem_size %x\n", mem_addr, mem_size);
! 	printf("-- 2: sectype = %b\n", section_type, EXEC_SECTYPE_FORMAT);
  #endif
  
!         if (!(section_type & EXEC_SECTYPE_ALLOC))
!                 return 0;
  
! 	if ((err = kimg_read(handle, file_ofs, kinfo.ki_imgaddr + offset,
! 			     file_size, &got)) != 0)
! 		return err;
! 	if (got != file_size)
! 		return EX_CORRUPT;
! 	offset += mem_size;
  
  	return 0;
  }
  
  /*
!  * Get the kernel and put it somewhere (not its final position.)
!  * The kerninfo struct we get passed has the ki_dirname and ki_name
   * members filled in.
!  * We fill in the rest.
   */
  int
! getkernel_net(unsigned long myip, unsigned long srvip, unsigned long gwip,
! 	      unsigned long netmask, char *myhostname,
! 	      struct kerninfo *ki /* IN/OUT */)
  {
  	int err;
  	exec_info_t xinfo;
! 	int root_nfs_port;
! 	int root_mount_port;
  
  	assert(ki->ki_dirname);
! 	assert(ki->ki_name);
  
! 	/* Lookup NFS/MOUNTD ports for ROOT using PORTMAP */
! 	root_nfs_port = rpc_lookup(ARP_ROOTSERVER, PROG_NFS, 2);
! 	root_mount_port = rpc_lookup(ARP_ROOTSERVER, PROG_MOUNT, 1);
! 	if ((root_nfs_port == -1) || (root_mount_port == -1)) {
! 		printf("Unable to get root NFS/MOUNT ports\n");
! 		return 0;
  	}
  
  	printf("Mounting %s...\n", ki->ki_dirname);
! 	err = nfs_mount(ARP_ROOTSERVER, root_mount_port,
! 			ki->ki_dirname, ki->ki_dirfh);
  	if (err) {
! 		printf("Can't mount ROOT filesystem: %s\n", nfs_strerror(err));
! 		return 0;
  	}
  
! 	printf("Looking up %s...\n", ki->ki_name);
! 	err = nfs_lookup(ARP_ROOTSERVER, root_nfs_port, ki->ki_dirfh,
! 			 (*ki->ki_name == '/') ? ki->ki_name+1 : ki->ki_name,
! 			 ki->ki_fh);
  	if (err) {
! 		netprintf("Can't lookup %s: %s\n", ki->ki_name, nfs_strerror(err));
! 		return 0;
  	}
  
  	/*
! 	 * First figure out how big the thing is, then load it all at once.
  	 */
! 	printf("Loading %s...\n", ki->ki_name);
  
! 	if ((err = exec_load(kimg_read, kimg_load_1, (void *)root_nfs_port,
! 			     &xinfo)) != 0) {
! 		printf("cannot load kernel image 1: %s\n", exec_strerror(err));
! 		return 0;
  	}
  
! 	/* We assume the entry is the same as the lowest text addr. */
! 	xinfo.entry &= 0x00FFFFFF;
! 	ki->ki_ldaddr = xinfo.entry;
! 	ki->ki_entry = xinfo.entry;
! 
! 	/* Reserve the memory where the kernel will eventually reside. */
! 	lmm_remove_free(&malloc_lmm,
! 			(void *)phystokv(ki->ki_ldaddr), ki->ki_imgsize);
! 
! 	ki->ki_imgaddr = mustcalloc(ki->ki_imgsize, 1);
! 	if ((err = exec_load(kimg_read, kimg_load_2, (void *)root_nfs_port,
! 			     &xinfo)) != 0) {
! 		printf("cannot load kernel image 2: %s\n", exec_strerror(err));
! 		return 0;
  	}
  
! 	return 1;			/* yay */
  }
--- 78,301 ----
  }
  
  /*
!  * Callback to load the kernel for real.
!  * Copies data from the NFS file into ki->ki_imgaddr.
   */
  static int
! kimg_load(void *handle,
! 	  oskit_addr_t file_ofs, oskit_size_t file_size,
! 	  oskit_addr_t mem_addr, oskit_size_t mem_size,
! 	  exec_sectype_t section_type)
  {
+ 	struct kerninfo *ki = handle;
+ 	oskit_size_t got;
+ 	int err;
+ 
  #if 0
! 	printf("** load: file_ofs %x, file_size %x\n", file_ofs, file_size);
! 	printf("-- load: mem_addr %x, mem_size %x\n", mem_addr, mem_size);
! 	printf("-- load: sectype = %b\n", section_type, EXEC_SECTYPE_FORMAT);
  #endif
  
          if (!(section_type & EXEC_SECTYPE_ALLOC))
                  return 0;
  
! 	if ((err = kimg_read(ki, file_ofs,
! 			     ki->ki_imgaddr + mem_addr - ki->ki_mbhdr.load_addr,
! 			     file_size, &got)) != 0)
! 		return err;
! 	if (got != file_size)
! 		return EX_CORRUPT;
  
! 	return 0;
  }
  
  /*
!  * Callback for the exec library that just tallys up the sizes.
   */
  static int
! kimg_tally(void *handle,
! 	   oskit_addr_t file_ofs, oskit_size_t file_size,
! 	   oskit_addr_t mem_addr, oskit_size_t mem_size,
! 	   exec_sectype_t section_type)
  {
! 	struct multiboot_header *h = handle;
  
  #if 0
! 	printf("** tally: file_ofs %x, file_size %x\n", file_ofs, file_size);
! 	printf("-- tally: mem_addr %x, mem_size %x\n", mem_addr, mem_size);
! 	printf("-- tally: sectype = %b\n", section_type, EXEC_SECTYPE_FORMAT);
  #endif
  
! 	if (!(section_type & EXEC_SECTYPE_ALLOC))
! 		return 0;
  
! 	assert(mem_size > 0);
! 	if (mem_addr < h->load_addr)
! 		h->load_addr = mem_addr;
! 	if (mem_addr+file_size > h->load_end_addr)
! 		h->load_end_addr = mem_addr+file_size;
! 	if (mem_addr+mem_size > h->bss_end_addr)
! 		h->bss_end_addr = mem_addr+mem_size;
! 
! 	return 0;
! }
! 
! /*
!  * Look in the first MULTIBOOT_SEARCH bytes of the file for the
!  * MultiBoot header and puts it in ki->ki_mbhdr;
!  *
!  * Returns 0 if found, 1 otherwise.
!  */
! static int
! find_multiboot_header(struct kerninfo *ki)
! {
! 	int err;
! 	int offset;
! 	char buf[NFS_READ_SIZE];
! 	oskit_size_t got;
! 	int i;
! 	struct multiboot_header *h;
! 
! 	for (offset = 0; offset < MULTIBOOT_SEARCH; offset += NFS_READ_SIZE) {
! 		err = kimg_read(ki, offset, buf, NFS_READ_SIZE, &got);
! 		if (err)
! 			return 1;
! 		for (i = 0; i < got - sizeof(*h); i += 4) {
! 			h = (struct multiboot_header *)&buf[i];
! 			if (h->magic == MULTIBOOT_MAGIC
! 			    && (h->magic + h->flags + h->checksum) == 0) {
! 				ki->ki_mbhdr = *h;
! 				return 0;
! 			}
! 		}
! 	}
! 	return 1;
! }
  
+ /*
+  * Fills in certain fields of the ki_mbhdr multiboot_header using
+  * the "executable interpreter" library.
+  *
+  * Returns 0 on success, 1 otherwise;
+  */
+ static int
+ fill_in_multiboot_header(struct kerninfo *ki)
+ {
+ 	struct multiboot_header *h = &ki->ki_mbhdr;
+ 	struct exec_info xinfo;
+ 	int err;
+ 
+ 	h->load_addr = 0xffffffff;
+ 	h->load_end_addr = 0;
+ 	h->bss_end_addr = 0;
+ 
+ 	err = exec_load(kimg_read, kimg_tally, &ki->ki_mbhdr, &xinfo);
+ 	if (err) {
+ 		printf("Can't tally sections: %s.\n", exec_strerror(err));
+ 		return 1;
+ 	}
+ 	h->entry = xinfo.entry;
+ 
  	return 0;
  }
  
  /*
!  * Get the kernel and put it somewhere (not its final position).
!  * The kerninfo struct we get passed has the ki_ip, ki_dirname, and ki_filename
   * members filled in.
!  * We fill in the ki_mbhdr and ki_imgaddr parts.
!  *
!  * Returns 0 on success, 1 otherwise.
   */
  int
! getkernel_net(struct kerninfo *ki /* IN/OUT */)
  {
  	int err;
  	exec_info_t xinfo;
! 	int mount_port;
  
  	assert(ki->ki_dirname);
! 	assert(ki->ki_filename);
  
! 	/*
! 	 * Lookup NFS/MOUNTD ports for ROOT using PORTMAP.
! 	 */
! 	nfs_port = rpc_lookup(ARP_ROOTSERVER, PROG_NFS, 2);
! 	mount_port = rpc_lookup(ARP_ROOTSERVER, PROG_MOUNT, 1);
! 	if (nfs_port == -1 || mount_port == -1) {
! 		printf("Can't get root NFS/MOUNT ports.\n");
! 		return 1;
  	}
  
+ 	/*
+ 	 * NFS mount the directory.
+ 	 */
  	printf("Mounting %s...\n", ki->ki_dirname);
! 	err = nfs_mount(ARP_ROOTSERVER, mount_port, ki->ki_dirname, dirfh);
  	if (err) {
! 		printf("Can't mount ROOT filesystem: %s.\n", nfs_strerror(err));
! 		return 1;
  	}
  
! 	/*
! 	 * Lookup the file.
! 	 */
! 	printf("Looking up %s...\n", ki->ki_filename);
! 	err = nfs_lookup(ARP_ROOTSERVER, nfs_port, dirfh, ki->ki_filename,
! 			 filefh);
  	if (err) {
! 		printf("Can't lookup %s: %s.\n",
! 		       ki->ki_filename, nfs_strerror(err));
! 		return 1;
  	}
  
  	/*
! 	 * Look in the file for the MultiBoot header.
  	 */
! 	if (find_multiboot_header(ki) != 0) {
! 		printf("Can't find MultiBoot header in image.\n");
! 		return 1;
! 	}
  
! 	/*
! 	 * Fill in the rest of the MultiBoot header, if needed.
! 	 * Stuff like load address, bss size, etc.
! 	 */
! 	if (! (ki->ki_mbhdr.flags & MULTIBOOT_AOUT_KLUDGE)
! 	    && fill_in_multiboot_header(ki) != 0) {
! 		printf("Can't fill in MultiBoot header.\n");
! 		return 1;
  	}
  
! 	/*
! 	 * Do a bunch of checks on the kernel load ranges.
! 	 */
! 	assert(ki->ki_mbhdr.load_addr < ki->ki_mbhdr.load_end_addr);
! 	assert(ki->ki_mbhdr.load_end_addr < ki->ki_mbhdr.bss_end_addr);
! 	printf("Kernel will be at %08x-%08x text+data %d bss %d\n",
! 		ki->ki_mbhdr.load_addr, ki->ki_mbhdr.bss_end_addr,
! 		ki->ki_mbhdr.load_end_addr - ki->ki_mbhdr.load_addr,
! 		ki->ki_mbhdr.bss_end_addr - ki->ki_mbhdr.load_end_addr);
! 	if (ki->ki_mbhdr.load_addr < 0x1000)
! 		panic("kernel wants to be loaded too low!");
! 	if (ki->ki_mbhdr.bss_end_addr > phys_mem_max)
! 		panic("kernel wants to be loaded beyond available physical memory!");
! 	if ((ki->ki_mbhdr.load_addr < 0x100000)
! 	    && (ki->ki_mbhdr.bss_end_addr > 0xa0000))
! 		panic("kernel wants to be loaded on top of I/O space!");
! 
! 	/*
! 	 * Now, read the whole thing in somewhere.
! 	 * It will be copied into its final resting home later,
! 	 * right before we jump in.
! 	 */
! 	printf("Loading %s...\n", ki->ki_filename);
! 	ki->ki_imgaddr = mustcalloc(kerninfo_imagesize(ki), 1);
! 	if ((err = exec_load(kimg_read, kimg_load, (void *)ki, &xinfo)) != 0) {
! 		printf("Can't load kernel image: %s.\n", exec_strerror(err));
! 		return 1;
  	}
  
! 	return 0;			/* yay */
  }
Index: loadkernel.c
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/loadkernel.c,v
retrieving revision 1.5.2.1
retrieving revision 1.5.2.2
diff -c -r1.5.2.1 -r1.5.2.2
*** loadkernel.c	1998/03/14 03:15:26	1.5.2.1
--- loadkernel.c	1998/03/14 04:14:47	1.5.2.2
***************
*** 27,32 ****
--- 27,33 ----
  #include <oskit/x86/proc_reg.h>		/* cli/sti */
  #include <oskit/x86/base_gdt.h>		/* LINEAR_CS */
  #include <oskit/x86/base_vm.h>		/* kvtophys */
+ #include <oskit/x86/pc/base_multiboot.h> /* multiboot_info_dump */
  #include <oskit/c/malloc.h>		/* mustmalloc */
  #include <oskit/c/string.h>		/* memcpy */
  #include <oskit/c/stdio.h>		/* printf */
***************
*** 36,49 ****
  extern char do_boot[], do_boot_end[];
  
  void
! loadkernel(struct kerninfo *kinfo)
  {
  	oskit_size_t stub_size;
  	void *stub;
  	struct far_pointer_32 ptr;
  	oskit_addr_t copy_source;
  	oskit_size_t copy_size;
  
  	printf("Booting kernel...\n\n");
  
  	cli();
--- 37,53 ----
  extern char do_boot[], do_boot_end[];
  
  void
! loadkernel(struct kerninfo *ki)
  {
+ 	oskit_addr_t entry, load_addr;
  	oskit_size_t stub_size;
  	void *stub;
  	struct far_pointer_32 ptr;
  	oskit_addr_t copy_source;
  	oskit_size_t copy_size;
  
+ 	multiboot_info_dump(ki->ki_mbinfo);
+ 
  	printf("Booting kernel...\n\n");
  
  	cli();
***************
*** 73,91 ****
  	 *
  	 * XXX the "mr" constraint for "ptr" should be "m" but GCC
  	 * says "inconsistent operand constraints."
  	 */
! 	copy_source = kvtophys(kinfo->ki_imgaddr);
! 	copy_size = kinfo->ki_imgsize;
! 	if (copy_source > kinfo->ki_entry) {
  		asm volatile("
  			cld
  			ljmp	%0
  		" : /* no outputs */
  		  : "mr" (ptr),
! 		    "a" (kinfo->ki_entry),
  		    "S" (copy_source),
! 		    "D" (kinfo->ki_entry),
  		    "c" (copy_size),
  		    "d" (LINEAR_DS));
  	}
  	else {
--- 77,111 ----
  	 *
  	 * XXX the "mr" constraint for "ptr" should be "m" but GCC
  	 * says "inconsistent operand constraints."
+ 	 *
+ 	 * Be careful what you put as the values for the registers in
+ 	 * the asm's below.
+ 	 * If you have too many indirections and whatnot then GCC
+ 	 * will apparently run out of registers and won't be able to
+ 	 * set, for example, %ebx to the desired value.
+ 	 * The GCC chokeage looked like this for me:
+ 	 *
+ 	 *	fixed or forbidden register was spilled.
+ 	 *	This may be due to a compiler bug or to impossible asm
+ 	 *
+ 	 * That is why I have load_addr and entry be local vars instead of
+ 	 * just putting the expressions in the asm.
  	 */
! 	copy_source = kvtophys(ki->ki_imgaddr);
! 	copy_size = kerninfo_imagesize(ki);
! 	entry = ki->ki_mbhdr.entry;
! 	load_addr = ki->ki_mbhdr.load_addr;
! 	if (copy_source > load_addr) {
  		asm volatile("
  			cld
  			ljmp	%0
  		" : /* no outputs */
  		  : "mr" (ptr),
! 		    "a" (entry),
  		    "S" (copy_source),
! 		    "D" (load_addr),
  		    "c" (copy_size),
+ 		    "b" (kvtophys(ki->ki_mbinfo)),
  		    "d" (LINEAR_DS));
  	}
  	else {
***************
*** 94,103 ****
  			ljmp	%0
  		" : /* no outputs */
  		  : "mr" (ptr),
! 		    "a" (kinfo->ki_entry),
  		    "S" (copy_source + copy_size - 1),
! 		    "D" (kinfo->ki_entry + copy_size - 1),
  		    "c" (copy_size),
  		    "d" (LINEAR_DS));
  	}
  }
--- 114,124 ----
  			ljmp	%0
  		" : /* no outputs */
  		  : "mr" (ptr),
! 		    "a" (entry),
  		    "S" (copy_source + copy_size - 1),
! 		    "D" (load_addr + copy_size - 1),
  		    "c" (copy_size),
+ 		    "b" (kvtophys(ki->ki_mbinfo)),
  		    "d" (LINEAR_DS));
  	}
  }
Index: main.c
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/main.c,v
retrieving revision 1.17.2.1
retrieving revision 1.17.2.2
diff -c -r1.17.2.1 -r1.17.2.2
*** main.c	1998/03/14 03:15:26	1.17.2.1
--- main.c	1998/03/14 04:14:47	1.17.2.2
***************
*** 31,90 ****
  #include <oskit/c/assert.h>		/* assert */
  #include <oskit/c/arpa/inet.h>		/* ntohl */
  #include <oskit/c/fd.h>			/* fd_set_console */
  
  #include <oskit/dev/dev.h>
  
- #include "boottype.h"			/* boothowto */
  #include "timer.h"			/* TIMER_FREQ */
  #include "driver.h"			/* net_init */
  #include "ether.h"			/* arptable */
  #include "gdt.h"			/* copy_base_gdt */
  #include "boot.h"			/* kerninfo */
  #include "netboot.h"			/* netprintf */
- #include "../bsd/reboot.h"		/* RB_ constants */
  
- void			*kernel_tempstack;
- struct bootinfo		*bsdbootinfo;
- struct kerninfo		kinfo;
- 
- unsigned long		boothowto;
- 
- static void
- makeboothowto(int argc, char *argv[])
- {
- 	int i;
- 
- 	boothowto = 0;
- 	for (i = 0; i < argc; i++) {
- 
- #define FLAG(s, f) \
- 		if (strcmp(argv[i], #s) == 0) { \
- 			boothowto |= (f); \
- 			continue; \
- 		}
- 
- 		FLAG(-a, RB_ASKNAME);
- 		FLAG(-s, RB_SINGLE);
- 		FLAG(-r, RB_DFLTROOT);
- 		FLAG(-b, RB_HALT);
- 		FLAG(-d, BSD_RB_KDB);
- 		FLAG(-c, BSD_RB_CONFIG);
- 		FLAG(-h, BSD_RB_SERIAL);
- 		FLAG(-f, BSD_RB_FASTCONSOLE);
- #undef FLAG
- 	}
- }
- 
  void
  main(int argc, char *argv[])
  {
! 	char url[512];
  
! 	printf("Netboot metakernel v2.01 (compiled %s)\n", __DATE__);
  
- 	/* For now, use what we were booted with. */
- 	makeboothowto(argc, argv);
- 
  	fd_set_console();		/* so stdin, etc work */
  	oskit_dev_init();
  	osenv_timer_register(bumpticks, TIMER_FREQ);
--- 31,59 ----
  #include <oskit/c/assert.h>		/* assert */
  #include <oskit/c/arpa/inet.h>		/* ntohl */
  #include <oskit/c/fd.h>			/* fd_set_console */
+ #include <oskit/c/malloc.h>		/* malloc_lmm */
+ #include <oskit/lmm.h>			/* lmm_remove_free */
+ #include <oskit/x86/pc/base_multiboot.h>	/* boot_info */
  
  #include <oskit/dev/dev.h>
  
  #include "timer.h"			/* TIMER_FREQ */
  #include "driver.h"			/* net_init */
  #include "ether.h"			/* arptable */
  #include "gdt.h"			/* copy_base_gdt */
  #include "boot.h"			/* kerninfo */
  #include "netboot.h"			/* netprintf */
  
  void
  main(int argc, char *argv[])
  {
! 	struct kerninfo kinfo;
! 	struct multiboot_info *mbi;
! 	char cmdline[512];
! 	char *args;
  
! 	printf("Netboot metakernel v2.02 (compiled %s)\n", __DATE__);
  
  	fd_set_console();		/* so stdin, etc work */
  	oskit_dev_init();
  	osenv_timer_register(bumpticks, TIMER_FREQ);
***************
*** 99,148 ****
  	 * Figure out our rootserver, dir to mount, and file to load.
  	 * Then try to get it.
  	 */
  reprompt:
! 	printf("\nTell me the kernel file name in ip:/dir/file form "
! 	       "(\"quit\" to exit)\n");
! 	printf("kernel name: ");
! 	fgets(url, 512, stdin);
! 	url[strlen(url) - 1] = '\0';	/* chop \n */
! 	if (strcmp(url, "quit") == 0)
  		exit(0);
! 	if (url[0] == '\0')
  		goto reprompt;
! 	if (! parse_pseudo_url(url,
! 			       &arptable[ARP_ROOTSERVER].ipaddr,
! 			       &kinfo.ki_dirname, &kinfo.ki_name)) {
! 		printf("bad url, try again\n");
  		goto reprompt;
  	}
! 	if (! getkernel_net(arptable[ARP_CLIENT].ipaddr,
! 			    arptable[ARP_ROOTSERVER].ipaddr,
! 			    arptable[ARP_GATEWAY].ipaddr,
! 			    netmask, hostname,
! 			    &kinfo)) {
! 		printf("can't get the kernel, try again\n");
  		goto reprompt;
  	}
- 	netprintf("Root server: %I, dir %s, file %s\r\n",
- 		  arptable[ARP_ROOTSERVER].ipaddr,
- 		  kinfo.ki_dirname, kinfo.ki_name);
- 
- 	/* Fill in a bootinfo struct for BSD. */
- 	bsdbootinfo = (struct bootinfo *)mustcalloc(sizeof(struct bootinfo), 1);
- 	bsdbootinfo->bi_version = BOOTINFO_VERSION;
- 	bsdbootinfo->bi_kernelname = mustmalloc(strlen(kinfo.ki_name) + 1);
- 	strcpy(bsdbootinfo->bi_kernelname, kinfo.ki_name);
- 	bsdbootinfo->bi_size = sizeof(struct bootinfo);
- 
- 	/* Allocate a non-conflicting stack for passing args to the kernel. */
- 	kernel_tempstack = mustmalloc(0x1000);
- 	kernel_tempstack += 0x1000;
  
  	/*
  	 * Clean some stuff up before we load the new image.
  	 * In particular we don't want the timer hammering it,
  	 * and don't want it using some bogus GDT (we may overwrite ours
! 	 * with the new image.)
  	 */
  	net_shutdown();
  	osenv_timer_shutdown();
--- 68,136 ----
  	 * Figure out our rootserver, dir to mount, and file to load.
  	 * Then try to get it.
  	 */
+ 	printf("\nType \"help\" for help.\n\n");
  reprompt:
! 	printf("NetBoot: ");
! 	fgets(cmdline, 512, stdin);
! 	cmdline[strlen(cmdline) - 1] = '\0';	/* chop \n */
! 	if (strcmp(cmdline, "help") == 0) {
! 		printf("\nTell me the kernel file name and args in the form\n"
! 		       "\t<IPaddr>:<path> [args]\n"
! 		       "For example:\n"
! 		       "\t155.22.33.44:/home/foo/kernel -f -h\n"
! 		       "The directory must be an NFS exported directory.\n"
! 		       "Type \"quit\" to exit.\n\n");
! 		goto reprompt;
! 	}
! 	if (strcmp(cmdline, "quit") == 0)
  		exit(0);
! 	if (cmdline[0] == '\0')
  		goto reprompt;
! 	if (! parse_cmdline(cmdline,
! 			    &kinfo.ki_ip.s_addr,
! 			    &kinfo.ki_dirname,
! 			    &kinfo.ki_filename,
! 			    &args)) {
! 		printf("Bad command line, try again.\n");
  		goto reprompt;
  	}
! 	netprintf("Root server: %I, dir: %s,\r\n"
! 		  "  file: %s,  cmdline: `%s'\r\n",
! 		  kinfo.ki_ip.s_addr, kinfo.ki_dirname, kinfo.ki_filename,
! 		  args ? args : "");
! 	memcpy(&arptable[ARP_ROOTSERVER].ipaddr, &kinfo.ki_ip.s_addr,
! 	       sizeof arptable[ARP_ROOTSERVER].ipaddr);
! 	if (getkernel_net(&kinfo) != 0) {
! 		printf("Can't get the kernel, try again.\n");
  		goto reprompt;
+ 	}
+ 
+ 	/*
+ 	 * Reserve the memory where the kernel will eventually reside.
+ 	 * Future malloc's, like the one for the multiboot_info struct
+ 	 * we pass to the new kernel, will stay out of this region.
+ 	 */
+ 	lmm_remove_free(&malloc_lmm,
+ 			(void *)phystokv(kinfo.ki_mbhdr.load_addr),
+ 			kerninfo_imagesize(&kinfo));
+ 
+ 	/*
+ 	 * Allocate and fill in a multiboot_info struct we will pass.
+ 	 */
+ 	mbi = kinfo.ki_mbinfo = mustcalloc(sizeof(struct multiboot_info), 1);
+ 	mbi->mem_lower = boot_info.mem_lower;
+ 	mbi->mem_upper = boot_info.mem_upper;
+ 	mbi->flags |= MULTIBOOT_MEMORY;
+ 	if (args) {
+ 		mbi->cmdline = kvtophys(strdup(args));
+ 		mbi->flags |= MULTIBOOT_CMDLINE;
  	}
  
  	/*
  	 * Clean some stuff up before we load the new image.
  	 * In particular we don't want the timer hammering it,
  	 * and don't want it using some bogus GDT (we may overwrite ours
! 	 * with the new image).
  	 */
  	net_shutdown();
  	osenv_timer_shutdown();
Index: misc.c
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/misc.c,v
retrieving revision 1.10
retrieving revision 1.10.2.1
diff -c -r1.10 -r1.10.2.1
*** misc.c	1997/10/21 00:06:29	1.10
--- misc.c	1998/03/14 04:14:48	1.10.2.1
***************
*** 11,21 ****
  #include <oskit/c/string.h>		/* memcpy */
  #include <oskit/c/stdarg.h>		/* va_list */
  #include <oskit/c/stdio.h>		/* putchar */
- #include <oskit/c/ctype.h>		/* isdigit */
- #include <oskit/c/stdlib.h>		/* atol */
  
  #include "netboot.h"
- #include "driver.h"
  
  /*
   * Convert IP address from net to machine order
--- 11,18 ----
***************
*** 31,52 ****
  	*d     = *(s+3);
  }
  
- /*
-  * Set a default netmask for IP address
-  */
- void
- default_netmask(unsigned long addr)
- {
- 	int net = addr >> 24;
- 	
- 	if (net <= 127)
- 		netmask = 0xff000000;
- 	else if (net < 192)
- 		netmask = 0xffff0000;
- 	else
- 		netmask = 0xffffff00;
- }
- 
  /**************************************************************************
  PRINTF and friends
  
--- 28,33 ----
***************
*** 204,211 ****
   * Convert ascii ipaddr to long.
   * XXX should be changed to inet_addr.
   */
! int
! setip(char *p, unsigned long *i)
  {
          unsigned long ip = 0;
          int val;
--- 185,192 ----
   * Convert ascii ipaddr to long.
   * XXX should be changed to inet_addr.
   */
! static int
! setip(char *p, unsigned int *i)
  {
          unsigned long ip = 0;
          int val;
***************
*** 232,250 ****
  }
  
  /*
!  * Take the "pseudo url" url and set the IP, dir, and name components.
!  * The url is modified and the dir and name pointers point into it.
!  * The url looks like ip:/dir/file, eg 155.99.212.1:/tmp/foo
   */ 
  int
! parse_pseudo_url(char *url, unsigned long *ip, char **dir, char **name)
  {
! 	char *p;
  
! 	if (! setip(url, ip))
  		return 0;
  
! 	p = strchr(url, ':');
  	if (! p)
  		return 0;
  	if (*++p != '/')
--- 213,232 ----
  }
  
  /*
!  * Take the command line and set the IP, dir, and name components.
!  * The cmdline is modified and things point into it.
!  * The cmdline looks like "ip:/dir/file -foo bar", eg "155.99.212.1:/tmp/foo -l"
   */ 
  int
! parse_cmdline(char *cmdline, unsigned int *ip, char **dir, char **name,
! 	      char **rest)
  {
! 	char *p = cmdline;
  
! 	if (! setip(p, ip))
  		return 0;
  
! 	p = strchr(p, ':');
  	if (! p)
  		return 0;
  	if (*++p != '/')
***************
*** 262,267 ****
--- 244,258 ----
  	/* Allow the case ip:/foo; we might have just NULified that slash. */
  	if ((*dir)[0] == '\0')
  		*dir = "/";
+ 
+ 	p = strchr(p, ' ');
+ 	if (! p) {
+ 		/* No command line args, ok. */
+ 		*rest = NULL;
+ 		return 1;
+ 	}
+ 	*p++ = '\0';
+ 	*rest = p;
  
  	return 1;
  }
Index: netboot.h
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/netboot.h,v
retrieving revision 1.9
retrieving revision 1.9.2.1
diff -c -r1.9 -r1.9.2.1
*** netboot.h	1997/10/21 00:06:30	1.9
--- netboot.h	1998/03/14 04:14:48	1.9.2.1
***************
*** 9,15 ****
  
  #include <oskit/machine/types.h>
  #include <oskit/c/sys/types.h>
- #include "bootinfo.h"			/* struct bootinfo */
  #include "boot.h"			/* struct kerninfo */
  
  #ifndef MAX_ARP_RETRIES
--- 9,14 ----
***************
*** 35,46 ****
  #define MKIP(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d))
  
  void convert_ipaddr(void *d, void *s);
- void default_netmask(unsigned long addr);
  char *netsprintf(char *buf, char *fmt, ...);
  void netprintf(char *fmt, ...);
! int parse_pseudo_url(char *url, unsigned long *ip, char **dir, char **name);
! int setip(char *p, unsigned long *i);
! 
! extern void			*kernel_tempstack;
! extern struct bootinfo		*bsdbootinfo;
! extern struct kerninfo		kinfo;
--- 34,40 ----
  #define MKIP(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d))
  
  void convert_ipaddr(void *d, void *s);
  char *netsprintf(char *buf, char *fmt, ...);
  void netprintf(char *fmt, ...);
! int parse_cmdline(char *cmdline, unsigned int *ip, char **dir, char **name,
! 		  char **rest);
Index: rpc.c
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/rpc.c,v
retrieving revision 1.6
retrieving revision 1.6.2.1
diff -c -r1.6 -r1.6.2.1
*** rpc.c	1997/08/25 09:10:34	1.6
--- rpc.c	1998/03/14 04:14:49	1.6.2.1
***************
*** 170,176 ****
  {
  	static char buf[64];
  
! 	sprintf(buf, "RPC Error: (%ld,%ld,%ld)",
  		ntohl(rpc->u.reply.rstatus),
  		ntohl(rpc->u.reply.verifier),
  		ntohl(rpc->u.reply.astatus));
--- 170,176 ----
  {
  	static char buf[64];
  
! 	sprintf(buf, "RPC Error: (%d,%d,%d)",
  		ntohl(rpc->u.reply.rstatus),
  		ntohl(rpc->u.reply.verifier),
  		ntohl(rpc->u.reply.astatus));
Index: udp.c
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/udp.c,v
retrieving revision 1.8
retrieving revision 1.8.2.1
diff -c -r1.8 -r1.8.2.1
*** udp.c	1997/08/25 09:10:34	1.8
--- udp.c	1998/03/14 04:14:49	1.8.2.1
***************
*** 13,18 ****
--- 13,19 ----
  #include "await.h"
  #include "driver.h"
  #include "udp.h"
+ #include "ip.h"
  #include "ether.h"
  
  /**************************************************************************
