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