*BSD News Article 16105


Return to BSD News archive

Newsgroups: comp.os.386bsd.questions
Path: sserve!newshost.anu.edu.au!munnari.oz.au!spool.mu.edu!sdd.hp.com!cs.utexas.edu!utnut!utcsri!newsflash.concordia.ca!sifon!not-for-mail
From: storm@binkley.cs.mcgill.ca (Marc Wandschneider)
Subject: Re: Diskless 386bsd ??
Message-ID: <1t5ur1$lbk@binkley.cs.mcgill.ca>
Lines: 959
Sender: news@sifon.cc.mcgill.ca
Organization: SOCS - Mcgill University, Montreal, Canada
References: <1993May16.094813.16948@ericsson.se>
Date: Sun, 16 May 1993 17:49:21 GMT

In article <1993May16.094813.16948@ericsson.se> etxsral@hal.ericsson.se (Lars Nilsson) writes:
>Does anyone know how to use 386bsd in a 'diskless' configuration ?
>
>I remember that someone posted a patch to alt.sources that made it's
>possible to boot from a floppy and then mount / & swap & /usr from
>a NFS fileserver.
>
>I've searched everywhere for the patch but I can't find it.
>
>Can somebody help me to find the patch or the author of the patch ?


The following is something I have lying around in my directory:



Toodlepip!
Marc 'em.




----- BEGIN INCLUDED FILE -----

Here are the patches required to allow diskless 386bsd operation.  The
following should be considered a BETA release since, while it provides
the diskless functionality, it still has some rough edges.  In particular,
the setup program searches for a magic cookie in the kernel which it
then patches with the appropriate nfs_diskless structure, the hostname
is not set up by the setup program, no boot rom exists yet, etc.

To configure a diskless 386bsd kernel:

  1) un-shar the following file and apply the patch file 'diffs.out'

  2) do a make install in /usr/src/usr.sbin/config to recompile the config
     program

  3) create a kernel description file in /sys/i386/conf, making sure
     to add:

	option	DISKLESS
	config  "386bsd" swap on nfs size 50000

     The size in the above example indicates the number of 512 byte blocks
     of swap space configured (ie: 25Mb).  An example configuration is
     included in the file DISKLESS in this package

   4) generate a kernel:

	/usr/sbin/config DISKLESS
	cd ../../compile/DISKLESS
	make

   5) Compile the program 'setup.c' on the NFS server which will provide
      the root and swap file systems. This program has been tested on
      HP-UX 9.0 (350 and 720) and a 386bsd system.  It requires the use
      of the getfh() system call which takes a filename as a parameter.
      It will not work with versions that require a file descriptor
      (HP-UX 8.X comes to mind).  nfsdiskless.h must match
      /sys/nfs/nfsdiskless.h on the 386bsd system.  diskless.h contains
      excerpts from socket.h, mount.h, if.h and nfsv2.h

   6) copy the kernel created in step 4 into the directory the setup program
      lives in.

   7) ./setup -intf <your interface> -rootfs <your root> -swap <your swapfile>
	-hostname <diskless hostname> -netmask <diskless netmask>

	eg:  ./setup -intf we0 -rootfs /var/386bsd -swap /var/swap/alpha
		-hostname alpha -netmask 255.255.255.0

   8) copy the resulting 386bsd file to a tinyBSD boot floppy.  You will
      probably need to remove most of the other files on the disk to make
      enough space.

   9) Boot with the disk.  You will probably have to modify the /etc/rc
      script so it doesn't try and fsck a non-existant filesystem, etc.
      If you get a panic "nfs swap" it probably means you haven't exported
      your filesystems correctly.


Problem areas:

  1) NFS on 386bsd does not support the flock() system call.  This prevents
     the passwd(1) program and others from working.  A wordaround would be
     to use lock-files if the flock() function is not supported.

  2) The setup program cannot re-setup a kernel.  This is because the
     magic cookie is overwritten.  A better way of patching the kernel
     would be to use the symbol table in the executable, but this is not
     portable (easily at 1am in the morning)

  3) The hostname should be configured by the setup program.

Acknowledgements:

   Wolfgang Solfrank (ws@tools.de) provided input and some of the patches
   from his implementation.

   The setup program is loosely based on a similar program in the 4.4BSD
   distribution.


Have fun...

Martin Renters				martin@innovus.com


# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by Martin Renters <martin@foxtrot> on Sun Mar 21 23:22:03 1993
#
# This archive contains:
#	diffs.out	DISKLESS	setup.c		diskless.h	
#	nfsdiskless.h	
#

LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH

echo x - diffs.out
cat >diffs.out <<'@EOF'

*** /mnt/usr/src/sys.386bsd/i386/i386/pmap.c	Tue Jan 26 20:11:25 1993
--- /sys/i386/i386/pmap.c	Sat Jan 30 10:24:35 1993
***************
*** 999,1004 ****
--- 999,1005 ----
  #endif
  			npv = (pv_entry_t)
  				malloc(sizeof *npv, M_VMPVENT, M_NOWAIT);
+ 			if (npv == NULL) panic("pmap_enter: malloc returned NULL");
  			npv->pv_va = va;
  			npv->pv_pmap = pmap;
  			npv->pv_next = pv->pv_next;
*** /mnt/usr/src/sys.386bsd/i386/i386/autoconf.c	Tue Jul 14 18:53:09 1992
--- /sys/i386/i386/autoconf.c	Fri Jan 29 16:48:38 1993
***************
*** 142,147 ****
--- 142,150 ----
   */
  setroot()
  {
+ #ifdef DISKLESS
+ 	return;
+ #else
  	int  majdev, mindev, unit, part, adaptor;
  	dev_t temp, orootdev;
  	struct swdevt *swp;
***************
*** 189,192 ****
--- 192,196 ----
  	if (temp == dumpdev)
  		dumpdev = swdevt[0].sw_dev;
  #endif
+ #endif /* DISKLESS */
  }
*** /mnt/usr/src/sys.386bsd/kern/vfs_conf.c	Mon May 25 02:43:56 1992
--- /sys/kern/vfs_conf.c	Fri Jan 29 15:07:30 1993
***************
*** 40,47 ****
--- 40,49 ----
   * This specifies the filesystem used to mount the root.
   * This specification should be done by /etc/config.
   */
+ #ifndef DISKLESS
  extern int ufs_mountroot();
  int (*mountroot)() = ufs_mountroot;
+ #endif
  
  /*
   * These define the root filesystem and device.
*** /mnt/usr/src/sys.386bsd/nfs/nfsdiskless.h	Tue Dec 24 14:24:15 1991
--- /sys/nfs/nfsdiskless.h	Sun Mar 21 18:23:19 1993
***************
*** 44,49 ****
--- 44,50 ----
   * For now it is statically initialized in swapvmunix.c, but someday a primary
   * bootstrap should fill it in.
   */
+ #define NFSMNAMELEN	64
  struct nfs_diskless {
  	struct ifaliasreq myif;		/* Info. for partial ifconfig */
  	struct sockaddr	mygateway;	/* Default gateway for "route add" */
***************
*** 50,58 ****
  	struct nfs_args	swap_args;	/* Mount args for swap file */
  	u_char		swap_fh[NFS_FHSIZE]; /* Swap file's file handle */
  	struct sockaddr	swap_saddr;	/* Address of swap server */
! 	char		*swap_hostnam;	/* Host name for mount pt */
  	struct nfs_args	root_args;	/* Mount args for root fs */
  	u_char		root_fh[NFS_FHSIZE]; /* File handle of root dir */
  	struct sockaddr	root_saddr;	/* Address of root server */
! 	char		*root_hostnam;	/* Host name for mount pt */
  };
--- 51,59 ----
  	struct nfs_args	swap_args;	/* Mount args for swap file */
  	u_char		swap_fh[NFS_FHSIZE]; /* Swap file's file handle */
  	struct sockaddr	swap_saddr;	/* Address of swap server */
! 	char		swap_hostnam[NFSMNAMELEN];	/* Host name for mount pt */
  	struct nfs_args	root_args;	/* Mount args for root fs */
  	u_char		root_fh[NFS_FHSIZE]; /* File handle of root dir */
  	struct sockaddr	root_saddr;	/* Address of root server */
! 	char		root_hostnam[NFSMNAMELEN];	/* Host name for mount pt */
  };
*** /mnt/usr/src/sys.386bsd/vm/swap_pager.c	Tue Jan 26 20:16:16 1993
--- /sys/vm/swap_pager.c	Fri Jan 29 19:55:33 1993
***************
*** 593,598 ****
--- 593,599 ----
  	splx(s);
  	bp->b_flags = B_BUSY | (flags & B_READ);
  	bp->b_proc = &proc0;	/* XXX (but without B_PHYS set this is ok) */
+ 	bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;   /* DISKLESS (WS)*/
  	bp->b_un.b_addr = (caddr_t)kva;
  	bp->b_blkno = swb->swb_block + btodb(off);
  	VHOLD(swapdev_vp);
***************
*** 625,630 ****
--- 626,633 ----
  		spc->spc_m = m;
  		bp->b_flags |= B_CALL;
  		bp->b_iodone = swap_pager_iodone;
+ 		bp->b_dirtyoff = 0;		/* DISKLESS: (WS) */
+ 		bp->b_dirtyend = bp->b_bcount;
  		s = splbio();
  		swp->sw_poip++;
  		queue_enter(&swap_pager_inuse, spc, swp_clean_t, spc_list);
*** bak/config.y	Fri Mar 19 16:50:57 1993
--- /usr/src/usr.sbin/config/config.y	Fri Mar 19 18:42:33 1993
***************
*** 244,250 ****
  		= {
  			struct file_list *fl = newswap();
  
! 			if (eq($1, "generic"))
  				fl->f_fn = $1;
  			else {
  				fl->f_swapdev = nametodev($1, 0, 'b');
--- 244,250 ----
  		= {
  			struct file_list *fl = newswap();
  
! 			if (eq($1, "generic") || eq($1,"nfs"))
  				fl->f_fn = $1;
  			else {
  				fl->f_swapdev = nametodev($1, 0, 'b');
***************
*** 641,647 ****
  	 */
  	if (system->f_fn)
  		return;
! 	if (eq(fl->f_fn, "generic"))
  		system->f_fn = ns(fl->f_fn);
  	else
  		system->f_fn = ns(system->f_needs);
--- 641,647 ----
  	 */
  	if (system->f_fn)
  		return;
! 	if (eq(fl->f_fn, "generic") || eq(fl->f_fn, "nfs"))
  		system->f_fn = ns(fl->f_fn);
  	else
  		system->f_fn = ns(system->f_needs);
***************
*** 812,818 ****
  {
  	char buf[BUFSIZ];
  	register struct file_list *swap;
! 	int generic;
  
  	if (fl == 0 || fl->f_type != SYSTEMSPEC) {
  		yyerror("internal error, bad system specification");
--- 812,818 ----
  {
  	char buf[BUFSIZ];
  	register struct file_list *swap;
! 	int generic,nfs;
  
  	if (fl == 0 || fl->f_type != SYSTEMSPEC) {
  		yyerror("internal error, bad system specification");
***************
*** 820,826 ****
  	}
  	swap = fl->f_next;
  	generic = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "generic");
! 	if (fl->f_rootdev == NODEV && !generic) {
  		yyerror("no root device specified");
  		exit(1);
  	}
--- 820,827 ----
  	}
  	swap = fl->f_next;
  	generic = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "generic");
! 	nfs = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "nfs");
! 	if (fl->f_rootdev == NODEV && !generic && !nfs) {
  		yyerror("no root device specified");
  		exit(1);
  	}
***************
*** 912,918 ****
  {
  
  	for (;fl && fl->f_type == SWAPSPEC; fl = fl->f_next) {
! 		if (eq(fl->f_fn, "generic"))
  			continue;
  		if (alreadychecked(fl->f_swapdev, checked, pchecked))
  			continue;
--- 913,919 ----
  {
  
  	for (;fl && fl->f_type == SWAPSPEC; fl = fl->f_next) {
! 		if (eq(fl->f_fn, "generic") || eq(fl->f_fn, "nfs"))
  			continue;
  		if (alreadychecked(fl->f_swapdev, checked, pchecked))
  			continue;
*** bak/mkswapconf.c	Fri Mar 19 16:50:57 1993
--- /usr/src/usr.sbin/config/mkswapconf.c	Sat Mar 20 21:27:38 1993
***************
*** 79,84 ****
--- 79,93 ----
  	}
  	fprintf(fp, "#include \"sys/param.h\"\n");
  	fprintf(fp, "#include \"sys/conf.h\"\n");
+ 	if (eq(fl->f_fn, "nfs")) {
+ 		fprintf(fp, "#include \"../sys/socket.h\"\n");
+ 		fprintf(fp, "#include \"../sys/mount.h\"\n");
+ 		fprintf(fp, "#include \"../net/if.h\"\n");
+ 		fprintf(fp, "#include \"../nfs/nfsv2.h\"\n");
+ 		fprintf(fp, "#include \"../nfs/nfsdiskless.h\"\n");
+ 		fprintf(fp, "\nextern int nfs_mountroot();\n");
+ 		fprintf(fp, "\nint (*mountroot)() = nfs_mountroot;\n");
+ 	}
  	fprintf(fp, "\n");
  	/*
  	 * If there aren't any swap devices
***************
*** 105,110 ****
--- 114,124 ----
  	} while (swap && swap->f_type == SWAPSPEC);
  	fprintf(fp, "\t{ 0, 0, 0 }\n");
  	fprintf(fp, "};\n");
+ 	if (eq(fl->f_fn, "nfs")) {
+ 		fprintf(fp,"struct nfs_diskless nfs_diskless = {\n");
+ 		fprintf(fp,"	{ { 'D', 'i', 'S', 'k', 'L', 'e', 'S', 's', '\\0' }}\n");
+ 		fprintf(fp,"};\n");
+ 	}
  	fclose(fp);
  	return (swap);
  }
@EOF

chmod 640 diffs.out

echo x - DISKLESS
cat >DISKLESS <<'@EOF'
#
# DISKLESS - Diskless 386bsd with DDB
#
machine		"i386"
cpu		"i386"
ident		DISKLESS
timezone	5 dst
maxusers	10
options		INET,NFS,UFS,DISKLESS,XSERVER
options		"COMPAT_43"
options		"TCP_COMPAT_42"

config		"386bsd"	swap on nfs size 50000

controller	isa0
#controller	wd0	at isa? port "IO_WD1" bio irq 14 vector wdintr
#disk		wd0	at wd0 drive 0
#disk		wd0	at wd0 drive 1

controller	fd0	at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr
disk		fd0	at fd0 drive 0
disk		fd1	at fd0 drive 1

#controller	as0	at isa? port 0x330 bio irq 11 drq 5 vector asintr
#disk		as0	at as0 drive 0
#disk		as1	at as0 drive 1

device		pc0	at isa? port "IO_KBD" tty irq 1 vector pcrint
device		npx0	at isa? port "IO_NPX" irq 13 vector npxintr
device		com1	at isa? port "IO_COM1" tty irq 4 vector comintr
#device		com2	at isa? port "IO_COM2" tty irq 3 vector comintr

device we0 at isa? port 0x280 net irq 3 iomem 0xd0000 iosiz 8192 vector weintr
#device ne0 at isa? port 0x320 net irq 3 vector neintr
#device ec0 at isa? port 0x250 net irq 2 iomem 0xd8000 iosiz 8192 vector ecintr

device		wt0	at isa? port 0x300 bio irq 5 drq 1 vector wtintr

pseudo-device	loop
pseudo-device	ether
pseudo-device	sl	2
pseudo-device	log
pseudo-device	ddb
pseudo-device	pty	4

pseudo-device	swappager
pseudo-device	vnodepager
pseudo-device	devpager
@EOF

chmod 640 DISKLESS

echo x - setup.c
cat >setup.c <<'@EOF'
/*************************************************************************

Diskless Configuration Program

Based loosely on the 4.4BSD diskless setup code

*************************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <netdb.h>

#include "diskless.h"
#include "nfsdiskless.h"

#ifndef i386				/* Most other systems BIG ENDIAN */
#define BIG_ENDIAN
#endif

struct nfs_diskless nfs_diskless;

#define MAGIC_COOKIE	"DiSkLeSs"
#define NFS_SOCKET	2049

#define KW_HELP		0
#define KW_INTERFACE	1
#define KW_ROOTFS	2
#define KW_SWAP		3
#define KW_RSIZE	4
#define KW_WSIZE	5
#define KW_NETMASK	6
#define KW_HOSTNAME	7
#define KW_KERNEL	8

struct {
	char *name;
	int  keyval;
} keywords[] = {
	{ "-intf",	KW_INTERFACE },
	{ "-rootfs",	KW_ROOTFS },
	{ "-swap",	KW_SWAP },
	{ "-netmask",	KW_NETMASK },
	{ "-rsize",	KW_RSIZE },
	{ "-wsize",	KW_WSIZE },
	{ "-hostname",	KW_HOSTNAME },
	{ "-kernel",	KW_KERNEL },
	{ NULL,		KW_HELP }
};

char *hostname = "386bsd";
char *kernel = "386bsd";
char *rootpath = "/var/386bsd";
char *swappath = "/var/swap/386bsd";
char servername[256];
int rsize = 8192;
int wsize = 8192;

main(argc, argv)
	int argc; char *argv[];
{
	int fd,i,j,cmd;
	unsigned int broadcast, netmask, myip;
	struct hostent *hp;
	struct stat statbuf;
	char buf[1024];
	char *p, *q;

	netmask = 0;
	bzero(&nfs_diskless, 0, sizeof(struct nfs_diskless));
	strcpy(nfs_diskless.myif.ifra_name,"we0");
	nfs_diskless.myif.ifra_addr.sa_len = sizeof(struct sockaddr);
	nfs_diskless.myif.ifra_addr.sa_family = AF_INET;
	nfs_diskless.myif.ifra_broadaddr.sa_len = sizeof(struct sockaddr);
	nfs_diskless.myif.ifra_broadaddr.sa_family = AF_INET;
	nfs_diskless.myif.ifra_mask.sa_len = sizeof(struct sockaddr);
	nfs_diskless.myif.ifra_mask.sa_family = AF_UNSPEC;
	nfs_diskless.swap_args.sotype = i386order(SOCK_DGRAM);
	nfs_diskless.swap_args.flags = i386order(NFSMNT_WSIZE | NFSMNT_RSIZE);
	nfs_diskless.swap_args.timeo = i386order(10);
	nfs_diskless.swap_args.retrans = i386order(100);
	nfs_diskless.swap_saddr.sa_len = sizeof(struct sockaddr);
	nfs_diskless.swap_saddr.sa_family = AF_INET;
	nfs_diskless.root_args.sotype = i386order(SOCK_DGRAM);
	nfs_diskless.root_args.flags = i386order(NFSMNT_WSIZE | NFSMNT_RSIZE);
	nfs_diskless.root_args.timeo = i386order(10);
	nfs_diskless.root_args.retrans = i386order(100);
	nfs_diskless.root_saddr.sa_len = sizeof(struct sockaddr);
	nfs_diskless.root_saddr.sa_family = AF_INET;

	if (gethostname(servername, 256) < 0) {
		fprintf(stderr,"%s: unable to get host server name\n",argv[0]);
		exit(2);
	}
	if ((hp = gethostbyname(servername)) == NULL) {
		fprintf(stderr,"%s: unable to get host address\n",argv[0]);
		exit(2);
	}
	nfs_diskless.swap_saddr.sa_data[0] = nfs_diskless.root_saddr.sa_data[0]
		= NFS_SOCKET >> 8;
	nfs_diskless.swap_saddr.sa_data[1] = nfs_diskless.root_saddr.sa_data[1]
		= NFS_SOCKET & 0x00FF;
	bcopy(*hp->h_addr_list, &nfs_diskless.swap_saddr.sa_data[2], 4);
	bcopy(*hp->h_addr_list, &nfs_diskless.root_saddr.sa_data[2], 4);
	
	i = 1;
	while (i < argc) {
		cmd = KW_HELP;
		for (j=0; keywords[j].name; j++) {
			if (!strcmp(keywords[j].name, argv[i])) {
				if ((i+1) < argc) {
					cmd = keywords[j].keyval;
					break;
				}
			}
		}
		switch(cmd) {
			case KW_HELP:
				help(argv[0], argv[i]);
				exit(2);
			case KW_INTERFACE:
				if (strlen(argv[i+1]) >= IFNAMSIZ) {
					fprintf(stderr,
						"%s: interface name '%s' too long.\n",
						argv[0], argv[i+1]);
					exit(2);
				}
				strcpy(nfs_diskless.myif.ifra_name, argv[i+1]);
				i += 2;
				break;
			case KW_ROOTFS:
				rootpath = argv[i+1];
				i += 2;
				break;
			case KW_SWAP:
				swappath = argv[i+1];
				i += 2;
				break;
			case KW_RSIZE:
				rsize = atoi(argv[i+1]);
				i += 2;
				break;
			case KW_WSIZE:
				wsize = atoi(argv[i+1]);
				i += 2;
				break;
			case KW_NETMASK:
				netmask = inet_addr(argv[i+1]);
				i +=2;
				break;
			case KW_HOSTNAME:
				hostname = argv[i+1];
				i += 2;
				break;
			case KW_KERNEL:
				kernel = argv[i+1];
				i += 2;
				break;
		}
	}
	nfs_diskless.swap_args.rsize = i386order(rsize);
	nfs_diskless.swap_args.wsize = i386order(wsize);
	nfs_diskless.root_args.rsize = i386order(rsize);
	nfs_diskless.root_args.wsize = i386order(wsize);
	if ((hp = gethostbyname(hostname)) == NULL) {
		fprintf(stderr,"%s: unable to get diskless address\n",argv[0]);
		exit(2);
	}
	bcopy(*hp->h_addr_list, &nfs_diskless.myif.ifra_addr.sa_data[2], 4);
	if (!netmask) {
		unsigned char net;
		net = nfs_diskless.myif.ifra_addr.sa_data[2];
		if (net <= 127)
			netmask = inet_addr("255.0.0.0");
		else if (net < 192)
			netmask = inet_addr("255.255.0.0");
		else	netmask = inet_addr("255.255.255.0");
	}
	bcopy(*hp->h_addr_list, &myip, 4);
	broadcast = (myip & netmask) | ~netmask;
	bcopy(&broadcast, &nfs_diskless.myif.ifra_broadaddr.sa_data[2], 4);
	bcopy(&netmask, &nfs_diskless.myif.ifra_mask.sa_data[2], 4);
	if (stat(rootpath, &statbuf) < 0) {
		fprintf(stderr,"%s: unable to stat '%s'\n",
			argv[0],rootpath);
		exit(2);
	}
	if (!S_ISDIR(statbuf.st_mode)) {
		fprintf(stderr,"%s: '%s' is not a directory\n",
			argv[0],rootpath);
		exit(2);
	}
	if (getfh(rootpath, nfs_diskless.root_fh) < 0) {
		fprintf(stderr,"%s: unable to get handle for '%s'\n",
			argv[0],rootpath);
		exit(2);
	}
	sprintf(buf,"%s:%s",servername, rootpath);
	buf[NFSMNAMELEN-1] = 0;
	strcpy(nfs_diskless.root_hostnam,buf);
	printf("root is on %s\n",nfs_diskless.root_hostnam);
	if (stat(swappath, &statbuf) < 0) {
		fprintf(stderr,"%s: unable to stat '%s'\n",
			argv[0],swappath);
		exit(2);
	}
	if (!S_ISREG(statbuf.st_mode)) {
		fprintf(stderr,"%s: '%s' is not a regular file\n",
			argv[0],swappath);
		exit(2);
	}
	if (getfh(swappath, nfs_diskless.swap_fh) < 0) {
		fprintf(stderr,"%s: unable to get handle for '%s'\n",
			argv[0],swappath);
		exit(2);
	}
	sprintf(buf,"%s:%s",servername, swappath);
	buf[NFSMNAMELEN-1] = 0;
	strcpy(nfs_diskless.swap_hostnam,buf);
	printf("swap is on %s\n",nfs_diskless.swap_hostnam);

			/***********************/
			/* Now update kernel   */
			/***********************/
	if (stat(kernel, &statbuf) < 0) {
		fprintf(stderr,"%s: unable to stat '%s'\n",
			argv[0],kernel);
		exit(2);
	}
	if ((fd = open(kernel, O_RDWR)) < 0) {
		fprintf(stderr,"%s: unable to open kernel file '%s'\n",
			argv[0],kernel);
		exit(2);
	}
	if ((p = q = malloc(statbuf.st_size)) == NULL) {
		fprintf(stderr,"%s: unable to allocate memory for kernel\n",
			argv[0]);
		exit(2);
	}
	if (read(fd, p, statbuf.st_size) != statbuf.st_size) {
		fprintf(stderr,"%s: unable to read kernel\n",
			argv[0]);
		exit(2);
	}
	while ((q < (p + statbuf.st_size)) && memcmp(q, MAGIC_COOKIE,
		sizeof(MAGIC_COOKIE) - 1)) q++;
	if (q == (p+statbuf.st_size)) {
		fprintf(stderr,"%s: unable to find magic cookie in kernel '%s'\n",
			argv[0],kernel);
		exit(2);
	}
	printf("kernel size = %d bytes, nfs_diskless at offset %d\n",
		statbuf.st_size, q-p);
	bcopy(&nfs_diskless, q, sizeof(struct nfs_diskless));
	if (lseek(fd, 0L, SEEK_SET) < 0) {
		fprintf(stderr,"%s: unable to rewind kernel '%s'\n",
			argv[0],kernel);
		exit(2);
	}
	if (write(fd, p, statbuf.st_size) != statbuf.st_size) {
		fprintf(stderr,"%s: unable to write to kernel '%s'\n",
			argv[0],kernel);
		exit(2);
	}
	close(fd);
}

/********************************************************************
HELP - Print help message
********************************************************************/
help(prog, keywd)
	char *prog, *keywd;
{
	int i;
	fprintf(stderr,"%s: invalid keyword '%s' or not enough parameters\n",prog,keywd);
	fprintf(stderr,"     valid keywords: ");
	for (i=0; keywords[i].name; i++) fprintf(stderr,"%s ", keywords[i].name);
	fprintf(stderr,"\n");
}

/*********************************************************************
I386ORDER - Byte swap
*********************************************************************/
i386order(i)
	unsigned int i;
{
#ifdef BIG_ENDIAN
	return( ((i >> 24) & 0x000000FF) |
		((i >> 8)  & 0x0000FF00) |
		((i << 8)  & 0x00FF0000) |
		((i << 24) & 0xFF000000));
#else
	return(i);
#endif
}
@EOF

chmod 640 setup.c

echo x - diskless.h
cat >diskless.h <<'@EOF'
/*
 * Copyright (c) 1982,1985,1986,1988 Regents of the University of California.
 * 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.
 * 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 the University of
 *	California, Berkeley and its contributors.
 * 4. 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 BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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.
 *
 *	@(#)socket.h	7.13 (Berkeley) 4/20/91
 */

/*
 * Definitions related to sockets: types, address families, options.
 */

/*
 * Types
 */
#define	SOCK_STREAM	1		/* stream socket */
#define	SOCK_DGRAM	2		/* datagram socket */
#define	SOCK_RAW	3		/* raw-protocol interface */
#define	SOCK_RDM	4		/* reliably-delivered message */
#define	SOCK_SEQPACKET	5		/* sequenced packet stream */

/*
 * Option flags per-socket.
 */
#define	SO_DEBUG	0x0001		/* turn on debugging info recording */
#define	SO_ACCEPTCONN	0x0002		/* socket has had listen() */
#define	SO_REUSEADDR	0x0004		/* allow local address reuse */
#define	SO_KEEPALIVE	0x0008		/* keep connections alive */
#define	SO_DONTROUTE	0x0010		/* just use interface addresses */
#define	SO_BROADCAST	0x0020		/* permit sending of broadcast msgs */
#define	SO_USELOOPBACK	0x0040		/* bypass hardware when possible */
#define	SO_LINGER	0x0080		/* linger on close if data present */
#define	SO_OOBINLINE	0x0100		/* leave received OOB data in line */

/*
 * Additional options, not kept in so_options.
 */
#define SO_SNDBUF	0x1001		/* send buffer size */
#define SO_RCVBUF	0x1002		/* receive buffer size */
#define SO_SNDLOWAT	0x1003		/* send low-water mark */
#define SO_RCVLOWAT	0x1004		/* receive low-water mark */
#define SO_SNDTIMEO	0x1005		/* send timeout */
#define SO_RCVTIMEO	0x1006		/* receive timeout */
#define	SO_ERROR	0x1007		/* get error status and clear */
#define	SO_TYPE		0x1008		/* get socket type */

/*
 * Structure used for manipulating linger option.
 */
struct	linger {
	int	l_onoff;		/* option on/off */
	int	l_linger;		/* linger time */
};

/*
 * Level number for (get/set)sockopt() to apply to socket itself.
 */
#define	SOL_SOCKET	0xffff		/* options for socket level */

/*
 * Address families.
 */
#define	AF_UNSPEC	0		/* unspecified */
#define	AF_UNIX		1		/* local to host (pipes, portals) */
#define	AF_INET		2		/* internetwork: UDP, TCP, etc. */
#define	AF_IMPLINK	3		/* arpanet imp addresses */
#define	AF_PUP		4		/* pup protocols: e.g. BSP */
#define	AF_CHAOS	5		/* mit CHAOS protocols */
#define	AF_NS		6		/* XEROX NS protocols */
#define	AF_ISO		7		/* ISO protocols */
#define	AF_OSI		AF_ISO
#define	AF_ECMA		8		/* european computer manufacturers */
#define	AF_DATAKIT	9		/* datakit protocols */
#define	AF_CCITT	10		/* CCITT protocols, X.25 etc */
#define	AF_SNA		11		/* IBM SNA */
#define AF_DECnet	12		/* DECnet */
#define AF_DLI		13		/* DEC Direct data link interface */
#define AF_LAT		14		/* LAT */
#define	AF_HYLINK	15		/* NSC Hyperchannel */
#define	AF_APPLETALK	16		/* Apple Talk */
#define	AF_ROUTE	17		/* Internal Routing Protocol */
#define	AF_LINK		18		/* Link layer interface */
#define	pseudo_AF_XTP	19		/* eXpress Transfer Protocol (no AF) */

#define	AF_MAX		20

/*
 * Structure used by kernel to store most
 * addresses.
 */
struct sockaddr {
	u_char	sa_len;			/* total length */
	u_char	sa_family;		/* address family */
	char	sa_data[14];		/* actually longer; address value */
};

#define	IFNAMSIZ	16

struct ifaliasreq {
	char	ifra_name[IFNAMSIZ];		/* if name, e.g. "en0" */
	struct	sockaddr ifra_addr;
	struct	sockaddr ifra_broadaddr;
	struct	sockaddr ifra_mask;
};


/*
 * File Handle (32 bytes for version 2), variable up to 1024 for version 3
 */

#define NFS_FHSIZE	32
typedef struct { u_char f[NFS_FHSIZE] } nfsv2fh_t;
/*
 * Arguments to mount NFS
 */
struct nfs_args {
	struct sockaddr	*addr;		/* file server address */
	int		sotype;		/* Socket type */
	int		proto;		/* and Protocol */
	nfsv2fh_t	*fh;		/* File handle to be mounted */
	int		flags;		/* flags */
	int		wsize;		/* write size in bytes */
	int		rsize;		/* read size in bytes */
	int		timeo;		/* initial timeout in .1 secs */
	int		retrans;	/* times to retry send */
	char		*hostname;	/* server's name */
};
/*
 * NFS mount option flags
 */
#define	NFSMNT_SOFT	0x0001	/* soft mount (hard is default) */
#define	NFSMNT_WSIZE	0x0002	/* set write size */
#define	NFSMNT_RSIZE	0x0004	/* set read size */
#define	NFSMNT_TIMEO	0x0008	/* set initial timeout */
#define	NFSMNT_RETRANS	0x0010	/* set number of request retrys */
#define	NFSMNT_HOSTNAME	0x0020	/* set hostname for error printf */
#define	NFSMNT_INT	0x0040	/* allow interrupts on hard mount */
#define	NFSMNT_NOCONN	0x0080	/* Don't Connect the socket */
#define	NFSMNT_SCKLOCK	0x0100	/* Lock socket against others */
#define	NFSMNT_WANTSCK	0x0200	/* Want a socket lock */
#define	NFSMNT_SPONGY	0x0400	/* spongy mount (soft for stat and lookup) */
#define	NFSMNT_COMPRESS	0x0800	/* Compress nfs rpc xdr */
#define	NFSMNT_LOCKBITS	(NFSMNT_SCKLOCK | NFSMNT_WANTSCK)

@EOF

chmod 644 diskless.h

echo x - nfsdiskless.h
cat >nfsdiskless.h <<'@EOF'
/*
 * Copyright (c) 1991 The Regents of the University of California.
 * All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Rick Macklem at The University of Guelph.
 *
 * 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.
 * 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 the University of
 *	California, Berkeley and its contributors.
 * 4. 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 BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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.
 *
 *	@(#)nfsdiskless.h	7.1 (Berkeley) 3/4/91
 */

/*
 * Structure that must be initialized for a diskless nfs client.
 * This structure is used by nfs_mountroot() to set up the root and swap
 * vnodes plus do a partial ifconfig(8) and route(8) so that the critical net
 * interface can communicate with the server.
 * For now it is statically initialized in swapvmunix.c, but someday a primary
 * bootstrap should fill it in.
 */
#define NFSMNAMELEN	64
struct nfs_diskless {
	struct ifaliasreq myif;		/* Info. for partial ifconfig */
	struct sockaddr	mygateway;	/* Default gateway for "route add" */
	struct nfs_args	swap_args;	/* Mount args for swap file */
	u_char		swap_fh[NFS_FHSIZE]; /* Swap file's file handle */
	struct sockaddr	swap_saddr;	/* Address of swap server */
	char		swap_hostnam[NFSMNAMELEN];	/* Host name for mount pt */
	struct nfs_args	root_args;	/* Mount args for root fs */
	u_char		root_fh[NFS_FHSIZE]; /* File handle of root dir */
	struct sockaddr	root_saddr;	/* Address of root server */
	char		root_hostnam[NFSMNAMELEN];	/* Host name for mount pt */
};
@EOF

chmod 640 nfsdiskless.h

exit 0

-- 
----------------------------------------------------------------------------
         storm@cs.mcgill.ca           SOCS Staff, McGill University
         Marc Wandschneider                   (514)398-5924
 386bsd--ftp agate.berkeley.edu:/pub/386BSD/386bsd-0.1, mail for FAQ info