]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/netboot.c
xnu-1228.7.58.tar.gz
[apple/xnu.git] / bsd / kern / netboot.c
index ce58ad6192cb802a6254bae9aff8ab26bed59e96..3f2c11a86de83e4092e74cd27a0deeb7d3136d17 100644 (file)
@@ -1,16 +1,19 @@
 /*
- * Copyright (c) 2001 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2001-2006 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
@@ -20,7 +23,7 @@
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
 /*
 #include <sys/kernel.h>
 #include <sys/conf.h>
 #include <sys/ioctl.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
+#include <sys/proc_internal.h>
+#include <sys/mount_internal.h>
 #include <sys/mbuf.h>
 #include <sys/filedesc.h>
-#include <sys/vnode.h>
+#include <sys/vnode_internal.h>
 #include <sys/malloc.h>
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 #include <sys/reboot.h>
+#include <sys/kauth.h>
 #include <net/if.h>
 #include <net/if_dl.h>
 #include <net/if_types.h>
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 #include <netinet/dhcp_options.h>
+#include <netinet/in_dhcp.h>
 
+#include <kern/kern_types.h>
+#include <kern/kalloc.h>
 
-//#include <libkern/libkern.h>
+#include <pexpert/pexpert.h>
 
-extern dev_t           rootdev;                /* device of the root */
+//#include <libkern/libkern.h>
 extern struct filedesc         filedesc0;
 
-extern char *  strchr(const char *str, int ch);
-
-extern int     nfs_mountroot();        /* nfs_vfsops.c */
+extern int     nfs_mountroot(void);    /* nfs_vfsops.c */
 extern int (*mountroot)(void);
 
 extern unsigned char   rootdevice[];
@@ -66,32 +72,35 @@ static int                  S_netboot = 0;
 static struct netboot_info *   S_netboot_info_p;
 
 void *
-IOBSDRegistryEntryForDeviceTree(char * path);
+IOBSDRegistryEntryForDeviceTree(const char * path);
 
 void
 IOBSDRegistryEntryRelease(void * entry);
 
 const void *
-IOBSDRegistryEntryGetData(void * entry, char * property_name, 
+IOBSDRegistryEntryGetData(void * entry, const char * property_name, 
                          int * packet_length);
 
 extern int vndevice_root_image(const char * path, char devname[], 
                               dev_t * dev_p);
 extern int di_root_image(const char *path, char devname[], dev_t *dev_p);
 
-
-static boolean_t path_getfile __P((char * image_path, 
-                                  struct sockaddr_in * sin_p, 
-                                  char * serv_name, char * pathname));
-
 #define BOOTP_RESPONSE "bootp-response"
 #define BSDP_RESPONSE  "bsdp-response"
 #define DHCP_RESPONSE  "dhcp-response"
 
-extern int 
-bootp(struct ifnet * ifp, struct in_addr * iaddr_p, int max_retry,
-      struct in_addr * netmask_p, struct in_addr * router_p,
-      struct proc * procp);
+/* forward declarations */
+int    inet_aton(char * cp, struct in_addr * pin);
+
+boolean_t      netboot_iaddr(struct in_addr * iaddr_p);
+boolean_t      netboot_rootpath(struct in_addr * server_ip,
+                                char * name, int name_len, 
+                                char * path, int path_len);
+int    netboot_setup(void);
+int    netboot_mountroot(void);
+int    netboot_root(void);
+
+
 
 #define IP_FORMAT      "%d.%d.%d.%d"
 #define IP_CH(ip)      ((u_char *)ip)
@@ -122,7 +131,7 @@ struct netboot_info {
 int
 inet_aton(char * cp, struct in_addr * pin)
 {
-    u_char * b = (char *)pin;
+    u_char * b = (u_char *)pin;
     int           i;
     char * p;
 
@@ -152,7 +161,7 @@ inet_aton(char * cp, struct in_addr * pin)
  *   "17.202.16.17:seaport:/release/.images/Image9/CurrentHera"
  */
 static __inline__ boolean_t
-parse_booter_path(char * path, struct in_addr * iaddr_p, char * * host,
+parse_booter_path(char * path, struct in_addr * iaddr_p, char const * * host,
                  char * * mount_dir, char * * image_path)
 {
     char *     start;
@@ -239,9 +248,10 @@ find_colon(char * str)
  * nfs:17.202.42.112:/Volumes/Foo\:/Library/NetBoot/NetBootSP0:Jaguar/Jaguar.dmg
  */
 static __inline__ boolean_t
-parse_netboot_path(char * path, struct in_addr * iaddr_p, char * * host,
+parse_netboot_path(char * path, struct in_addr * iaddr_p, char const * * host,
                   char * * mount_dir, char * * image_path)
 {
+       static char     tmp[MAX_IPv4_STR_LEN];  /* Danger - not thread safe */
     char *     start;
     char *     colon;
 
@@ -275,12 +285,12 @@ parse_netboot_path(char * path, struct in_addr * iaddr_p, char * * host,
        (void)find_colon(start);
        *image_path = start;
     }
-    *host = inet_ntoa(*iaddr_p);
+    *host = inet_ntop(AF_INET, iaddr_p, tmp, sizeof(tmp));
     return (TRUE);
 }
 
 static boolean_t
-parse_image_path(char * path, struct in_addr * iaddr_p, char * * host,
+parse_image_path(char * path, struct in_addr * iaddr_p, char const * * host,
                 char * * mount_dir, char * * image_path)
 {
     if (path[0] >= '0' && path[0] <= '9') {
@@ -304,29 +314,29 @@ get_root_path(char * root_path)
        return (FALSE);
     }
     pkt = IOBSDRegistryEntryGetData(entry, BSDP_RESPONSE, &pkt_len);
-    if (pkt != NULL && pkt_len >= sizeof(struct dhcp)) {
+    if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
        printf("netboot: retrieving root path from BSDP response\n");
     }
     else {
        pkt = IOBSDRegistryEntryGetData(entry, BOOTP_RESPONSE, 
                                        &pkt_len);
-       if (pkt != NULL && pkt_len >= sizeof(struct dhcp)) {
+       if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
            printf("netboot: retrieving root path from BOOTP response\n");
        }
     }
     if (pkt != NULL) {
        int                     len;
        dhcpol_t                options;
-       char *                  path;
-       struct dhcp *           reply;
+       const char *            path;
+       const struct dhcp *     reply;
 
-       reply = (struct dhcp *)pkt;
-       (void)dhcpol_parse_packet(&options, reply, pkt_len, NULL);
+       reply = (const struct dhcp *)pkt;
+       (void)dhcpol_parse_packet(&options, reply, pkt_len);
 
-       path = (char *)dhcpol_find(&options, 
-                                  dhcptag_root_path_e, &len, NULL);
+       path = (const char *)dhcpol_find(&options, 
+                                        dhcptag_root_path_e, &len, NULL);
        if (path) {
-           bcopy(path, root_path, len);
+           memcpy(root_path, path, len);
            root_path[len] = '\0';
            found = TRUE;
        }
@@ -345,10 +355,12 @@ netboot_info_init(struct in_addr iaddr)
     char *                     vndevice = NULL;
 
     MALLOC_ZONE(vndevice, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
-    if (PE_parse_boot_arg("vndevice", vndevice) == TRUE) {
+    if (vndevice == NULL)
+       panic("netboot_info_init: M_NAMEI zone exhausted");
+    if (PE_parse_boot_argn("vndevice", vndevice, MAXPATHLEN) == TRUE) {
        use_hdix = FALSE;
     }
-    _FREE_ZONE(vndevice, MAXPATHLEN, M_NAMEI);
+    FREE_ZONE(vndevice, MAXPATHLEN, M_NAMEI);
 
     info = (struct netboot_info *)kalloc(sizeof(*info));
     bzero(info, sizeof(*info));
@@ -358,10 +370,12 @@ netboot_info_init(struct in_addr iaddr)
 
     /* check for a booter-specified path then a NetBoot path */
     MALLOC_ZONE(root_path, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
-    if (PE_parse_boot_arg("rp", root_path) == TRUE
-       || PE_parse_boot_arg("rootpath", root_path) == TRUE
+    if (root_path  == NULL)
+       panic("netboot_info_init: M_NAMEI zone exhausted");
+    if (PE_parse_boot_argn("rp", root_path, MAXPATHLEN) == TRUE
+       || PE_parse_boot_argn("rootpath", root_path, MAXPATHLEN) == TRUE
        || get_root_path(root_path) == TRUE) {
-       char * server_name = NULL;
+       const char * server_name = NULL;
        char * mount_point = NULL;
        char * image_path = NULL;
        struct in_addr  server_ip;
@@ -374,13 +388,13 @@ netboot_info_init(struct in_addr iaddr)
            info->server_name = (char *)kalloc(info->server_name_length);
            info->mount_point_length = strlen(mount_point) + 1;
            info->mount_point = (char *)kalloc(info->mount_point_length);
-           strcpy(info->server_name, server_name);
-           strcpy(info->mount_point, mount_point);
+           strlcpy(info->server_name, server_name, info->server_name_length);
+           strlcpy(info->mount_point, mount_point, info->mount_point_length);
            
            printf("Server %s Mount %s", 
                   server_name, info->mount_point);
            if (image_path != NULL) {
-               boolean_t       needs_slash;
+               boolean_t       needs_slash = FALSE;
 
                info->image_path_length = strlen(image_path) + 1;
                if (image_path[0] != '/') {
@@ -389,11 +403,12 @@ netboot_info_init(struct in_addr iaddr)
                }
                info->image_path = (char *)kalloc(info->image_path_length);
                if (needs_slash) {
-                   info->image_path[0] = '/';
-                   strcpy(info->image_path + 1, image_path);
-               }
-               else {
-                   strcpy(info->image_path, image_path);
+                       info->image_path[0] = '/';
+                       strlcpy(info->image_path + 1, image_path,
+                                       info->image_path_length - 1);
+               } else {
+                       strlcpy(info->image_path, image_path,
+                                       info->image_path_length);
                }
                printf(" Image %s", info->image_path);
            }
@@ -406,13 +421,13 @@ netboot_info_init(struct in_addr iaddr)
            info->use_hdix = TRUE;
            info->image_path_length = strlen(root_path) + 1;
            info->image_path = (char *)kalloc(info->image_path_length);
-           strcpy(info->image_path, root_path);
+           strlcpy(info->image_path, root_path, info->image_path_length);
        }           
        else {
            printf("netboot: root path uses unrecognized format\n");
        }
     }
-    _FREE_ZONE(root_path, MAXPATHLEN, M_NAMEI);
+    FREE_ZONE(root_path, MAXPATHLEN, M_NAMEI);
     return (info);
 }
 
@@ -466,8 +481,8 @@ netboot_rootpath(struct in_addr * server_ip,
               path_len, S_netboot_info_p->mount_point_length);
        return (FALSE);
     }
-    strcpy(path, S_netboot_info_p->mount_point);
-    strncpy(name, S_netboot_info_p->server_name, name_len);
+    strlcpy(path, S_netboot_info_p->mount_point, path_len);
+    strlcpy(name, S_netboot_info_p->server_name, name_len);
     *server_ip = S_netboot_info_p->server_ip;
     return (TRUE);
 }
@@ -487,31 +502,31 @@ get_ip_parameters(struct in_addr * iaddr_p, struct in_addr * netmask_p,
        return (FALSE);
     }
     pkt = IOBSDRegistryEntryGetData(entry, DHCP_RESPONSE, &pkt_len);
-    if (pkt != NULL && pkt_len >= sizeof(struct dhcp)) {
+    if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
        printf("netboot: retrieving IP information from DHCP response\n");
     }
     else {
        pkt = IOBSDRegistryEntryGetData(entry, BOOTP_RESPONSE, &pkt_len);
-       if (pkt != NULL && pkt_len >= sizeof(struct dhcp)) {
+       if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
            printf("netboot: retrieving IP information from BOOTP response\n");
        }
     }
     if (pkt != NULL) {
-       struct in_addr *        ip;
+       const struct in_addr *  ip;
        int                     len;
        dhcpol_t                options;
-       struct dhcp *           reply;
+       const struct dhcp *     reply;
 
-       reply = (struct dhcp *)pkt;
-       (void)dhcpol_parse_packet(&options, reply, pkt_len, NULL);
+       reply = (const struct dhcp *)pkt;
+       (void)dhcpol_parse_packet(&options, reply, pkt_len);
        *iaddr_p = reply->dp_yiaddr;
-       ip = (struct in_addr *)
+       ip = (const struct in_addr *)
            dhcpol_find(&options, 
                        dhcptag_subnet_mask_e, &len, NULL);
        if (ip) {
            *netmask_p = *ip;
        }
-       ip = (struct in_addr *)
+       ip = (const struct in_addr *)
            dhcpol_find(&options, dhcptag_router_e, &len, NULL);
        if (ip) {
            *router_p = *ip;
@@ -522,98 +537,91 @@ get_ip_parameters(struct in_addr * iaddr_p, struct in_addr * netmask_p,
 }
 
 static int
-inet_aifaddr(struct socket * so, char * name, const struct in_addr * addr, 
-            const struct in_addr * mask,
-            const struct in_addr * broadcast)
-{
-    struct sockaddr    blank_sin = { sizeof(blank_sin), AF_INET };
-    struct ifaliasreq  ifra;
-
-    bzero(&ifra, sizeof(ifra));
-    strncpy(ifra.ifra_name, name, sizeof(ifra.ifra_name));
-    if (addr) {
-       ifra.ifra_addr = blank_sin;
-       ((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr = *addr;
-    }
-    if (mask) {
-       ifra.ifra_mask = blank_sin;
-       ((struct sockaddr_in *)&ifra.ifra_mask)->sin_addr = *mask;
-    }
-    if (broadcast) {
-       ifra.ifra_broadaddr = blank_sin;
-       ((struct sockaddr_in *)&ifra.ifra_broadaddr)->sin_addr = *broadcast;
-    }
-    return (ifioctl(so, SIOCAIFADDR, (caddr_t)&ifra, current_proc()));
-}
-
-static int
-default_route_add(struct in_addr router, boolean_t proxy_arp)
+route_cmd(int cmd, struct in_addr d, struct in_addr g, 
+         struct in_addr m, u_long more_flags)
 {
     struct sockaddr_in                 dst;
     u_long                     flags = RTF_UP | RTF_STATIC;
     struct sockaddr_in         gw;
     struct sockaddr_in         mask;
     
-    if (proxy_arp == FALSE) {
-       flags |= RTF_GATEWAY;
-    }
+    flags |= more_flags;
 
-    /* dest 0.0.0.0 */
+    /* destination */
     bzero((caddr_t)&dst, sizeof(dst));
     dst.sin_len = sizeof(dst);
     dst.sin_family = AF_INET;
+    dst.sin_addr = d;
 
     /* gateway */
     bzero((caddr_t)&gw, sizeof(gw));
     gw.sin_len = sizeof(gw);
     gw.sin_family = AF_INET;
-    gw.sin_addr = router;
+    gw.sin_addr = g;
 
-    /* mask 0.0.0.0 */
+    /* mask */
     bzero(&mask, sizeof(mask));
     mask.sin_len = sizeof(mask);
     mask.sin_family = AF_INET;
+    mask.sin_addr = m;
 
-    printf("netboot: adding default route " IP_FORMAT "\n", 
-          IP_LIST(&router));
-
-    return (rtrequest(RTM_ADD, (struct sockaddr *)&dst, (struct sockaddr *)&gw,
+    return (rtrequest(cmd, (struct sockaddr *)&dst, (struct sockaddr *)&gw,
                      (struct sockaddr *)&mask, flags, NULL));
 }
 
+static int
+default_route_add(struct in_addr router, boolean_t proxy_arp)
+{
+    u_long                     flags = 0;
+    struct in_addr             zeroes = { 0 };
+    
+    if (proxy_arp == FALSE) {
+       flags |= RTF_GATEWAY;
+    }
+    return (route_cmd(RTM_ADD, zeroes, router, zeroes, flags));
+}
+
+static int
+host_route_delete(struct in_addr host)
+{
+    struct in_addr             zeroes = { 0 };
+    
+    return (route_cmd(RTM_DELETE, host, zeroes, zeroes, RTF_HOST));
+}
+
 static struct ifnet *
-find_interface()
+find_interface(void)
 {
     struct ifnet *             ifp = NULL;
 
     if (rootdevice[0]) {
-       ifp = ifunit(rootdevice);
+               ifp = ifunit((char *)rootdevice);
     }
     if (ifp == NULL) {
-       TAILQ_FOREACH(ifp, &ifnet, if_link)
-           if ((ifp->if_flags &
-                (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
-               break;
+               ifnet_head_lock_shared();
+               TAILQ_FOREACH(ifp, &ifnet_head, if_link)
+                       if ((ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
+                               break;
+               ifnet_head_done();
     }
     return (ifp);
 }
 
 int
-netboot_mountroot()
+netboot_mountroot(void)
 {
     int                        error = 0;
     struct in_addr             iaddr = { 0 };
     struct ifreq               ifr;
     struct ifnet *             ifp;
     struct in_addr             netmask = { 0 };
-    struct proc *              procp = current_proc();
+    proc_t                     procp = current_proc();
     struct in_addr             router = { 0 };
     struct socket *            so = NULL;
+    unsigned int               try;
 
     bzero(&ifr, sizeof(ifr));
 
-    thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
-
     /* find the interface */
     ifp = find_interface();
     if (ifp == NULL) {
@@ -621,7 +629,8 @@ netboot_mountroot()
        error = ENXIO;
        goto failed;
     }
-    sprintf(ifr.ifr_name, "%s%d", ifp->if_name, ifp->if_unit);
+    snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", ifp->if_name,
+            ifp->if_unit);
     printf("netboot: using network interface '%s'\n", ifr.ifr_name);
 
     /* bring it up */
@@ -638,10 +647,10 @@ netboot_mountroot()
 
     /* grab information from the registry */
     if (get_ip_parameters(&iaddr, &netmask, &router) == FALSE) {
-       /* use BOOTP to retrieve IP address, netmask and router */
-       error = bootp(ifp, &iaddr, 32, &netmask, &router, procp);
+       /* use DHCP to retrieve IP address, netmask and router */
+       error = dhcp(ifp, &iaddr, 64, &netmask, &router, procp);
        if (error) {
-           printf("netboot: BOOTP failed %d\n", error);
+           printf("netboot: DHCP failed %d\n", error);
            goto failed;
        }
     }
@@ -662,22 +671,59 @@ netboot_mountroot()
        /* enable proxy arp if we don't have a router */
        router.s_addr = iaddr.s_addr;
     }
+    printf("netboot: adding default route " IP_FORMAT "\n", 
+          IP_LIST(&router));
     error = default_route_add(router, router.s_addr == iaddr.s_addr);
     if (error) {
        printf("netboot: default_route_add failed %d\n", error);
     }
 
     soclose(so);
-    thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
 
     S_netboot_info_p = netboot_info_init(iaddr);
     switch (S_netboot_info_p->image_type) {
     default:
     case kNetBootImageTypeNFS:
-       error = nfs_mountroot();
+       for (try = 1; TRUE; try++) {
+           error = nfs_mountroot();
+           if (error == 0) {
+               break;
+           }
+           printf("netboot: nfs_mountroot() attempt %u failed; "
+                  "clearing ARP entry and trying again\n", try);
+           /* 
+            * error is either EHOSTDOWN or EHOSTUNREACH, which likely means
+            * that the port we're plugged into has spanning tree enabled,
+            * and either the router or the server can't answer our ARP
+            * requests.  Clear the incomplete ARP entry by removing the
+            * appropriate route, depending on the error code:
+            *     EHOSTDOWN            NFS server's route
+            *     EHOSTUNREACH         router's route
+            */
+           switch (error) {
+           default:
+               /* NOT REACHED */
+           case EHOSTDOWN:
+               /* remove the server's arp entry */
+               error = host_route_delete(S_netboot_info_p->server_ip);
+               if (error) {
+                   printf("netboot: host_route_delete(" IP_FORMAT
+                          ") failed %d\n", 
+                          IP_LIST(&S_netboot_info_p->server_ip), error);
+               }
+               break;
+           case EHOSTUNREACH:
+               error = host_route_delete(router);
+               if (error) {
+                   printf("netboot: host_route_delete(" IP_FORMAT
+                          ") failed %d\n", IP_LIST(&router), error);
+               }
+               break;
+           }
+       }
        break;
     case kNetBootImageTypeHTTP:
-       error = netboot_setup(procp);
+       error = netboot_setup();
        break;
     }
     if (error == 0) {
@@ -691,12 +737,11 @@ failed:
     if (so != NULL) {
        soclose(so);
     }
-    thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
     return (error);
 }
 
 int
-netboot_setup(struct proc * p)
+netboot_setup()
 {
     dev_t      dev;
     int        error = 0;
@@ -708,7 +753,7 @@ netboot_setup(struct proc * p)
     if (S_netboot_info_p->use_hdix) {
        printf("netboot_setup: calling di_root_image\n");
        error = di_root_image(S_netboot_info_p->image_path, 
-                             rootdevice, &dev);
+                             (char *)rootdevice, &dev);
        if (error) {
            printf("netboot_setup: di_root_image: failed %d\n", error);
            goto done;
@@ -717,7 +762,7 @@ netboot_setup(struct proc * p)
     else {
        printf("netboot_setup: calling vndevice_root_image\n");
        error = vndevice_root_image(S_netboot_info_p->image_path, 
-                                   rootdevice, &dev);
+                                   (char *)rootdevice, &dev);
        if (error) {
            printf("netboot_setup: vndevice_root_image: failed %d\n", error);
            goto done;
@@ -732,18 +777,18 @@ netboot_setup(struct proc * p)
         struct vnode *newdp;
 
        /* Get the vnode for '/'.  Set fdp->fd_fd.fd_cdir to reference it. */
-       if (VFS_ROOT(mountlist.cqh_last, &newdp))
+       if (VFS_ROOT(TAILQ_LAST(&mountlist,mntlist), &newdp, vfs_context_kernel()))
                panic("netboot_setup: cannot find root vnode");
-       VREF(newdp);
+       vnode_ref(newdp);
+       vnode_put(newdp);
        tvp = rootvnode;
-       vrele(tvp);
+       vnode_rele(tvp);
        filedesc0.fd_cdir = newdp;
        rootvnode = newdp;
-       simple_lock(&mountlist_slock);
-       CIRCLEQ_REMOVE(&mountlist, CIRCLEQ_FIRST(&mountlist), mnt_list);
-       simple_unlock(&mountlist_slock);
-       VOP_UNLOCK(rootvnode, 0, p);
-       mountlist.cqh_first->mnt_flag |= MNT_ROOTFS;
+       mount_list_lock();
+       TAILQ_REMOVE(&mountlist, TAILQ_FIRST(&mountlist), mnt_list);
+       mount_list_unlock();
+       mountlist.tqh_first->mnt_flag |= MNT_ROOTFS;
     }
  done:
     netboot_info_free(&S_netboot_info_p);
@@ -751,7 +796,7 @@ netboot_setup(struct proc * p)
 }
 
 int
-netboot_root()
+netboot_root(void)
 {
     return (S_netboot);
 }