+ register struct mount *mp;
+ register struct nfs_diskless *nd = &nfs_diskless;
+ struct socket *so;
+ struct vnode *vp;
+ struct proc *p = curproc; /* XXX */
+ int error, i, s;
+
+ /*
+ * XXX time must be non-zero when we init the interface or else
+ * the arp code will wedge...
+ */
+ if (time.tv_sec == 0)
+ time.tv_sec = 1;
+
+#ifdef notyet
+ /* Set up swap credentials. */
+ proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid);
+ proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid);
+ if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) >
+ NGROUPS)
+ proc0.p_ucred->cr_ngroups = NGROUPS;
+ for (i = 0; i < proc0.p_ucred->cr_ngroups; i++)
+ proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]);
+#endif
+
+ /*
+ * Do enough of ifconfig(8) so that the critical net interface can
+ * talk to the server.
+ */
+ if (error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0))
+ panic("nfs_mountroot: socreate: %d", error);
+ if (error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p))
+ panic("nfs_mountroot: SIOCAIFADDR: %d", error);
+ soclose(so);
+
+ /*
+ * If the gateway field is filled in, set it as the default route.
+ */
+ if (nd->mygateway.sin_len != 0) {
+ struct sockaddr_in mask, sin;
+
+ bzero((caddr_t)&mask, sizeof(mask));
+ sin = mask;
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(sin);
+ if (error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
+ (struct sockaddr *)&nd->mygateway,
+ (struct sockaddr *)&mask,
+ RTF_UP | RTF_GATEWAY, (struct rtentry **)0))
+ panic("nfs_mountroot: RTM_ADD: %d", error);
+ }
+
+ /*
+ * If swapping to an nfs node (indicated by swdevt[0].sw_dev == NODEV):
+ * Create a fake mount point just for the swap vnode so that the
+ * swap file can be on a different server from the rootfs.
+ */
+ if (swdevt[0].sw_dev == NODEV) {
+ nd->swap_args.fh = (nfsv2fh_t *)nd->swap_fh;
+ (void) nfs_mountdiskless(nd->swap_hostnam, "/swap", 0,
+ &nd->swap_saddr, &nd->swap_args, &vp);
+
+ /*
+ * Since the swap file is not the root dir of a file system,
+ * hack it to a regular file.
+ */
+ vp->v_type = VREG;
+ vp->v_flag = 0;
+ swapdev_vp = vp;
+ VREF(vp);
+ swdevt[0].sw_vp = vp;
+ swdevt[0].sw_nblks = ntohl(nd->swap_nblks);
+ } else if (bdevvp(swapdev, &swapdev_vp))
+ panic("nfs_mountroot: can't setup swapdev_vp");
+
+ /*
+ * Create the rootfs mount point.
+ */
+ nd->root_args.fh = (nfsv2fh_t *)nd->root_fh;
+ mp = nfs_mountdiskless(nd->root_hostnam, "/", MNT_RDONLY,
+ &nd->root_saddr, &nd->root_args, &vp);
+
+ if (vfs_lock(mp))
+ panic("nfs_mountroot: vfs_lock");
+ rootfs = mp;
+ mp->mnt_next = mp;
+ mp->mnt_prev = mp;
+ mp->mnt_vnodecovered = NULLVP;
+ vfs_unlock(mp);
+ rootvp = vp;
+
+ /*
+ * This is not really an nfs issue, but it is much easier to
+ * set hostname here and then let the "/etc/rc.xxx" files
+ * mount the right /var based upon its preset value.
+ */
+ bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN);
+ hostname[MAXHOSTNAMELEN - 1] = '\0';
+ for (i = 0; i < MAXHOSTNAMELEN; i++)
+ if (hostname[i] == '\0')
+ break;
+ hostnamelen = i;
+ inittodr(ntohl(nd->root_time));
+ return (0);
+}
+
+/*
+ * Internal version of mount system call for diskless setup.
+ */
+static struct mount *
+nfs_mountdiskless(path, which, mountflag, sin, args, vpp)
+ char *path;
+ char *which;
+ int mountflag;
+ struct sockaddr_in *sin;
+ struct nfs_args *args;
+ register struct vnode **vpp;
+{
+ register struct mount *mp;
+ register struct mbuf *m;
+ register int error;
+
+ mp = (struct mount *)malloc((u_long)sizeof(struct mount),
+ M_MOUNT, M_NOWAIT);
+ if (mp == NULL)
+ panic("nfs_mountroot: %s mount malloc", which);
+ mp->mnt_op = &nfs_vfsops;
+ mp->mnt_flag = mountflag;
+ mp->mnt_mounth = NULLVP;
+
+ MGET(m, MT_SONAME, M_DONTWAIT);
+ if (m == NULL)
+ panic("nfs_mountroot: %s mount mbuf", which);
+ bcopy((caddr_t)sin, mtod(m, caddr_t), sin->sin_len);
+ m->m_len = sin->sin_len;
+ nfsargs_ntoh(args);
+ if (error = mountnfs(args, mp, m, which, path, vpp))
+ panic("nfs_mountroot: mount %s on %s: %d", path, which, error);
+
+ return (mp);
+}
+
+/*
+ * Convert the integer fields of the nfs_args structure from net byte order
+ * to host byte order. Called by nfs_mountroot() above.
+ */
+void
+nfsargs_ntoh(nfsp)
+ register struct nfs_args *nfsp;
+{
+
+ NTOHL(nfsp->sotype);
+ NTOHL(nfsp->proto);
+ NTOHL(nfsp->flags);
+ NTOHL(nfsp->wsize);
+ NTOHL(nfsp->rsize);
+ NTOHL(nfsp->timeo);
+ NTOHL(nfsp->retrans);
+ NTOHL(nfsp->maxgrouplist);
+ NTOHL(nfsp->readahead);
+ NTOHL(nfsp->leaseterm);
+ NTOHL(nfsp->deadthresh);