176ca3cb0SRobert Mustacchi /*
276ca3cb0SRobert Mustacchi * This file and its contents are supplied under the terms of the
376ca3cb0SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
476ca3cb0SRobert Mustacchi * You may only use this file in accordance with the terms of version
576ca3cb0SRobert Mustacchi * 1.0 of the CDDL.
676ca3cb0SRobert Mustacchi *
776ca3cb0SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
876ca3cb0SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
976ca3cb0SRobert Mustacchi * http://www.illumos.org/license/CDDL.
1076ca3cb0SRobert Mustacchi */
1176ca3cb0SRobert Mustacchi
1276ca3cb0SRobert Mustacchi /*
1376ca3cb0SRobert Mustacchi * Copyright (c) 2015 Joyent, Inc. All rights reserved.
1476ca3cb0SRobert Mustacchi */
1576ca3cb0SRobert Mustacchi
1676ca3cb0SRobert Mustacchi /*
1776ca3cb0SRobert Mustacchi * This file takes care of reading the boot time modules and constructing them
1876ca3cb0SRobert Mustacchi * into the appropriate series of vnodes.
1976ca3cb0SRobert Mustacchi */
2076ca3cb0SRobert Mustacchi
2176ca3cb0SRobert Mustacchi #include <sys/conf.h>
2276ca3cb0SRobert Mustacchi #include <sys/ddi.h>
2376ca3cb0SRobert Mustacchi #include <sys/sunddi.h>
2476ca3cb0SRobert Mustacchi #include <sys/vfs.h>
2576ca3cb0SRobert Mustacchi #include <sys/sysmacros.h>
2676ca3cb0SRobert Mustacchi #include <sys/stat.h>
2776ca3cb0SRobert Mustacchi
2876ca3cb0SRobert Mustacchi #include <sys/fs/bootfs_impl.h>
2976ca3cb0SRobert Mustacchi
3076ca3cb0SRobert Mustacchi kmem_cache_t *bootfs_node_cache;
3176ca3cb0SRobert Mustacchi
3276ca3cb0SRobert Mustacchi static const vattr_t bootfs_vattr_dir = {
3376ca3cb0SRobert Mustacchi AT_ALL, /* va_mask */
3476ca3cb0SRobert Mustacchi VDIR, /* va_type */
3576ca3cb0SRobert Mustacchi S_IFDIR | 0555, /* va_mode */
3676ca3cb0SRobert Mustacchi 0, /* va_uid */
3776ca3cb0SRobert Mustacchi 0, /* va_gid */
3876ca3cb0SRobert Mustacchi 0, /* va_fsid */
3976ca3cb0SRobert Mustacchi 0, /* va_nodeid */
4076ca3cb0SRobert Mustacchi 1, /* va_nlink */
4176ca3cb0SRobert Mustacchi 0, /* va_size */
4276ca3cb0SRobert Mustacchi 0, /* va_atime */
4376ca3cb0SRobert Mustacchi 0, /* va_mtime */
4476ca3cb0SRobert Mustacchi 0, /* va_ctime */
4576ca3cb0SRobert Mustacchi 0, /* va_rdev */
4676ca3cb0SRobert Mustacchi 0, /* va_blksize */
4776ca3cb0SRobert Mustacchi 0, /* va_nblocks */
4876ca3cb0SRobert Mustacchi 0 /* va_seq */
4976ca3cb0SRobert Mustacchi };
5076ca3cb0SRobert Mustacchi
5176ca3cb0SRobert Mustacchi static const vattr_t bootfs_vattr_reg = {
5276ca3cb0SRobert Mustacchi AT_ALL, /* va_mask */
5376ca3cb0SRobert Mustacchi VREG, /* va_type */
5476ca3cb0SRobert Mustacchi S_IFREG | 0555, /* va_mode */
5576ca3cb0SRobert Mustacchi 0, /* va_uid */
5676ca3cb0SRobert Mustacchi 0, /* va_gid */
5776ca3cb0SRobert Mustacchi 0, /* va_fsid */
5876ca3cb0SRobert Mustacchi 0, /* va_nodeid */
5976ca3cb0SRobert Mustacchi 1, /* va_nlink */
6076ca3cb0SRobert Mustacchi 0, /* va_size */
6176ca3cb0SRobert Mustacchi 0, /* va_atime */
6276ca3cb0SRobert Mustacchi 0, /* va_mtime */
6376ca3cb0SRobert Mustacchi 0, /* va_ctime */
6476ca3cb0SRobert Mustacchi 0, /* va_rdev */
6576ca3cb0SRobert Mustacchi 0, /* va_blksize */
6676ca3cb0SRobert Mustacchi 0, /* va_nblocks */
6776ca3cb0SRobert Mustacchi 0 /* va_seq */
6876ca3cb0SRobert Mustacchi };
6976ca3cb0SRobert Mustacchi
7076ca3cb0SRobert Mustacchi /*ARGSUSED*/
7176ca3cb0SRobert Mustacchi int
bootfs_node_constructor(void * buf,void * arg,int kmflags)7276ca3cb0SRobert Mustacchi bootfs_node_constructor(void *buf, void *arg, int kmflags)
7376ca3cb0SRobert Mustacchi {
7476ca3cb0SRobert Mustacchi bootfs_node_t *bnp = buf;
7576ca3cb0SRobert Mustacchi
7676ca3cb0SRobert Mustacchi bnp->bvn_vnp = vn_alloc(kmflags);
7776ca3cb0SRobert Mustacchi if (bnp->bvn_vnp == NULL)
7876ca3cb0SRobert Mustacchi return (-1);
7976ca3cb0SRobert Mustacchi
8076ca3cb0SRobert Mustacchi return (0);
8176ca3cb0SRobert Mustacchi }
8276ca3cb0SRobert Mustacchi
8376ca3cb0SRobert Mustacchi /*ARGSUSED*/
8476ca3cb0SRobert Mustacchi void
bootfs_node_destructor(void * buf,void * arg)8576ca3cb0SRobert Mustacchi bootfs_node_destructor(void *buf, void *arg)
8676ca3cb0SRobert Mustacchi {
8776ca3cb0SRobert Mustacchi bootfs_node_t *bnp = buf;
8876ca3cb0SRobert Mustacchi
8976ca3cb0SRobert Mustacchi vn_free(bnp->bvn_vnp);
9076ca3cb0SRobert Mustacchi }
9176ca3cb0SRobert Mustacchi
9276ca3cb0SRobert Mustacchi static int
bootfs_comparator(const void * a,const void * b)9376ca3cb0SRobert Mustacchi bootfs_comparator(const void *a, const void *b)
9476ca3cb0SRobert Mustacchi {
9576ca3cb0SRobert Mustacchi const bootfs_node_t *lfs, *rfs;
9676ca3cb0SRobert Mustacchi int ret;
9776ca3cb0SRobert Mustacchi
9876ca3cb0SRobert Mustacchi lfs = a;
9976ca3cb0SRobert Mustacchi rfs = b;
10076ca3cb0SRobert Mustacchi
10176ca3cb0SRobert Mustacchi ret = strcmp(lfs->bvn_name, rfs->bvn_name);
10276ca3cb0SRobert Mustacchi if (ret > 0)
10376ca3cb0SRobert Mustacchi ret = 1;
10476ca3cb0SRobert Mustacchi if (ret < 0)
10576ca3cb0SRobert Mustacchi ret = -1;
10676ca3cb0SRobert Mustacchi return (ret);
10776ca3cb0SRobert Mustacchi }
10876ca3cb0SRobert Mustacchi
10976ca3cb0SRobert Mustacchi static void
bootfs_node_init(bootfs_t * bfs,bootfs_node_t * bnp,const struct vattr * vap,const char * name,size_t namelen)11076ca3cb0SRobert Mustacchi bootfs_node_init(bootfs_t *bfs, bootfs_node_t *bnp, const struct vattr *vap,
11176ca3cb0SRobert Mustacchi const char *name, size_t namelen)
11276ca3cb0SRobert Mustacchi {
11376ca3cb0SRobert Mustacchi timestruc_t now;
11476ca3cb0SRobert Mustacchi
11576ca3cb0SRobert Mustacchi vn_reinit(bnp->bvn_vnp);
11676ca3cb0SRobert Mustacchi
11776ca3cb0SRobert Mustacchi bnp->bvn_vnp->v_flag |= VNOSWAP;
11876ca3cb0SRobert Mustacchi bnp->bvn_vnp->v_type = vap->va_type;
11976ca3cb0SRobert Mustacchi bnp->bvn_vnp->v_vfsp = bfs->bfs_vfsp;
12076ca3cb0SRobert Mustacchi bnp->bvn_vnp->v_rdev = 0;
12176ca3cb0SRobert Mustacchi bnp->bvn_vnp->v_data = (caddr_t)bnp;
12276ca3cb0SRobert Mustacchi vn_setops(bnp->bvn_vnp, bootfs_vnodeops);
12376ca3cb0SRobert Mustacchi
12476ca3cb0SRobert Mustacchi bnp->bvn_name = kmem_alloc(namelen + 1, KM_SLEEP);
12576ca3cb0SRobert Mustacchi bcopy(name, bnp->bvn_name, namelen);
12676ca3cb0SRobert Mustacchi bnp->bvn_name[namelen] = '\0';
12776ca3cb0SRobert Mustacchi if (vap->va_type == VDIR) {
12876ca3cb0SRobert Mustacchi avl_create(&bnp->bvn_dir, bootfs_comparator,
12976ca3cb0SRobert Mustacchi sizeof (bootfs_node_t),
13076ca3cb0SRobert Mustacchi offsetof(bootfs_node_t, bvn_link));
13176ca3cb0SRobert Mustacchi }
13276ca3cb0SRobert Mustacchi bzero(&bnp->bvn_link, sizeof (avl_node_t));
13376ca3cb0SRobert Mustacchi bcopy(vap, &bnp->bvn_attr, sizeof (vattr_t));
13476ca3cb0SRobert Mustacchi
13576ca3cb0SRobert Mustacchi gethrestime(&now);
13676ca3cb0SRobert Mustacchi bnp->bvn_attr.va_atime = now;
13776ca3cb0SRobert Mustacchi bnp->bvn_attr.va_ctime = now;
13876ca3cb0SRobert Mustacchi bnp->bvn_attr.va_mtime = now;
13976ca3cb0SRobert Mustacchi bnp->bvn_attr.va_fsid = makedevice(bootfs_major, bfs->bfs_minor);
14076ca3cb0SRobert Mustacchi bnp->bvn_attr.va_nodeid = bfs->bfs_ninode;
14176ca3cb0SRobert Mustacchi bnp->bvn_attr.va_blksize = PAGESIZE;
14276ca3cb0SRobert Mustacchi bfs->bfs_ninode++;
14376ca3cb0SRobert Mustacchi list_insert_tail(&bfs->bfs_nodes, bnp);
14476ca3cb0SRobert Mustacchi }
14576ca3cb0SRobert Mustacchi
14676ca3cb0SRobert Mustacchi static void
bootfs_mkroot(bootfs_t * bfs)14776ca3cb0SRobert Mustacchi bootfs_mkroot(bootfs_t *bfs)
14876ca3cb0SRobert Mustacchi {
14976ca3cb0SRobert Mustacchi bootfs_node_t *bnp;
15076ca3cb0SRobert Mustacchi
15176ca3cb0SRobert Mustacchi bnp = kmem_cache_alloc(bootfs_node_cache, KM_SLEEP);
15276ca3cb0SRobert Mustacchi bootfs_node_init(bfs, bnp, &bootfs_vattr_dir, "/", 1);
15376ca3cb0SRobert Mustacchi bnp->bvn_vnp->v_flag |= VROOT;
15476ca3cb0SRobert Mustacchi bnp->bvn_parent = bnp;
15576ca3cb0SRobert Mustacchi bfs->bfs_rootvn = bnp;
15676ca3cb0SRobert Mustacchi bfs->bfs_stat.bfss_ndirs.value.ui32++;
15776ca3cb0SRobert Mustacchi vn_exists(bnp->bvn_vnp);
15876ca3cb0SRobert Mustacchi }
15976ca3cb0SRobert Mustacchi
16076ca3cb0SRobert Mustacchi static int
bootfs_mknode(bootfs_t * bfs,bootfs_node_t * parent,bootfs_node_t ** outp,const char * name,size_t namelen,const vattr_t * vap,uintptr_t addr,uint64_t size)16176ca3cb0SRobert Mustacchi bootfs_mknode(bootfs_t *bfs, bootfs_node_t *parent, bootfs_node_t **outp,
16276ca3cb0SRobert Mustacchi const char *name, size_t namelen, const vattr_t *vap, uintptr_t addr,
16376ca3cb0SRobert Mustacchi uint64_t size)
16476ca3cb0SRobert Mustacchi {
16576ca3cb0SRobert Mustacchi bootfs_node_t *bnp;
16676ca3cb0SRobert Mustacchi bootfs_node_t sn;
16776ca3cb0SRobert Mustacchi avl_index_t where;
16876ca3cb0SRobert Mustacchi char *buf;
16976ca3cb0SRobert Mustacchi
17076ca3cb0SRobert Mustacchi ASSERT(parent->bvn_attr.va_type == VDIR);
17176ca3cb0SRobert Mustacchi buf = kmem_alloc(namelen + 1, KM_SLEEP);
17276ca3cb0SRobert Mustacchi bcopy(name, buf, namelen);
17376ca3cb0SRobert Mustacchi buf[namelen] = '\0';
17476ca3cb0SRobert Mustacchi sn.bvn_name = buf;
17576ca3cb0SRobert Mustacchi if ((bnp = avl_find(&parent->bvn_dir, &sn, &where)) != NULL) {
17676ca3cb0SRobert Mustacchi kmem_free(buf, namelen + 1);
17776ca3cb0SRobert Mustacchi /* Directories can collide, files cannot */
17876ca3cb0SRobert Mustacchi if (vap->va_type == VDIR) {
17976ca3cb0SRobert Mustacchi *outp = bnp;
18076ca3cb0SRobert Mustacchi return (0);
18176ca3cb0SRobert Mustacchi }
18276ca3cb0SRobert Mustacchi return (EEXIST);
18376ca3cb0SRobert Mustacchi }
18476ca3cb0SRobert Mustacchi kmem_free(buf, namelen + 1);
18576ca3cb0SRobert Mustacchi
18676ca3cb0SRobert Mustacchi bnp = kmem_cache_alloc(bootfs_node_cache, KM_SLEEP);
18776ca3cb0SRobert Mustacchi bootfs_node_init(bfs, bnp, vap, name, namelen);
18876ca3cb0SRobert Mustacchi bnp->bvn_parent = parent;
18976ca3cb0SRobert Mustacchi avl_add(&parent->bvn_dir, bnp);
19076ca3cb0SRobert Mustacchi *outp = bnp;
19176ca3cb0SRobert Mustacchi
19276ca3cb0SRobert Mustacchi if (vap->va_type == VDIR) {
19376ca3cb0SRobert Mustacchi parent->bvn_attr.va_size++;
19476ca3cb0SRobert Mustacchi parent->bvn_attr.va_nlink++;
19576ca3cb0SRobert Mustacchi bfs->bfs_stat.bfss_ndirs.value.ui32++;
19676ca3cb0SRobert Mustacchi } else {
19776ca3cb0SRobert Mustacchi bnp->bvn_addr = addr;
19876ca3cb0SRobert Mustacchi bnp->bvn_size = size;
19976ca3cb0SRobert Mustacchi bfs->bfs_stat.bfss_nfiles.value.ui32++;
20076ca3cb0SRobert Mustacchi bfs->bfs_stat.bfss_nbytes.value.ui64 += size;
20176ca3cb0SRobert Mustacchi bnp->bvn_attr.va_nblocks = P2ROUNDUP(size, 512) >> 9;
20276ca3cb0SRobert Mustacchi bnp->bvn_attr.va_size = size;
20376ca3cb0SRobert Mustacchi }
20476ca3cb0SRobert Mustacchi
20576ca3cb0SRobert Mustacchi vn_exists(bnp->bvn_vnp);
20676ca3cb0SRobert Mustacchi
20776ca3cb0SRobert Mustacchi return (0);
20876ca3cb0SRobert Mustacchi }
20976ca3cb0SRobert Mustacchi
21076ca3cb0SRobert Mustacchi /*
21176ca3cb0SRobert Mustacchi * Given the address, size, and path a boot-time module would like, go through
21276ca3cb0SRobert Mustacchi * and create all of the directory entries that are required and then the file
21376ca3cb0SRobert Mustacchi * itself. If someone has passed in a module that has the same name as another
21476ca3cb0SRobert Mustacchi * one, we honor the first one.
21576ca3cb0SRobert Mustacchi */
21676ca3cb0SRobert Mustacchi static int
bootfs_construct_entry(bootfs_t * bfs,uintptr_t addr,uint64_t size,const char * mname)21776ca3cb0SRobert Mustacchi bootfs_construct_entry(bootfs_t *bfs, uintptr_t addr, uint64_t size,
21876ca3cb0SRobert Mustacchi const char *mname)
21976ca3cb0SRobert Mustacchi {
22076ca3cb0SRobert Mustacchi char *sp;
22176ca3cb0SRobert Mustacchi size_t nlen;
22276ca3cb0SRobert Mustacchi int ret;
22376ca3cb0SRobert Mustacchi bootfs_node_t *nbnp;
22476ca3cb0SRobert Mustacchi
22576ca3cb0SRobert Mustacchi const char *p = mname;
22676ca3cb0SRobert Mustacchi bootfs_node_t *bnp = bfs->bfs_rootvn;
22776ca3cb0SRobert Mustacchi
22876ca3cb0SRobert Mustacchi if (*p == '\0')
22976ca3cb0SRobert Mustacchi return (EINVAL);
23076ca3cb0SRobert Mustacchi
23176ca3cb0SRobert Mustacchi for (;;) {
23276ca3cb0SRobert Mustacchi /* First eliminate all leading / characters. */
23376ca3cb0SRobert Mustacchi while (*p == '/')
23476ca3cb0SRobert Mustacchi p++;
23576ca3cb0SRobert Mustacchi
23676ca3cb0SRobert Mustacchi /* A name with all slashes or ending in a / */
23776ca3cb0SRobert Mustacchi if (*p == '\0')
23876ca3cb0SRobert Mustacchi return (EINVAL);
23976ca3cb0SRobert Mustacchi
24076ca3cb0SRobert Mustacchi sp = strchr(p, '/');
24176ca3cb0SRobert Mustacchi if (sp == NULL)
24276ca3cb0SRobert Mustacchi break;
24376ca3cb0SRobert Mustacchi nlen = (ptrdiff_t)sp - (ptrdiff_t)p;
24476ca3cb0SRobert Mustacchi if (strncmp(p, ".", nlen) == 0) {
24576ca3cb0SRobert Mustacchi p = sp + 1;
24676ca3cb0SRobert Mustacchi continue;
24776ca3cb0SRobert Mustacchi }
24876ca3cb0SRobert Mustacchi
24976ca3cb0SRobert Mustacchi if (strncmp(p, "..", nlen) == 0) {
25076ca3cb0SRobert Mustacchi bnp = bnp->bvn_parent;
25176ca3cb0SRobert Mustacchi p = sp + 1;
25276ca3cb0SRobert Mustacchi continue;
25376ca3cb0SRobert Mustacchi }
25476ca3cb0SRobert Mustacchi
25576ca3cb0SRobert Mustacchi VERIFY(bootfs_mknode(bfs, bnp, &nbnp, p, nlen,
25676ca3cb0SRobert Mustacchi &bootfs_vattr_dir, addr, size) == 0);
25776ca3cb0SRobert Mustacchi p = sp + 1;
25876ca3cb0SRobert Mustacchi bnp = nbnp;
25976ca3cb0SRobert Mustacchi }
26076ca3cb0SRobert Mustacchi
26176ca3cb0SRobert Mustacchi nlen = strlen(p);
26276ca3cb0SRobert Mustacchi ret = bootfs_mknode(bfs, bnp, &nbnp, p, nlen, &bootfs_vattr_reg,
26376ca3cb0SRobert Mustacchi addr, size);
26476ca3cb0SRobert Mustacchi if (ret != 0)
26576ca3cb0SRobert Mustacchi return (ret);
26676ca3cb0SRobert Mustacchi
26776ca3cb0SRobert Mustacchi return (0);
26876ca3cb0SRobert Mustacchi }
26976ca3cb0SRobert Mustacchi
27076ca3cb0SRobert Mustacchi /*
27176ca3cb0SRobert Mustacchi * We're going to go through every boot time module and construct the
27276ca3cb0SRobert Mustacchi * appropriate vnodes for them now. Because there are very few of these that
27376ca3cb0SRobert Mustacchi * exist, generally on the order of a handful, we're going to create them all
27476ca3cb0SRobert Mustacchi * when the file system is initialized and then tear them all down when the
27576ca3cb0SRobert Mustacchi * module gets unloaded.
27676ca3cb0SRobert Mustacchi *
27776ca3cb0SRobert Mustacchi * The information about the modules is contained in properties on the root of
27876ca3cb0SRobert Mustacchi * the devinfo tree. Specifically there are three properties per module:
27976ca3cb0SRobert Mustacchi *
28076ca3cb0SRobert Mustacchi * - module-size-%d int64_t size, in bytes, of the boot time module.
28176ca3cb0SRobert Mustacchi * - module-addr-%d The address of the boot time module
28276ca3cb0SRobert Mustacchi * - module-name-%d The string name of the boot time module
28376ca3cb0SRobert Mustacchi *
28476ca3cb0SRobert Mustacchi * Note that the module-size and module-addr fields are always 64-bit values
28576ca3cb0SRobert Mustacchi * regardless of being on a 32-bit or 64-bit kernel. module-name is a string
28676ca3cb0SRobert Mustacchi * property.
28776ca3cb0SRobert Mustacchi *
28876ca3cb0SRobert Mustacchi * There is no property that indicates the total number of such modules. Modules
28976ca3cb0SRobert Mustacchi * start at 0 and work their way up incrementally. The first time we can't find
29076ca3cb0SRobert Mustacchi * a module or a property, then we stop.
29176ca3cb0SRobert Mustacchi */
29276ca3cb0SRobert Mustacchi void
bootfs_construct(bootfs_t * bfs)29376ca3cb0SRobert Mustacchi bootfs_construct(bootfs_t *bfs)
29476ca3cb0SRobert Mustacchi {
295*d98490e4SToomas Soome uint_t id = 0;
29676ca3cb0SRobert Mustacchi char paddr[64], psize[64], pname[64], *mname;
29776ca3cb0SRobert Mustacchi dev_info_t *root;
298*d98490e4SToomas Soome uint64_t size, addr;
29976ca3cb0SRobert Mustacchi int ret;
30076ca3cb0SRobert Mustacchi
30176ca3cb0SRobert Mustacchi bootfs_mkroot(bfs);
30276ca3cb0SRobert Mustacchi root = ddi_root_node();
30376ca3cb0SRobert Mustacchi
30476ca3cb0SRobert Mustacchi for (;;) {
30576ca3cb0SRobert Mustacchi if (id == UINT32_MAX)
30676ca3cb0SRobert Mustacchi break;
30776ca3cb0SRobert Mustacchi
30876ca3cb0SRobert Mustacchi if (snprintf(paddr, sizeof (paddr), "module-addr-%d", id) >
30976ca3cb0SRobert Mustacchi sizeof (paddr))
31076ca3cb0SRobert Mustacchi break;
31176ca3cb0SRobert Mustacchi
31276ca3cb0SRobert Mustacchi if (snprintf(psize, sizeof (paddr), "module-size-%d", id) >
31376ca3cb0SRobert Mustacchi sizeof (paddr))
31476ca3cb0SRobert Mustacchi break;
31576ca3cb0SRobert Mustacchi
31676ca3cb0SRobert Mustacchi if (snprintf(pname, sizeof (paddr), "module-name-%d", id) >
31776ca3cb0SRobert Mustacchi sizeof (paddr))
31876ca3cb0SRobert Mustacchi break;
31976ca3cb0SRobert Mustacchi
320*d98490e4SToomas Soome addr = (uint64_t)ddi_prop_get_int64(DDI_DEV_T_ANY, root,
321*d98490e4SToomas Soome DDI_PROP_DONTPASS, paddr, 0);
322*d98490e4SToomas Soome if (addr == 0 || addr == DDI_PROP_NOT_FOUND)
32376ca3cb0SRobert Mustacchi break;
32476ca3cb0SRobert Mustacchi
325*d98490e4SToomas Soome size = (uint64_t)ddi_prop_get_int64(DDI_DEV_T_ANY, root,
326*d98490e4SToomas Soome DDI_PROP_DONTPASS, psize, 0);
327*d98490e4SToomas Soome if (size == 0 || size == DDI_PROP_NOT_FOUND)
32876ca3cb0SRobert Mustacchi break;
32976ca3cb0SRobert Mustacchi
33076ca3cb0SRobert Mustacchi if (ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
33176ca3cb0SRobert Mustacchi DDI_PROP_DONTPASS, pname, &mname) != DDI_PROP_SUCCESS)
33276ca3cb0SRobert Mustacchi break;
33376ca3cb0SRobert Mustacchi
33476ca3cb0SRobert Mustacchi ret = bootfs_construct_entry(bfs, addr, size, mname);
33576ca3cb0SRobert Mustacchi if (ret == EINVAL)
33676ca3cb0SRobert Mustacchi bfs->bfs_stat.bfss_ndiscards.value.ui32++;
33776ca3cb0SRobert Mustacchi if (ret == EEXIST)
33876ca3cb0SRobert Mustacchi bfs->bfs_stat.bfss_ndups.value.ui32++;
33976ca3cb0SRobert Mustacchi ddi_prop_free(mname);
34076ca3cb0SRobert Mustacchi
34176ca3cb0SRobert Mustacchi id++;
34276ca3cb0SRobert Mustacchi }
34376ca3cb0SRobert Mustacchi }
34476ca3cb0SRobert Mustacchi
34576ca3cb0SRobert Mustacchi void
bootfs_destruct(bootfs_t * bfs)34676ca3cb0SRobert Mustacchi bootfs_destruct(bootfs_t *bfs)
34776ca3cb0SRobert Mustacchi {
34876ca3cb0SRobert Mustacchi bootfs_node_t *bnp;
34976ca3cb0SRobert Mustacchi
35076ca3cb0SRobert Mustacchi while ((bnp = list_remove_head(&bfs->bfs_nodes)) != NULL) {
35176ca3cb0SRobert Mustacchi ASSERT(bnp->bvn_vnp->v_count == 1);
35276ca3cb0SRobert Mustacchi VN_RELE(bnp->bvn_vnp);
35376ca3cb0SRobert Mustacchi kmem_free(bnp->bvn_name, strlen(bnp->bvn_name) + 1);
35476ca3cb0SRobert Mustacchi kmem_cache_free(bootfs_node_cache, bnp);
35576ca3cb0SRobert Mustacchi }
35676ca3cb0SRobert Mustacchi }
357