autoconf.c revision 65500
14Srgrimes/*- 24Srgrimes * Copyright (c) 1990 The Regents of the University of California. 34Srgrimes * All rights reserved. 44Srgrimes * 54Srgrimes * This code is derived from software contributed to Berkeley by 64Srgrimes * William Jolitz. 74Srgrimes * 84Srgrimes * Redistribution and use in source and binary forms, with or without 94Srgrimes * modification, are permitted provided that the following conditions 104Srgrimes * are met: 114Srgrimes * 1. Redistributions of source code must retain the above copyright 124Srgrimes * notice, this list of conditions and the following disclaimer. 134Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 144Srgrimes * notice, this list of conditions and the following disclaimer in the 154Srgrimes * documentation and/or other materials provided with the distribution. 164Srgrimes * 3. All advertising materials mentioning features or use of this software 174Srgrimes * must display the following acknowledgement: 184Srgrimes * This product includes software developed by the University of 194Srgrimes * California, Berkeley and its contributors. 204Srgrimes * 4. Neither the name of the University nor the names of its contributors 214Srgrimes * may be used to endorse or promote products derived from this software 224Srgrimes * without specific prior written permission. 234Srgrimes * 244Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344Srgrimes * SUCH DAMAGE. 354Srgrimes * 36620Srgrimes * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 3750477Speter * $FreeBSD: head/sys/i386/i386/autoconf.c 65500 2000-09-05 22:34:11Z msmith $ 384Srgrimes */ 394Srgrimes 404Srgrimes/* 414Srgrimes * Setup the system to run on the current machine. 424Srgrimes * 438876Srgrimes * Configure() is called at boot time and initializes the vba 444Srgrimes * device tables and the memory controller monitoring. Available 454Srgrimes * devices are determined (from possibilities mentioned in ioconf.c), 464Srgrimes * and the drivers are initialized. 474Srgrimes */ 4832358Seivind#include "opt_bootp.h" 4932726Seivind#include "opt_ffs.h" 5025460Sjoerg#include "opt_cd9660.h" 5153888Sdillon#include "opt_nfs.h" 5237272Sjmg#include "opt_nfsroot.h" 5345720Speter#include "opt_bus.h" 5446806Sphk#include "opt_rootdevname.h" 5525164Speter 5655117Sbde#include "isa.h" 5755117Sbde 582056Swollman#include <sys/param.h> 592056Swollman#include <sys/systm.h> 6045720Speter#include <sys/bus.h> 612056Swollman#include <sys/conf.h> 6231328Speter#include <sys/disklabel.h> 6336809Sbde#include <sys/diskslice.h> 642056Swollman#include <sys/reboot.h> 652056Swollman#include <sys/kernel.h> 6636809Sbde#include <sys/malloc.h> 6712604Sbde#include <sys/mount.h> 6849558Sphk#include <sys/cons.h> 694Srgrimes 7020641Sbde#include <machine/bootinfo.h> 7131337Sbde#include <machine/ipl.h> 727090Sbde#include <machine/md_var.h> 7327288Sfsmp#ifdef APIC_IO 7425164Speter#include <machine/smp.h> 7550197Speter#else 7650197Speter#include <i386/isa/icu.h> 7725164Speter#endif /* APIC_IO */ 7827288Sfsmp 7955117Sbde#if NISA > 0 8050769Sdfr#include <isa/isavar.h> 8155117Sbde 8246915Speterdevice_t isa_bus_device = 0; 8355117Sbde#endif 8446915Speter 8542817Speterstatic void configure_first __P((void *)); 8612604Sbdestatic void configure __P((void *)); 8742817Speterstatic void configure_final __P((void *)); 8812604Sbde 8952778Smsmith#if defined(FFS) && defined(FFS_ROOT) 9012848Sbdestatic void setroot __P((void)); 9147444Sjb#endif 9212848Sbde 9365500Smsmith#if defined(NFS) && defined(NFS_ROOT) 9465500Smsmithstatic void pxe_setup_nfsdiskless(void); 9565500Smsmith#endif 9665500Smsmith 9742817SpeterSYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL); 9842817Speter/* SI_ORDER_SECOND is hookable */ 9942817SpeterSYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL); 10042817Speter/* SI_ORDER_MIDDLE is hookable */ 10142817SpeterSYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL); 10242817Speter 10346806Sphkdev_t rootdev = NODEV; 10446806Sphkdev_t dumpdev = NODEV; 10542817Speter 10645720Speterdevice_t nexus_dev; 10745720Speter 1084Srgrimes/* 1094Srgrimes * Determine i/o configuration for a machine. 1104Srgrimes */ 11110665Sbdestatic void 11242817Speterconfigure_first(dummy) 11342817Speter void *dummy; 11442817Speter{ 11542817Speter} 11642817Speter 11742817Speterstatic void 11810665Sbdeconfigure(dummy) 11910653Sdg void *dummy; 1204Srgrimes{ 1214Srgrimes 12229675Sgibbs /* 12350184Speter * Activate the ICU's. Note that we are explicitly at splhigh() 12450184Speter * at present as we have no way to disable stray PCI level triggered 12550184Speter * interrupts until the devices have had a driver attached. This 12650184Speter * is particularly a problem when the interrupts are shared. For 12750184Speter * example, if IRQ 10 is shared between a disk and network device 12850184Speter * and the disk device generates an interrupt, if we "activate" 12950184Speter * IRQ 10 when the network driver is set up, then we will get 13050184Speter * recursive interrupt 10's as nothing will know how to turn off 13150184Speter * the disk device's interrupt. 13250184Speter * 13350184Speter * Having the ICU's active means we can probe interrupt routing to 13450184Speter * see if a device causes the corresponding pending bit to be set. 13550184Speter * 13650184Speter * This is all rather inconvenient. 13729675Sgibbs */ 13827288Sfsmp#ifdef APIC_IO 13927288Sfsmp bsp_apic_configure(); 14025172Speter enable_intr(); 14127288Sfsmp#else 14227288Sfsmp enable_intr(); 14325172Speter INTREN(IRQ_SLAVE); 14427288Sfsmp#endif /* APIC_IO */ 14512791Sgibbs 14645720Speter /* nexus0 is the top of the i386 device tree */ 14754073Smdodd device_add_child(root_bus, "nexus", 0); 14812791Sgibbs 14938779Snsouch /* initialize new bus architecture */ 15038779Snsouch root_bus_configure(); 15138779Snsouch 15250769Sdfr#if NISA > 0 15350184Speter /* 15450184Speter * Explicitly probe and attach ISA last. The isa bus saves 15550184Speter * it's device node at attach time for us here. 15650184Speter */ 15745720Speter if (isa_bus_device) 15850769Sdfr isa_probe_children(isa_bus_device); 15950769Sdfr#endif 16045720Speter 16131336Sbde /* 16231336Sbde * Now we're ready to handle (pending) interrupts. 16331336Sbde * XXX this is slightly misplaced. 16431336Sbde */ 16531336Sbde spl0(); 16631336Sbde 16731337Sbde /* 16831337Sbde * Allow lowering of the ipl to the lowest kernel level if we 16931337Sbde * panic (or call tsleep() before clearing `cold'). No level is 17031337Sbde * completely safe (since a panic may occur in a critical region 17131337Sbde * at splhigh()), but we want at least bio interrupts to work. 17231337Sbde */ 17331337Sbde safepri = cpl; 17442817Speter} 17531337Sbde 17642817Speterstatic void 17742817Speterconfigure_final(dummy) 17842817Speter void *dummy; 17942817Speter{ 18042817Speter int i; 18122564Sbde 18210665Sbde cninit_finish(); 18310665Sbde 18420641Sbde if (bootverbose) { 18527561Sfsmp 18627561Sfsmp#ifdef APIC_IO 18727615Sfsmp imen_dump(); 18827561Sfsmp#endif /* APIC_IO */ 18927561Sfsmp 19020641Sbde /* 19120641Sbde * Print out the BIOS's idea of the disk geometries. 19220641Sbde */ 19320641Sbde printf("BIOS Geometries:\n"); 19420641Sbde for (i = 0; i < N_BIOS_GEOM; i++) { 19520641Sbde unsigned long bios_geom; 19620641Sbde int max_cylinder, max_head, max_sector; 19720641Sbde 19820641Sbde bios_geom = bootinfo.bi_bios_geom[i]; 19920641Sbde 20020641Sbde /* 20120641Sbde * XXX the bootstrap punts a 1200K floppy geometry 20220641Sbde * when the get-disk-geometry interrupt fails. Skip 20320641Sbde * drives that have this geometry. 20420641Sbde */ 20520641Sbde if (bios_geom == 0x4f010f) 20620641Sbde continue; 20720641Sbde 20820641Sbde printf(" %x:%08lx ", i, bios_geom); 20920641Sbde max_cylinder = bios_geom >> 16; 21020641Sbde max_head = (bios_geom >> 8) & 0xff; 21120641Sbde max_sector = bios_geom & 0xff; 21220641Sbde printf( 21320641Sbde "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", 21420641Sbde max_cylinder, max_cylinder + 1, 21520641Sbde max_head, max_head + 1, 21620641Sbde max_sector, max_sector); 21720641Sbde } 21820641Sbde printf(" %d accounted for\n", bootinfo.bi_n_bios_used); 21920641Sbde 22016075Sjoerg printf("Device configuration finished.\n"); 22120641Sbde } 22229675Sgibbs cold = 0; 22329675Sgibbs} 22416075Sjoerg 22553888Sdillon#ifdef BOOTP 22653888Sdillonextern void bootpc_init(void); 22753888Sdillon#endif 22852778Smsmith/* 22952778Smsmith * Do legacy root filesystem discovery. 23052778Smsmith */ 23129675Sgibbsvoid 23229675Sgibbscpu_rootconf() 23329675Sgibbs{ 23453888Sdillon#ifdef BOOTP 23553888Sdillon bootpc_init(); 23653888Sdillon#endif 23752778Smsmith#if defined(NFS) && defined(NFS_ROOT) 23852778Smsmith#if !defined(BOOTP_NFSROOT) 23965500Smsmith pxe_setup_nfsdiskless(); 24052778Smsmith if (nfs_diskless_valid) 2417731Sphk#endif 24252778Smsmith rootdevnames[0] = "nfs:"; 2434Srgrimes#endif 24452778Smsmith#if defined(FFS) && defined(FFS_ROOT) 24553888Sdillon if (!rootdevnames[0]) 24653888Sdillon setroot(); 24752778Smsmith#endif 24829675Sgibbs} 24952778SmsmithSYSINIT(cpu_rootconf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, cpu_rootconf, NULL) 25017355Sbde 2518833Sdgu_long bootdev = 0; /* not a dev_t - encoding is different */ 2524Srgrimes 25352778Smsmith#if defined(FFS) && defined(FFS_ROOT) 25452778Smsmith#define FDMAJOR 2 2551290Sache#define FDUNITSHIFT 6 2564Srgrimes 2574Srgrimes/* 2584Srgrimes * Attempt to find the device from which we were booted. 2594Srgrimes * If we can do so, and not instructed not to do so, 26036809Sbde * set rootdevs[] and rootdevnames[] to correspond to the 26136809Sbde * boot device(s). 26252778Smsmith * 26352778Smsmith * This code survives in order to allow the system to be 26452778Smsmith * booted from legacy environments that do not correctly 26552778Smsmith * populate the kernel environment. There are significant 26652778Smsmith * restrictions on the bootability of the system in this 26752778Smsmith * situation; it can only be mounting root from a 'da' 26852778Smsmith * 'wd' or 'fd' device, and the root filesystem must be ufs. 2694Srgrimes */ 270798Swollmanstatic void 2714Srgrimessetroot() 2724Srgrimes{ 27336809Sbde int majdev, mindev, unit, slice, part; 27446773Sphk dev_t newrootdev, dev; 27536809Sbde char partname[2]; 27636809Sbde char *sname; 2774Srgrimes 27848512Sphk if ((bootdev & B_MAGICMASK) != B_DEVMAGIC) { 27950268Sbde printf("no B_DEVMAGIC (bootdev=%#lx)\n", bootdev); 28046806Sphk return; 28148512Sphk } 28236809Sbde majdev = B_TYPE(bootdev); 28347680Sphk dev = makebdev(majdev, 0); 28461717Sphk if (devsw(dev) == NULL) 28536809Sbde return; 28636809Sbde unit = B_UNIT(bootdev); 28736809Sbde slice = B_SLICE(bootdev); 28836809Sbde if (slice == WHOLE_DISK_SLICE) 28934624Smsmith slice = COMPATIBILITY_SLICE; 29048512Sphk if (slice < 0 || slice >= MAX_SLICES) { 29148512Sphk printf("bad slice\n"); 2924Srgrimes return; 29348512Sphk } 29436809Sbde 29536809Sbde /* 29636809Sbde * XXX kludge for inconsistent unit numbering and lack of slice 29736809Sbde * support for floppies. 29836809Sbde */ 2991290Sache if (majdev == FDMAJOR) { 30036809Sbde slice = COMPATIBILITY_SLICE; 3012400Sache part = RAW_PART; 3021290Sache mindev = unit << FDUNITSHIFT; 30336809Sbde } else { 30436809Sbde part = B_PARTITION(bootdev); 30534622Smsmith mindev = dkmakeminor(unit, slice, part); 3061290Sache } 30736809Sbde 30847680Sphk newrootdev = makebdev(majdev, mindev); 30950511Sphk sname = dsname(newrootdev, unit, slice, part, partname); 31052778Smsmith rootdevnames[0] = malloc(strlen(sname) + 6, M_DEVBUF, M_NOWAIT); 31152778Smsmith sprintf(rootdevnames[0], "ufs:%s%s", sname, partname); 31236809Sbde 3134Srgrimes /* 31436809Sbde * For properly dangerously dedicated disks (ones with a historical 31536809Sbde * bogus partition table), the boot blocks will give slice = 4, but 31636809Sbde * the kernel will only provide the compatibility slice since it 31736809Sbde * knows that slice 4 is not a real slice. Arrange to try mounting 31836809Sbde * the compatibility slice as root if mounting the slice passed by 31936809Sbde * the boot blocks fails. This handles the dangerously dedicated 32036809Sbde * case and perhaps others. 3214Srgrimes */ 32236809Sbde if (slice == COMPATIBILITY_SLICE) 3234Srgrimes return; 32436809Sbde slice = COMPATIBILITY_SLICE; 32550511Sphk sname = dsname(newrootdev, unit, slice, part, partname); 32652778Smsmith rootdevnames[1] = malloc(strlen(sname) + 6, M_DEVBUF, M_NOWAIT); 32752778Smsmith sprintf(rootdevnames[1], "ufs:%s%s", sname, partname); 3284Srgrimes} 32947444Sjb#endif 33065500Smsmith 33165500Smsmith#if defined(NFS) && defined(NFS_ROOT) 33265500Smsmith 33365500Smsmith#include <sys/socket.h> 33465500Smsmith#include <net/if.h> 33565500Smsmith#include <net/if_dl.h> 33665500Smsmith#include <net/if_types.h> 33765500Smsmith#include <net/if_var.h> 33865500Smsmith#include <net/ethernet.h> 33965500Smsmith#include <netinet/in.h> 34065500Smsmith#include <nfs/rpcv2.h> 34165500Smsmith#include <nfs/nfsproto.h> 34265500Smsmith#include <nfs/nfs.h> 34365500Smsmith#include <nfs/nfsdiskless.h> 34465500Smsmith 34565500Smsmithextern struct nfs_diskless nfs_diskless; 34665500Smsmith 34765500Smsmithstatic int 34865500Smsmithinaddr_to_sockaddr(char *ev, struct sockaddr_in *sa) 34965500Smsmith{ 35065500Smsmith u_int32_t a[4]; 35165500Smsmith char *cp; 35265500Smsmith 35365500Smsmith bzero(sa, sizeof(*sa)); 35465500Smsmith sa->sin_len = sizeof(*sa); 35565500Smsmith sa->sin_family = AF_INET; 35665500Smsmith 35765500Smsmith if ((cp = getenv(ev)) == NULL) 35865500Smsmith return(1); 35965500Smsmith if (sscanf(cp, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) != 4) 36065500Smsmith return(1); 36165500Smsmith /* XXX is this ordering correct? */ 36265500Smsmith sa->sin_addr.s_addr = (a[3] << 24) + (a[2] << 16) + (a[1] << 8) + a[0]; 36365500Smsmith return(0); 36465500Smsmith} 36565500Smsmith 36665500Smsmithstatic int 36765500Smsmithhwaddr_to_sockaddr(char *ev, struct sockaddr_dl *sa) 36865500Smsmith{ 36965500Smsmith char *cp; 37065500Smsmith u_int32_t a[6]; 37165500Smsmith 37265500Smsmith bzero(sa, sizeof(*sa)); 37365500Smsmith sa->sdl_len = sizeof(*sa); 37465500Smsmith sa->sdl_family = AF_LINK; 37565500Smsmith sa->sdl_type = IFT_ETHER; 37665500Smsmith sa->sdl_alen = ETHER_ADDR_LEN; 37765500Smsmith if ((cp = getenv(ev)) == NULL) 37865500Smsmith return(1); 37965500Smsmith if (sscanf(cp, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]) != 6) 38065500Smsmith return(1); 38165500Smsmith sa->sdl_data[0] = a[0]; 38265500Smsmith sa->sdl_data[1] = a[1]; 38365500Smsmith sa->sdl_data[2] = a[2]; 38465500Smsmith sa->sdl_data[3] = a[3]; 38565500Smsmith sa->sdl_data[4] = a[4]; 38665500Smsmith sa->sdl_data[5] = a[5]; 38765500Smsmith return(0); 38865500Smsmith} 38965500Smsmith 39065500Smsmithstatic int 39165500Smsmithdecode_nfshandle(char *ev, u_char *fh) 39265500Smsmith{ 39365500Smsmith u_char *cp; 39465500Smsmith int len, val; 39565500Smsmith 39665500Smsmith if (((cp = getenv(ev)) == NULL) || (strlen(cp) < 2) || (*cp != 'X')) 39765500Smsmith return(0); 39865500Smsmith len = 0; 39965500Smsmith cp++; 40065500Smsmith for (;;) { 40165500Smsmith if (*cp == 'X') 40265500Smsmith return(len); 40365500Smsmith if ((sscanf(cp, "%2x", &val) != 1) || (val > 0xff)) 40465500Smsmith return(0); 40565500Smsmith *(fh++) = val; 40665500Smsmith len++; 40765500Smsmith cp += 2; 40865500Smsmith if (len > NFSX_V2FH) 40965500Smsmith return(0); 41065500Smsmith } 41165500Smsmith} 41265500Smsmith 41365500Smsmith/* 41465500Smsmith * Populate the essential fields in the nfsv3_diskless structure. 41565500Smsmith * 41665500Smsmith * The loader is expected to export the following environment variables: 41765500Smsmith * 41865500Smsmith * boot.netif.ip IP address on boot interface 41965500Smsmith * boot.netif.netmask netmask on boot interface 42065500Smsmith * boot.netif.gateway default gateway (optional) 42165500Smsmith * boot.netif.hwaddr hardware address of boot interface 42265500Smsmith * boot.nfsroot.server IP address of root filesystem server 42365500Smsmith * boot.nfsroot.path path of the root filesystem on server 42465500Smsmith * boot.nfsroot.nfshandle NFS handle for root filesystem on server 42565500Smsmith */ 42665500Smsmithstatic void 42765500Smsmithpxe_setup_nfsdiskless() 42865500Smsmith{ 42965500Smsmith struct nfs_diskless *nd = &nfs_diskless; 43065500Smsmith struct ifnet *ifp; 43165500Smsmith struct ifaddr *ifa; 43265500Smsmith struct sockaddr_dl *sdl, ourdl; 43365500Smsmith struct sockaddr_in myaddr, netmask; 43465500Smsmith char *cp; 43565500Smsmith 43665500Smsmith /* set up interface */ 43765500Smsmith if (inaddr_to_sockaddr("boot.netif.ip", &myaddr)) 43865500Smsmith return; 43965500Smsmith if (inaddr_to_sockaddr("boot.netif.netmask", &netmask)) { 44065500Smsmith printf("PXE: no netmask\n"); 44165500Smsmith return; 44265500Smsmith } 44365500Smsmith bcopy(&myaddr, &nd->myif.ifra_addr, sizeof(myaddr)); 44465500Smsmith bcopy(&myaddr, &nd->myif.ifra_broadaddr, sizeof(myaddr)); 44565500Smsmith ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = 44665500Smsmith myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr; 44765500Smsmith bcopy(&netmask, &nd->myif.ifra_mask, sizeof(netmask)); 44865500Smsmith 44965500Smsmith if (hwaddr_to_sockaddr("boot.netif.hwaddr", &ourdl)) { 45065500Smsmith printf("PXE: no hardware address\n"); 45165500Smsmith return; 45265500Smsmith } 45365500Smsmith ifa = NULL; 45465500Smsmith ifp = TAILQ_FIRST(&ifnet); 45565500Smsmith TAILQ_FOREACH(ifp, &ifnet, if_link) { 45665500Smsmith TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 45765500Smsmith if ((ifa->ifa_addr->sa_family == AF_LINK) && 45865500Smsmith (sdl = ((struct sockaddr_dl *)ifa->ifa_addr))) { 45965500Smsmith if ((sdl->sdl_type == ourdl.sdl_type) && 46065500Smsmith (sdl->sdl_alen == ourdl.sdl_alen) && 46165500Smsmith !bcmp(sdl->sdl_data + sdl->sdl_nlen, 46265500Smsmith ourdl.sdl_data + ourdl.sdl_nlen, 46365500Smsmith sdl->sdl_alen)) 46465500Smsmith goto match_done; 46565500Smsmith } 46665500Smsmith } 46765500Smsmith } 46865500Smsmith printf("PXE: no interface\n"); 46965500Smsmith return; /* no matching interface */ 47065500Smsmithmatch_done: 47165500Smsmith sprintf(nd->myif.ifra_name, "%s%d", ifp->if_name, ifp->if_unit); 47265500Smsmith 47365500Smsmith 47465500Smsmith /* set up gateway */ 47565500Smsmith inaddr_to_sockaddr("boot.netif.gateway", &nd->mygateway); 47665500Smsmith 47765500Smsmith /* XXX set up swap? */ 47865500Smsmith 47965500Smsmith /* set up root mount */ 48065500Smsmith nd->root_args.rsize = 8192; /* XXX tunable? */ 48165500Smsmith nd->root_args.wsize = 8192; 48265500Smsmith nd->root_args.sotype = SOCK_DGRAM; 48365500Smsmith nd->root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT); 48465500Smsmith if (inaddr_to_sockaddr("boot.nfsroot.server", &nd->root_saddr)) { 48565500Smsmith printf("PXE: no server\n"); 48665500Smsmith return; 48765500Smsmith } 48865500Smsmith nd->root_saddr.sin_port = htons(NFS_PORT); 48965500Smsmith if (decode_nfshandle("boot.nfsroot.nfshandle", &nd->root_fh[0]) == 0) { 49065500Smsmith printf("PXE: no NFS handle\n"); 49165500Smsmith return; 49265500Smsmith } 49365500Smsmith if ((cp = getenv("boot.nfsroot.path")) != NULL) 49465500Smsmith strncpy(nd->root_hostnam, cp, MNAMELEN - 1); 49565500Smsmith 49665500Smsmith nfs_diskless_valid = 1; 49765500Smsmith} 49865500Smsmith#endif 499