Home | History | Annotate | Download | only in mdesc
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <sys/types.h>
     30 #include <sys/param.h>
     31 #include <sys/mdesc.h>
     32 #include <sys/mdesc_impl.h>
     33 
     34 md_t *
     35 md_init_intern(uint64_t *ptr,  void *(*allocp)(size_t),
     36 	    void (*freep)(void *, size_t))
     37 {
     38 	md_impl_t	*mdp;
     39 	int		idx;
     40 	int		count;
     41 	int		done;
     42 	uint64_t	gen;
     43 	mde_str_cookie_t root_name;
     44 
     45 	/*
     46 	 * Very basic checkup for alignment to avoid
     47 	 * bus error issues.
     48 	 */
     49 	if ((((uintptr_t)ptr) & 7) != 0)
     50 		return (NULL);
     51 
     52 	mdp = (md_impl_t *)allocp(sizeof (md_impl_t));
     53 
     54 	if (mdp == NULL)
     55 		return (NULL);
     56 
     57 	mdp->allocp = allocp;
     58 	mdp->freep = freep;
     59 
     60 	mdp->caddr = (char *)ptr;
     61 
     62 	/*
     63 	 * setup internal structures
     64 	 */
     65 
     66 	mdp->headerp = (md_header_t *)mdp->caddr;
     67 
     68 	if (mdtoh32(mdp->headerp->transport_version) != MD_TRANSPORT_VERSION) {
     69 		goto cleanup_nohash;
     70 	}
     71 
     72 	mdp->node_blk_size = mdtoh32(mdp->headerp->node_blk_sz);
     73 	mdp->name_blk_size = mdtoh32(mdp->headerp->name_blk_sz);
     74 	mdp->data_blk_size = mdtoh32(mdp->headerp->data_blk_sz);
     75 
     76 	mdp->size = MD_HEADER_SIZE + mdp->node_blk_size +
     77 	    mdp->name_blk_size + mdp->data_blk_size;
     78 
     79 	mdp->mdep = (md_element_t *)(mdp->caddr + MD_HEADER_SIZE);
     80 	mdp->namep = (char *)(mdp->caddr + MD_HEADER_SIZE + mdp->node_blk_size);
     81 	mdp->datap = (uint8_t *)(mdp->caddr + MD_HEADER_SIZE +
     82 	    mdp->name_blk_size + mdp->node_blk_size);
     83 
     84 	mdp->root_node = MDE_INVAL_ELEM_COOKIE;
     85 
     86 
     87 	/*
     88 	 * Should do a lot more sanity checking here.
     89 	 */
     90 
     91 	/*
     92 	 * Should initialize a name hash here if we intend to use one
     93 	 */
     94 
     95 	/*
     96 	 * Setup to find the root node
     97 	 */
     98 	root_name = md_find_name((md_t *)mdp, "root");
     99 	if (root_name == MDE_INVAL_STR_COOKIE) {
    100 		goto cleanup;
    101 	}
    102 
    103 	/*
    104 	 * One more property we need is the count of nodes in the
    105 	 * DAG, not just the number of elements.
    106 	 *
    107 	 * We try and pickup the root node along the way here.
    108 	 */
    109 
    110 	for (done = 0, idx = 0, count = 0; !done; ) {
    111 		md_element_t *np;
    112 
    113 		np = &(mdp->mdep[idx]);
    114 
    115 		switch (MDE_TAG(np)) {
    116 		case MDET_LIST_END:
    117 			done = 1;
    118 			break;
    119 
    120 		case MDET_NODE:
    121 			if (root_name == MDE_NAME(np)) {
    122 				if (mdp->root_node != MDE_INVAL_ELEM_COOKIE) {
    123 					/* Gah .. more than one root */
    124 					goto cleanup;
    125 				}
    126 				mdp->root_node = (mde_cookie_t)idx;
    127 			}
    128 			idx = MDE_PROP_INDEX(np);
    129 			count++;
    130 			break;
    131 
    132 		default:
    133 			idx++;	/* ignore */
    134 		}
    135 	}
    136 
    137 	/*
    138 	 * Ensure there is a root node
    139 	 */
    140 	if (mdp->root_node == MDE_INVAL_ELEM_COOKIE) {
    141 		goto cleanup;
    142 	}
    143 
    144 	/*
    145 	 * Register the counts
    146 	 */
    147 
    148 	mdp->element_count = idx + 1;	/* include LIST_END */
    149 	mdp->node_count = count;
    150 
    151 	/*
    152 	 * Final sanity check that everything adds up
    153 	 */
    154 	if (mdp->element_count != (mdp->node_blk_size / MD_ELEMENT_SIZE))
    155 		goto cleanup;
    156 
    157 	mdp->md_magic = LIBMD_MAGIC;
    158 
    159 	/*
    160 	 * Setup MD generation
    161 	 */
    162 	if (md_get_prop_val((md_t *)mdp, mdp->root_node,
    163 	    "md-generation#", &gen) != 0)
    164 		mdp->gen = MDESC_INVAL_GEN;
    165 	else
    166 		mdp->gen = gen;
    167 
    168 	return ((md_t *)mdp);
    169 
    170 cleanup:
    171 	/*
    172 	 * Clean up here - including a name hash if
    173 	 * we build one.
    174 	 */
    175 
    176 cleanup_nohash:
    177 	mdp->freep(mdp, sizeof (md_impl_t));
    178 	return (NULL);
    179 }
    180