*BSD News Article 16144


Return to BSD News archive

Path: sserve!newshost.anu.edu.au!munnari.oz.au!spool.mu.edu!howland.reston.ans.net!gatech!news-feed-1.peachnet.edu!emory!ogicse!psgrain!percy!agora!implode!davidg
From: davidg@implode.rain.com (David Greenman)
Newsgroups: comp.os.386bsd.questions
Subject: Re: Diskless 386bsd ??
Message-ID: <C74wG3.106@implode.rain.com>
Date: 16 May 93 19:21:38 GMT
Article-I.D.: implode.C74wG3.106
Organization: Delta Systems, Portland, OR.
Lines: 959


  A friend of mine looked through his alt.sources archive and found
the following. 

-DG

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	319
#
echo x - 319
sed 's/^X//' >319 << 'END-of-319'
XNewsgroups: comp.os.386bsd.development
XPath: percy!psgrain!uunet!usc!cs.utexas.edu!utnut!torn!mcshub!martin
XFrom: martin@innovus.com (Martin Renters)
XSubject: diskless 386bsd patches
XMessage-ID: <1993Mar22.053826.17787@mcshub.dcss.mcmaster.ca>
XSender: usenet@mcshub.dcss.mcmaster.ca
XNntp-Posting-Host: foxtrot.innovus.com
XOrganization: Innovus Inc., Hamilton, Ontario, Canada
XDate: Mon, 22 Mar 1993 05:38:26 GMT
XLines: 929
X
XHere are the patches required to allow diskless 386bsd operation.  The
Xfollowing should be considered a BETA release since, while it provides
Xthe diskless functionality, it still has some rough edges.  In particular,
Xthe setup program searches for a magic cookie in the kernel which it
Xthen patches with the appropriate nfs_diskless structure, the hostname
Xis not set up by the setup program, no boot rom exists yet, etc.
X
XTo configure a diskless 386bsd kernel:
X
X  1) un-shar the following file and apply the patch file 'diffs.out'
X
X  2) do a make install in /usr/src/usr.sbin/config to recompile the config
X     program
X
X  3) create a kernel description file in /sys/i386/conf, making sure
X     to add:
X
X	option	DISKLESS
X	config  "386bsd" swap on nfs size 50000
X
X     The size in the above example indicates the number of 512 byte blocks
X     of swap space configured (ie: 25Mb).  An example configuration is
X     included in the file DISKLESS in this package
X
X   4) generate a kernel:
X
X	/usr/sbin/config DISKLESS
X	cd ../../compile/DISKLESS
X	make
X
X   5) Compile the program 'setup.c' on the NFS server which will provide
X      the root and swap file systems. This program has been tested on
X      HP-UX 9.0 (350 and 720) and a 386bsd system.  It requires the use
X      of the getfh() system call which takes a filename as a parameter.
X      It will not work with versions that require a file descriptor
X      (HP-UX 8.X comes to mind).  nfsdiskless.h must match
X      /sys/nfs/nfsdiskless.h on the 386bsd system.  diskless.h contains
X      excerpts from socket.h, mount.h, if.h and nfsv2.h
X
X   6) copy the kernel created in step 4 into the directory the setup program
X      lives in.
X
X   7) ./setup -intf <your interface> -rootfs <your root> -swap <your swapfile>
X	-hostname <diskless hostname> -netmask <diskless netmask>
X
X	eg:  ./setup -intf we0 -rootfs /var/386bsd -swap /var/swap/alpha
X		-hostname alpha -netmask 255.255.255.0
X
X   8) copy the resulting 386bsd file to a tinyBSD boot floppy.  You will
X      probably need to remove most of the other files on the disk to make
X      enough space.
X
X   9) Boot with the disk.  You will probably have to modify the /etc/rc
X      script so it doesn't try and fsck a non-existant filesystem, etc.
X      If you get a panic "nfs swap" it probably means you haven't exported
X      your filesystems correctly.
X
X
XProblem areas:
X
X  1) NFS on 386bsd does not support the flock() system call.  This prevents
X     the passwd(1) program and others from working.  A wordaround would be
X     to use lock-files if the flock() function is not supported.
X
X  2) The setup program cannot re-setup a kernel.  This is because the
X     magic cookie is overwritten.  A better way of patching the kernel
X     would be to use the symbol table in the executable, but this is not
X     portable (easily at 1am in the morning)
X
X  3) The hostname should be configured by the setup program.
X
XAcknowledgements:
X
X   Wolfgang Solfrank (ws@tools.de) provided input and some of the patches
X   from his implementation.
X
X   The setup program is loosely based on a similar program in the 4.4BSD
X   distribution.
X
X
XHave fun...
X
XMartin Renters				martin@innovus.com
X
X
X# This is a shell archive.  Remove anything before this line,
X# then unpack it by saving it in a file and typing "sh file".
X#
X# Wrapped by Martin Renters <martin@foxtrot> on Sun Mar 21 23:22:03 1993
X#
X# This archive contains:
X#	diffs.out	DISKLESS	setup.c		diskless.h	
X#	nfsdiskless.h	
X#
X
XLANG=""; export LANG
XPATH=/bin:/usr/bin:$PATH; export PATH
X
Xecho x - diffs.out
Xcat >diffs.out <<'@EOF'
X
X*** /mnt/usr/src/sys.386bsd/i386/i386/pmap.c	Tue Jan 26 20:11:25 1993
X--- /sys/i386/i386/pmap.c	Sat Jan 30 10:24:35 1993
X***************
X*** 999,1004 ****
X--- 999,1005 ----
X  #endif
X  			npv = (pv_entry_t)
X  				malloc(sizeof *npv, M_VMPVENT, M_NOWAIT);
X+ 			if (npv == NULL) panic("pmap_enter: malloc returned NULL");
X  			npv->pv_va = va;
X  			npv->pv_pmap = pmap;
X  			npv->pv_next = pv->pv_next;
X*** /mnt/usr/src/sys.386bsd/i386/i386/autoconf.c	Tue Jul 14 18:53:09 1992
X--- /sys/i386/i386/autoconf.c	Fri Jan 29 16:48:38 1993
X***************
X*** 142,147 ****
X--- 142,150 ----
X   */
X  setroot()
X  {
X+ #ifdef DISKLESS
X+ 	return;
X+ #else
X  	int  majdev, mindev, unit, part, adaptor;
X  	dev_t temp, orootdev;
X  	struct swdevt *swp;
X***************
X*** 189,192 ****
X--- 192,196 ----
X  	if (temp == dumpdev)
X  		dumpdev = swdevt[0].sw_dev;
X  #endif
X+ #endif /* DISKLESS */
X  }
X*** /mnt/usr/src/sys.386bsd/kern/vfs_conf.c	Mon May 25 02:43:56 1992
X--- /sys/kern/vfs_conf.c	Fri Jan 29 15:07:30 1993
X***************
X*** 40,47 ****
X--- 40,49 ----
X   * This specifies the filesystem used to mount the root.
X   * This specification should be done by /etc/config.
X   */
X+ #ifndef DISKLESS
X  extern int ufs_mountroot();
X  int (*mountroot)() = ufs_mountroot;
X+ #endif
X  
X  /*
X   * These define the root filesystem and device.
X*** /mnt/usr/src/sys.386bsd/nfs/nfsdiskless.h	Tue Dec 24 14:24:15 1991
X--- /sys/nfs/nfsdiskless.h	Sun Mar 21 18:23:19 1993
X***************
X*** 44,49 ****
X--- 44,50 ----
X   * For now it is statically initialized in swapvmunix.c, but someday a primary
X   * bootstrap should fill it in.
X   */
X+ #define NFSMNAMELEN	64
X  struct nfs_diskless {
X  	struct ifaliasreq myif;		/* Info. for partial ifconfig */
X  	struct sockaddr	mygateway;	/* Default gateway for "route add" */
X***************
X*** 50,58 ****
X  	struct nfs_args	swap_args;	/* Mount args for swap file */
X  	u_char		swap_fh[NFS_FHSIZE]; /* Swap file's file handle */
X  	struct sockaddr	swap_saddr;	/* Address of swap server */
X! 	char		*swap_hostnam;	/* Host name for mount pt */
X  	struct nfs_args	root_args;	/* Mount args for root fs */
X  	u_char		root_fh[NFS_FHSIZE]; /* File handle of root dir */
X  	struct sockaddr	root_saddr;	/* Address of root server */
X! 	char		*root_hostnam;	/* Host name for mount pt */
X  };
X--- 51,59 ----
X  	struct nfs_args	swap_args;	/* Mount args for swap file */
X  	u_char		swap_fh[NFS_FHSIZE]; /* Swap file's file handle */
X  	struct sockaddr	swap_saddr;	/* Address of swap server */
X! 	char		swap_hostnam[NFSMNAMELEN];	/* Host name for mount pt */
X  	struct nfs_args	root_args;	/* Mount args for root fs */
X  	u_char		root_fh[NFS_FHSIZE]; /* File handle of root dir */
X  	struct sockaddr	root_saddr;	/* Address of root server */
X! 	char		root_hostnam[NFSMNAMELEN];	/* Host name for mount pt */
X  };
X*** /mnt/usr/src/sys.386bsd/vm/swap_pager.c	Tue Jan 26 20:16:16 1993
X--- /sys/vm/swap_pager.c	Fri Jan 29 19:55:33 1993
X***************
X*** 593,598 ****
X--- 593,599 ----
X  	splx(s);
X  	bp->b_flags = B_BUSY | (flags & B_READ);
X  	bp->b_proc = &proc0;	/* XXX (but without B_PHYS set this is ok) */
X+ 	bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;   /* DISKLESS (WS)*/
X  	bp->b_un.b_addr = (caddr_t)kva;
X  	bp->b_blkno = swb->swb_block + btodb(off);
X  	VHOLD(swapdev_vp);
X***************
X*** 625,630 ****
X--- 626,633 ----
X  		spc->spc_m = m;
X  		bp->b_flags |= B_CALL;
X  		bp->b_iodone = swap_pager_iodone;
X+ 		bp->b_dirtyoff = 0;		/* DISKLESS: (WS) */
X+ 		bp->b_dirtyend = bp->b_bcount;
X  		s = splbio();
X  		swp->sw_poip++;
X  		queue_enter(&swap_pager_inuse, spc, swp_clean_t, spc_list);
X*** bak/config.y	Fri Mar 19 16:50:57 1993
X--- /usr/src/usr.sbin/config/config.y	Fri Mar 19 18:42:33 1993
X***************
X*** 244,250 ****
X  		= {
X  			struct file_list *fl = newswap();
X  
X! 			if (eq($1, "generic"))
X  				fl->f_fn = $1;
X  			else {
X  				fl->f_swapdev = nametodev($1, 0, 'b');
X--- 244,250 ----
X  		= {
X  			struct file_list *fl = newswap();
X  
X! 			if (eq($1, "generic") || eq($1,"nfs"))
X  				fl->f_fn = $1;
X  			else {
X  				fl->f_swapdev = nametodev($1, 0, 'b');
X***************
X*** 641,647 ****
X  	 */
X  	if (system->f_fn)
X  		return;
X! 	if (eq(fl->f_fn, "generic"))
X  		system->f_fn = ns(fl->f_fn);
X  	else
X  		system->f_fn = ns(system->f_needs);
X--- 641,647 ----
X  	 */
X  	if (system->f_fn)
X  		return;
X! 	if (eq(fl->f_fn, "generic") || eq(fl->f_fn, "nfs"))
X  		system->f_fn = ns(fl->f_fn);
X  	else
X  		system->f_fn = ns(system->f_needs);
X***************
X*** 812,818 ****
X  {
X  	char buf[BUFSIZ];
X  	register struct file_list *swap;
X! 	int generic;
X  
X  	if (fl == 0 || fl->f_type != SYSTEMSPEC) {
X  		yyerror("internal error, bad system specification");
X--- 812,818 ----
X  {
X  	char buf[BUFSIZ];
X  	register struct file_list *swap;
X! 	int generic,nfs;
X  
X  	if (fl == 0 || fl->f_type != SYSTEMSPEC) {
X  		yyerror("internal error, bad system specification");
X***************
X*** 820,826 ****
X  	}
X  	swap = fl->f_next;
X  	generic = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "generic");
X! 	if (fl->f_rootdev == NODEV && !generic) {
X  		yyerror("no root device specified");
X  		exit(1);
X  	}
X--- 820,827 ----
X  	}
X  	swap = fl->f_next;
X  	generic = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "generic");
X! 	nfs = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "nfs");
X! 	if (fl->f_rootdev == NODEV && !generic && !nfs) {
X  		yyerror("no root device specified");
X  		exit(1);
X  	}
X***************
X*** 912,918 ****
X  {
X  
X  	for (;fl && fl->f_type == SWAPSPEC; fl = fl->f_next) {
X! 		if (eq(fl->f_fn, "generic"))
X  			continue;
X  		if (alreadychecked(fl->f_swapdev, checked, pchecked))
X  			continue;
X--- 913,919 ----
X  {
X  
X  	for (;fl && fl->f_type == SWAPSPEC; fl = fl->f_next) {
X! 		if (eq(fl->f_fn, "generic") || eq(fl->f_fn, "nfs"))
X  			continue;
X  		if (alreadychecked(fl->f_swapdev, checked, pchecked))
X  			continue;
X*** bak/mkswapconf.c	Fri Mar 19 16:50:57 1993
X--- /usr/src/usr.sbin/config/mkswapconf.c	Sat Mar 20 21:27:38 1993
X***************
X*** 79,84 ****
X--- 79,93 ----
X  	}
X  	fprintf(fp, "#include \"sys/param.h\"\n");
X  	fprintf(fp, "#include \"sys/conf.h\"\n");
X+ 	if (eq(fl->f_fn, "nfs")) {
X+ 		fprintf(fp, "#include \"../sys/socket.h\"\n");
X+ 		fprintf(fp, "#include \"../sys/mount.h\"\n");
X+ 		fprintf(fp, "#include \"../net/if.h\"\n");
X+ 		fprintf(fp, "#include \"../nfs/nfsv2.h\"\n");
X+ 		fprintf(fp, "#include \"../nfs/nfsdiskless.h\"\n");
X+ 		fprintf(fp, "\nextern int nfs_mountroot();\n");
X+ 		fprintf(fp, "\nint (*mountroot)() = nfs_mountroot;\n");
X+ 	}
X  	fprintf(fp, "\n");
X  	/*
X  	 * If there aren't any swap devices
X***************
X*** 105,110 ****
X--- 114,124 ----
X  	} while (swap && swap->f_type == SWAPSPEC);
X  	fprintf(fp, "\t{ 0, 0, 0 }\n");
X  	fprintf(fp, "};\n");
X+ 	if (eq(fl->f_fn, "nfs")) {
X+ 		fprintf(fp,"struct nfs_diskless nfs_diskless = {\n");
X+ 		fprintf(fp,"	{ { 'D', 'i', 'S', 'k', 'L', 'e', 'S', 's', '\\0' }}\n");
X+ 		fprintf(fp,"};\n");
X+ 	}
X  	fclose(fp);
X  	return (swap);
X  }
X@EOF
X
Xchmod 640 diffs.out
X
Xecho x - DISKLESS
Xcat >DISKLESS <<'@EOF'
X#
X# DISKLESS - Diskless 386bsd with DDB
X#
Xmachine		"i386"
Xcpu		"i386"
Xident		DISKLESS
Xtimezone	5 dst
Xmaxusers	10
Xoptions		INET,NFS,UFS,DISKLESS,XSERVER
Xoptions		"COMPAT_43"
Xoptions		"TCP_COMPAT_42"
X
Xconfig		"386bsd"	swap on nfs size 50000
X
Xcontroller	isa0
X#controller	wd0	at isa? port "IO_WD1" bio irq 14 vector wdintr
X#disk		wd0	at wd0 drive 0
X#disk		wd0	at wd0 drive 1
X
Xcontroller	fd0	at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr
Xdisk		fd0	at fd0 drive 0
Xdisk		fd1	at fd0 drive 1
X
X#controller	as0	at isa? port 0x330 bio irq 11 drq 5 vector asintr
X#disk		as0	at as0 drive 0
X#disk		as1	at as0 drive 1
X
Xdevice		pc0	at isa? port "IO_KBD" tty irq 1 vector pcrint
Xdevice		npx0	at isa? port "IO_NPX" irq 13 vector npxintr
Xdevice		com1	at isa? port "IO_COM1" tty irq 4 vector comintr
X#device		com2	at isa? port "IO_COM2" tty irq 3 vector comintr
X
Xdevice we0 at isa? port 0x280 net irq 3 iomem 0xd0000 iosiz 8192 vector weintr
X#device ne0 at isa? port 0x320 net irq 3 vector neintr
X#device ec0 at isa? port 0x250 net irq 2 iomem 0xd8000 iosiz 8192 vector ecintr
X
Xdevice		wt0	at isa? port 0x300 bio irq 5 drq 1 vector wtintr
X
Xpseudo-device	loop
Xpseudo-device	ether
Xpseudo-device	sl	2
Xpseudo-device	log
Xpseudo-device	ddb
Xpseudo-device	pty	4
X
Xpseudo-device	swappager
Xpseudo-device	vnodepager
Xpseudo-device	devpager
X@EOF
X
Xchmod 640 DISKLESS
X
Xecho x - setup.c
Xcat >setup.c <<'@EOF'
X/*************************************************************************
X
XDiskless Configuration Program
X
XBased loosely on the 4.4BSD diskless setup code
X
X*************************************************************************/
X#include <stdio.h>
X#include <fcntl.h>
X#include <sys/stat.h>
X#include <netdb.h>
X
X#include "diskless.h"
X#include "nfsdiskless.h"
X
X#ifndef i386				/* Most other systems BIG ENDIAN */
X#define BIG_ENDIAN
X#endif
X
Xstruct nfs_diskless nfs_diskless;
X
X#define MAGIC_COOKIE	"DiSkLeSs"
X#define NFS_SOCKET	2049
X
X#define KW_HELP		0
X#define KW_INTERFACE	1
X#define KW_ROOTFS	2
X#define KW_SWAP		3
X#define KW_RSIZE	4
X#define KW_WSIZE	5
X#define KW_NETMASK	6
X#define KW_HOSTNAME	7
X#define KW_KERNEL	8
X
Xstruct {
X	char *name;
X	int  keyval;
X} keywords[] = {
X	{ "-intf",	KW_INTERFACE },
X	{ "-rootfs",	KW_ROOTFS },
X	{ "-swap",	KW_SWAP },
X	{ "-netmask",	KW_NETMASK },
X	{ "-rsize",	KW_RSIZE },
X	{ "-wsize",	KW_WSIZE },
X	{ "-hostname",	KW_HOSTNAME },
X	{ "-kernel",	KW_KERNEL },
X	{ NULL,		KW_HELP }
X};
X
Xchar *hostname = "386bsd";
Xchar *kernel = "386bsd";
Xchar *rootpath = "/var/386bsd";
Xchar *swappath = "/var/swap/386bsd";
Xchar servername[256];
Xint rsize = 8192;
Xint wsize = 8192;
X
Xmain(argc, argv)
X	int argc; char *argv[];
X{
X	int fd,i,j,cmd;
X	unsigned int broadcast, netmask, myip;
X	struct hostent *hp;
X	struct stat statbuf;
X	char buf[1024];
X	char *p, *q;
X
X	netmask = 0;
X	bzero(&nfs_diskless, 0, sizeof(struct nfs_diskless));
X	strcpy(nfs_diskless.myif.ifra_name,"we0");
X	nfs_diskless.myif.ifra_addr.sa_len = sizeof(struct sockaddr);
X	nfs_diskless.myif.ifra_addr.sa_family = AF_INET;
X	nfs_diskless.myif.ifra_broadaddr.sa_len = sizeof(struct sockaddr);
X	nfs_diskless.myif.ifra_broadaddr.sa_family = AF_INET;
X	nfs_diskless.myif.ifra_mask.sa_len = sizeof(struct sockaddr);
X	nfs_diskless.myif.ifra_mask.sa_family = AF_UNSPEC;
X	nfs_diskless.swap_args.sotype = i386order(SOCK_DGRAM);
X	nfs_diskless.swap_args.flags = i386order(NFSMNT_WSIZE | NFSMNT_RSIZE);
X	nfs_diskless.swap_args.timeo = i386order(10);
X	nfs_diskless.swap_args.retrans = i386order(100);
X	nfs_diskless.swap_saddr.sa_len = sizeof(struct sockaddr);
X	nfs_diskless.swap_saddr.sa_family = AF_INET;
X	nfs_diskless.root_args.sotype = i386order(SOCK_DGRAM);
X	nfs_diskless.root_args.flags = i386order(NFSMNT_WSIZE | NFSMNT_RSIZE);
X	nfs_diskless.root_args.timeo = i386order(10);
X	nfs_diskless.root_args.retrans = i386order(100);
X	nfs_diskless.root_saddr.sa_len = sizeof(struct sockaddr);
X	nfs_diskless.root_saddr.sa_family = AF_INET;
X
X	if (gethostname(servername, 256) < 0) {
X		fprintf(stderr,"%s: unable to get host server name\n",argv[0]);
X		exit(2);
X	}
X	if ((hp = gethostbyname(servername)) == NULL) {
X		fprintf(stderr,"%s: unable to get host address\n",argv[0]);
X		exit(2);
X	}
X	nfs_diskless.swap_saddr.sa_data[0] = nfs_diskless.root_saddr.sa_data[0]
X		= NFS_SOCKET >> 8;
X	nfs_diskless.swap_saddr.sa_data[1] = nfs_diskless.root_saddr.sa_data[1]
X		= NFS_SOCKET & 0x00FF;
X	bcopy(*hp->h_addr_list, &nfs_diskless.swap_saddr.sa_data[2], 4);
X	bcopy(*hp->h_addr_list, &nfs_diskless.root_saddr.sa_data[2], 4);
X	
X	i = 1;
X	while (i < argc) {
X		cmd = KW_HELP;
X		for (j=0; keywords[j].name; j++) {
X			if (!strcmp(keywords[j].name, argv[i])) {
X				if ((i+1) < argc) {
X					cmd = keywords[j].keyval;
X					break;
X				}
X			}
X		}
X		switch(cmd) {
X			case KW_HELP:
X				help(argv[0], argv[i]);
X				exit(2);
X			case KW_INTERFACE:
X				if (strlen(argv[i+1]) >= IFNAMSIZ) {
X					fprintf(stderr,
X						"%s: interface name '%s' too long.\n",
X						argv[0], argv[i+1]);
X					exit(2);
X				}
X				strcpy(nfs_diskless.myif.ifra_name, argv[i+1]);
X				i += 2;
X				break;
X			case KW_ROOTFS:
X				rootpath = argv[i+1];
X				i += 2;
X				break;
X			case KW_SWAP:
X				swappath = argv[i+1];
X				i += 2;
X				break;
X			case KW_RSIZE:
X				rsize = atoi(argv[i+1]);
X				i += 2;
X				break;
X			case KW_WSIZE:
X				wsize = atoi(argv[i+1]);
X				i += 2;
X				break;
X			case KW_NETMASK:
X				netmask = inet_addr(argv[i+1]);
X				i +=2;
X				break;
X			case KW_HOSTNAME:
X				hostname = argv[i+1];
X				i += 2;
X				break;
X			case KW_KERNEL:
X				kernel = argv[i+1];
X				i += 2;
X				break;
X		}
X	}
X	nfs_diskless.swap_args.rsize = i386order(rsize);
X	nfs_diskless.swap_args.wsize = i386order(wsize);
X	nfs_diskless.root_args.rsize = i386order(rsize);
X	nfs_diskless.root_args.wsize = i386order(wsize);
X	if ((hp = gethostbyname(hostname)) == NULL) {
X		fprintf(stderr,"%s: unable to get diskless address\n",argv[0]);
X		exit(2);
X	}
X	bcopy(*hp->h_addr_list, &nfs_diskless.myif.ifra_addr.sa_data[2], 4);
X	if (!netmask) {
X		unsigned char net;
X		net = nfs_diskless.myif.ifra_addr.sa_data[2];
X		if (net <= 127)
X			netmask = inet_addr("255.0.0.0");
X		else if (net < 192)
X			netmask = inet_addr("255.255.0.0");
X		else	netmask = inet_addr("255.255.255.0");
X	}
X	bcopy(*hp->h_addr_list, &myip, 4);
X	broadcast = (myip & netmask) | ~netmask;
X	bcopy(&broadcast, &nfs_diskless.myif.ifra_broadaddr.sa_data[2], 4);
X	bcopy(&netmask, &nfs_diskless.myif.ifra_mask.sa_data[2], 4);
X	if (stat(rootpath, &statbuf) < 0) {
X		fprintf(stderr,"%s: unable to stat '%s'\n",
X			argv[0],rootpath);
X		exit(2);
X	}
X	if (!S_ISDIR(statbuf.st_mode)) {
X		fprintf(stderr,"%s: '%s' is not a directory\n",
X			argv[0],rootpath);
X		exit(2);
X	}
X	if (getfh(rootpath, nfs_diskless.root_fh) < 0) {
X		fprintf(stderr,"%s: unable to get handle for '%s'\n",
X			argv[0],rootpath);
X		exit(2);
X	}
X	sprintf(buf,"%s:%s",servername, rootpath);
X	buf[NFSMNAMELEN-1] = 0;
X	strcpy(nfs_diskless.root_hostnam,buf);
X	printf("root is on %s\n",nfs_diskless.root_hostnam);
X	if (stat(swappath, &statbuf) < 0) {
X		fprintf(stderr,"%s: unable to stat '%s'\n",
X			argv[0],swappath);
X		exit(2);
X	}
X	if (!S_ISREG(statbuf.st_mode)) {
X		fprintf(stderr,"%s: '%s' is not a regular file\n",
X			argv[0],swappath);
X		exit(2);
X	}
X	if (getfh(swappath, nfs_diskless.swap_fh) < 0) {
X		fprintf(stderr,"%s: unable to get handle for '%s'\n",
X			argv[0],swappath);
X		exit(2);
X	}
X	sprintf(buf,"%s:%s",servername, swappath);
X	buf[NFSMNAMELEN-1] = 0;
X	strcpy(nfs_diskless.swap_hostnam,buf);
X	printf("swap is on %s\n",nfs_diskless.swap_hostnam);
X
X			/***********************/
X			/* Now update kernel   */
X			/***********************/
X	if (stat(kernel, &statbuf) < 0) {
X		fprintf(stderr,"%s: unable to stat '%s'\n",
X			argv[0],kernel);
X		exit(2);
X	}
X	if ((fd = open(kernel, O_RDWR)) < 0) {
X		fprintf(stderr,"%s: unable to open kernel file '%s'\n",
X			argv[0],kernel);
X		exit(2);
X	}
X	if ((p = q = malloc(statbuf.st_size)) == NULL) {
X		fprintf(stderr,"%s: unable to allocate memory for kernel\n",
X			argv[0]);
X		exit(2);
X	}
X	if (read(fd, p, statbuf.st_size) != statbuf.st_size) {
X		fprintf(stderr,"%s: unable to read kernel\n",
X			argv[0]);
X		exit(2);
X	}
X	while ((q < (p + statbuf.st_size)) && memcmp(q, MAGIC_COOKIE,
X		sizeof(MAGIC_COOKIE) - 1)) q++;
X	if (q == (p+statbuf.st_size)) {
X		fprintf(stderr,"%s: unable to find magic cookie in kernel '%s'\n",
X			argv[0],kernel);
X		exit(2);
X	}
X	printf("kernel size = %d bytes, nfs_diskless at offset %d\n",
X		statbuf.st_size, q-p);
X	bcopy(&nfs_diskless, q, sizeof(struct nfs_diskless));
X	if (lseek(fd, 0L, SEEK_SET) < 0) {
X		fprintf(stderr,"%s: unable to rewind kernel '%s'\n",
X			argv[0],kernel);
X		exit(2);
X	}
X	if (write(fd, p, statbuf.st_size) != statbuf.st_size) {
X		fprintf(stderr,"%s: unable to write to kernel '%s'\n",
X			argv[0],kernel);
X		exit(2);
X	}
X	close(fd);
X}
X
X/********************************************************************
XHELP - Print help message
X********************************************************************/
Xhelp(prog, keywd)
X	char *prog, *keywd;
X{
X	int i;
X	fprintf(stderr,"%s: invalid keyword '%s' or not enough parameters\n",prog,keywd);
X	fprintf(stderr,"     valid keywords: ");
X	for (i=0; keywords[i].name; i++) fprintf(stderr,"%s ", keywords[i].name);
X	fprintf(stderr,"\n");
X}
X
X/*********************************************************************
XI386ORDER - Byte swap
X*********************************************************************/
Xi386order(i)
X	unsigned int i;
X{
X#ifdef BIG_ENDIAN
X	return( ((i >> 24) & 0x000000FF) |
X		((i >> 8)  & 0x0000FF00) |
X		((i << 8)  & 0x00FF0000) |
X		((i << 24) & 0xFF000000));
X#else
X	return(i);
X#endif
X}
X@EOF
X
Xchmod 640 setup.c
X
Xecho x - diskless.h
Xcat >diskless.h <<'@EOF'
X/*
X * Copyright (c) 1982,1985,1986,1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X *	@(#)socket.h	7.13 (Berkeley) 4/20/91
X */
X
X/*
X * Definitions related to sockets: types, address families, options.
X */
X
X/*
X * Types
X */
X#define	SOCK_STREAM	1		/* stream socket */
X#define	SOCK_DGRAM	2		/* datagram socket */
X#define	SOCK_RAW	3		/* raw-protocol interface */
X#define	SOCK_RDM	4		/* reliably-delivered message */
X#define	SOCK_SEQPACKET	5		/* sequenced packet stream */
X
X/*
X * Option flags per-socket.
X */
X#define	SO_DEBUG	0x0001		/* turn on debugging info recording */
X#define	SO_ACCEPTCONN	0x0002		/* socket has had listen() */
X#define	SO_REUSEADDR	0x0004		/* allow local address reuse */
X#define	SO_KEEPALIVE	0x0008		/* keep connections alive */
X#define	SO_DONTROUTE	0x0010		/* just use interface addresses */
X#define	SO_BROADCAST	0x0020		/* permit sending of broadcast msgs */
X#define	SO_USELOOPBACK	0x0040		/* bypass hardware when possible */
X#define	SO_LINGER	0x0080		/* linger on close if data present */
X#define	SO_OOBINLINE	0x0100		/* leave received OOB data in line */
X
X/*
X * Additional options, not kept in so_options.
X */
X#define SO_SNDBUF	0x1001		/* send buffer size */
X#define SO_RCVBUF	0x1002		/* receive buffer size */
X#define SO_SNDLOWAT	0x1003		/* send low-water mark */
X#define SO_RCVLOWAT	0x1004		/* receive low-water mark */
X#define SO_SNDTIMEO	0x1005		/* send timeout */
X#define SO_RCVTIMEO	0x1006		/* receive timeout */
X#define	SO_ERROR	0x1007		/* get error status and clear */
X#define	SO_TYPE		0x1008		/* get socket type */
X
X/*
X * Structure used for manipulating linger option.
X */
Xstruct	linger {
X	int	l_onoff;		/* option on/off */
X	int	l_linger;		/* linger time */
X};
X
X/*
X * Level number for (get/set)sockopt() to apply to socket itself.
X */
X#define	SOL_SOCKET	0xffff		/* options for socket level */
X
X/*
X * Address families.
X */
X#define	AF_UNSPEC	0		/* unspecified */
X#define	AF_UNIX		1		/* local to host (pipes, portals) */
X#define	AF_INET		2		/* internetwork: UDP, TCP, etc. */
X#define	AF_IMPLINK	3		/* arpanet imp addresses */
X#define	AF_PUP		4		/* pup protocols: e.g. BSP */
X#define	AF_CHAOS	5		/* mit CHAOS protocols */
X#define	AF_NS		6		/* XEROX NS protocols */
X#define	AF_ISO		7		/* ISO protocols */
X#define	AF_OSI		AF_ISO
X#define	AF_ECMA		8		/* european computer manufacturers */
X#define	AF_DATAKIT	9		/* datakit protocols */
X#define	AF_CCITT	10		/* CCITT protocols, X.25 etc */
X#define	AF_SNA		11		/* IBM SNA */
X#define AF_DECnet	12		/* DECnet */
X#define AF_DLI		13		/* DEC Direct data link interface */
X#define AF_LAT		14		/* LAT */
X#define	AF_HYLINK	15		/* NSC Hyperchannel */
X#define	AF_APPLETALK	16		/* Apple Talk */
X#define	AF_ROUTE	17		/* Internal Routing Protocol */
X#define	AF_LINK		18		/* Link layer interface */
X#define	pseudo_AF_XTP	19		/* eXpress Transfer Protocol (no AF) */
X
X#define	AF_MAX		20
X
X/*
X * Structure used by kernel to store most
X * addresses.
X */
Xstruct sockaddr {
X	u_char	sa_len;			/* total length */
X	u_char	sa_family;		/* address family */
X	char	sa_data[14];		/* actually longer; address value */
X};
X
X#define	IFNAMSIZ	16
X
Xstruct ifaliasreq {
X	char	ifra_name[IFNAMSIZ];		/* if name, e.g. "en0" */
X	struct	sockaddr ifra_addr;
X	struct	sockaddr ifra_broadaddr;
X	struct	sockaddr ifra_mask;
X};
X
X
X/*
X * File Handle (32 bytes for version 2), variable up to 1024 for version 3
X */
X
X#define NFS_FHSIZE	32
Xtypedef struct { u_char f[NFS_FHSIZE] } nfsv2fh_t;
X/*
X * Arguments to mount NFS
X */
Xstruct nfs_args {
X	struct sockaddr	*addr;		/* file server address */
X	int		sotype;		/* Socket type */
X	int		proto;		/* and Protocol */
X	nfsv2fh_t	*fh;		/* File handle to be mounted */
X	int		flags;		/* flags */
X	int		wsize;		/* write size in bytes */
X	int		rsize;		/* read size in bytes */
X	int		timeo;		/* initial timeout in .1 secs */
X	int		retrans;	/* times to retry send */
X	char		*hostname;	/* server's name */
X};
X/*
X * NFS mount option flags
X */
X#define	NFSMNT_SOFT	0x0001	/* soft mount (hard is default) */
X#define	NFSMNT_WSIZE	0x0002	/* set write size */
X#define	NFSMNT_RSIZE	0x0004	/* set read size */
X#define	NFSMNT_TIMEO	0x0008	/* set initial timeout */
X#define	NFSMNT_RETRANS	0x0010	/* set number of request retrys */
X#define	NFSMNT_HOSTNAME	0x0020	/* set hostname for error printf */
X#define	NFSMNT_INT	0x0040	/* allow interrupts on hard mount */
X#define	NFSMNT_NOCONN	0x0080	/* Don't Connect the socket */
X#define	NFSMNT_SCKLOCK	0x0100	/* Lock socket against others */
X#define	NFSMNT_WANTSCK	0x0200	/* Want a socket lock */
X#define	NFSMNT_SPONGY	0x0400	/* spongy mount (soft for stat and lookup) */
X#define	NFSMNT_COMPRESS	0x0800	/* Compress nfs rpc xdr */
X#define	NFSMNT_LOCKBITS	(NFSMNT_SCKLOCK | NFSMNT_WANTSCK)
X
X@EOF
X
Xchmod 644 diskless.h
X
Xecho x - nfsdiskless.h
Xcat >nfsdiskless.h <<'@EOF'
X/*
X * Copyright (c) 1991 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Rick Macklem at The University of Guelph.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X *	@(#)nfsdiskless.h	7.1 (Berkeley) 3/4/91
X */
X
X/*
X * Structure that must be initialized for a diskless nfs client.
X * This structure is used by nfs_mountroot() to set up the root and swap
X * vnodes plus do a partial ifconfig(8) and route(8) so that the critical net
X * interface can communicate with the server.
X * For now it is statically initialized in swapvmunix.c, but someday a primary
X * bootstrap should fill it in.
X */
X#define NFSMNAMELEN	64
Xstruct nfs_diskless {
X	struct ifaliasreq myif;		/* Info. for partial ifconfig */
X	struct sockaddr	mygateway;	/* Default gateway for "route add" */
X	struct nfs_args	swap_args;	/* Mount args for swap file */
X	u_char		swap_fh[NFS_FHSIZE]; /* Swap file's file handle */
X	struct sockaddr	swap_saddr;	/* Address of swap server */
X	char		swap_hostnam[NFSMNAMELEN];	/* Host name for mount pt */
X	struct nfs_args	root_args;	/* Mount args for root fs */
X	u_char		root_fh[NFS_FHSIZE]; /* File handle of root dir */
X	struct sockaddr	root_saddr;	/* Address of root server */
X	char		root_hostnam[NFSMNAMELEN];	/* Host name for mount pt */
X};
X@EOF
X
Xchmod 640 nfsdiskless.h
X
Xexit 0
END-of-319
exit