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