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 #include <sys/types.h> 28 #include <sys/param.h> 29 #include <sys/mdesc.h> 30 #include <sys/mdesc_impl.h> 31 32 md_t * 33 md_init_intern(uint64_t *ptr, void *(*allocp)(size_t), 34 void (*freep)(void *, size_t)) 35 { 36 md_impl_t *mdp; 37 int idx; 38 int count; 39 int done; 40 uint64_t gen; 41 mde_str_cookie_t root_name; 42 43 /* 44 * Very basic checkup for alignment to avoid 45 * bus error issues. 46 */ 47 if ((((uintptr_t)ptr) & 7) != 0) 48 return (NULL); 49 50 mdp = (md_impl_t *)allocp(sizeof (md_impl_t)); 51 52 if (mdp == NULL) 53 return (NULL); 54 55 mdp->allocp = allocp; 56 mdp->freep = freep; 57 58 mdp->caddr = (char *)ptr; 59 60 /* 61 * setup internal structures 62 */ 63 64 mdp->headerp = (md_header_t *)mdp->caddr; 65 66 if (mdtoh32(mdp->headerp->transport_version) != MD_TRANSPORT_VERSION) { 67 goto cleanup_nohash; 68 } 69 70 mdp->node_blk_size = mdtoh32(mdp->headerp->node_blk_sz); 71 mdp->name_blk_size = mdtoh32(mdp->headerp->name_blk_sz); 72 mdp->data_blk_size = mdtoh32(mdp->headerp->data_blk_sz); 73 74 mdp->size = MD_HEADER_SIZE + mdp->node_blk_size + 75 mdp->name_blk_size + mdp->data_blk_size; 76 77 mdp->mdep = (md_element_t *)(mdp->caddr + MD_HEADER_SIZE); 78 mdp->namep = (char *)(mdp->caddr + MD_HEADER_SIZE + mdp->node_blk_size); 79 mdp->datap = (uint8_t *)(mdp->caddr + MD_HEADER_SIZE + 80 mdp->name_blk_size + mdp->node_blk_size); 81 82 mdp->root_node = MDE_INVAL_ELEM_COOKIE; 83 84 85 /* 86 * Should do a lot more sanity checking here. 87 */ 88 89 /* 90 * Should initialize a name hash here if we intend to use one 91 */ 92 93 /* 94 * Setup to find the root node 95 */ 96 root_name = md_find_name((md_t *)mdp, "root"); 97 if (root_name == MDE_INVAL_STR_COOKIE) { 98 goto cleanup; 99 } 100 101 /* 102 * One more property we need is the count of nodes in the 103 * DAG, not just the number of elements. 104 * 105 * We try and pickup the root node along the way here. 106 */ 107 108 for (done = 0, idx = 0, count = 0; !done; ) { 109 md_element_t *np; 110 111 np = &(mdp->mdep[idx]); 112 113 switch (MDE_TAG(np)) { 114 case MDET_LIST_END: 115 done = 1; 116 break; 117 118 case MDET_NODE: 119 if (root_name == MDE_NAME(np)) { 120 if (mdp->root_node != MDE_INVAL_ELEM_COOKIE) { 121 /* Gah .. more than one root */ 122 goto cleanup; 123 } 124 mdp->root_node = (mde_cookie_t)idx; 125 } 126 idx = MDE_PROP_INDEX(np); 127 count++; 128 break; 129 130 default: 131 idx++; /* ignore */ 132 } 133 } 134 135 /* 136 * Ensure there is a root node 137 */ 138 if (mdp->root_node == MDE_INVAL_ELEM_COOKIE) { 139 goto cleanup; 140 } 141 142 /* 143 * Register the counts 144 */ 145 146 mdp->element_count = idx + 1; /* include LIST_END */ 147 mdp->node_count = count; 148 149 /* 150 * Final sanity check that everything adds up 151 */ 152 if (mdp->element_count != (mdp->node_blk_size / MD_ELEMENT_SIZE)) 153 goto cleanup; 154 155 mdp->md_magic = LIBMD_MAGIC; 156 157 /* 158 * Setup MD generation 159 */ 160 if (md_get_prop_val((md_t *)mdp, mdp->root_node, 161 "md-generation#", &gen) != 0) 162 mdp->gen = MDESC_INVAL_GEN; 163 else 164 mdp->gen = gen; 165 166 return ((md_t *)mdp); 167 168 cleanup: 169 /* 170 * Clean up here - including a name hash if 171 * we build one. 172 */ 173 174 cleanup_nohash: 175 mdp->freep(mdp, sizeof (md_impl_t)); 176 return (NULL); 177 } 178