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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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 mde_str_cookie_t root_name; 43 44 /* 45 * Very basic checkup for alignment to avoid 46 * bus error issues. 47 */ 48 if ((((uintptr_t)ptr)&7) != 0) 49 return (NULL); 50 51 mdp = (md_impl_t *)allocp(sizeof (md_impl_t)); 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 mdp->headerp = (md_header_t *)mdp->caddr; 64 65 if (mdtoh32(mdp->headerp->transport_version) != MD_TRANSPORT_VERSION) { 66 goto cleanup_nohash; 67 } 68 69 mdp->node_blk_size = mdtoh32(mdp->headerp->node_blk_sz); 70 mdp->name_blk_size = mdtoh32(mdp->headerp->name_blk_sz); 71 mdp->data_blk_size = mdtoh32(mdp->headerp->data_blk_sz); 72 73 mdp->size = MD_HEADER_SIZE+mdp->node_blk_size+ 74 mdp->name_blk_size+mdp->data_blk_size; 75 76 mdp->mdep = (md_element_t *)(mdp->caddr+MD_HEADER_SIZE); 77 mdp->namep = (char *)(mdp->caddr+MD_HEADER_SIZE+mdp->node_blk_size); 78 mdp->datap = (uint8_t *)(mdp->caddr+MD_HEADER_SIZE+mdp->name_blk_size+ 79 mdp->node_blk_size); 80 81 mdp->root_node = MDE_INVAL_ELEM_COOKIE; 82 83 84 /* 85 * Should do a lot more sanity checking here. 86 */ 87 88 /* 89 * Should initialize a name hash here if we intend to use one 90 */ 91 92 /* 93 * Setup to find the root node 94 */ 95 root_name = md_find_name((md_t *)mdp, "root"); 96 if (root_name == MDE_INVAL_STR_COOKIE) { 97 goto cleanup; 98 } 99 100 /* 101 * One more property we need is the count of nodes in the 102 * DAG, not just the number of elements. 103 * 104 * We try and pickup the root node along the way here. 105 */ 106 107 for (done = 0, idx = 0, count = 0; !done; ) { 108 md_element_t *np; 109 110 np = &(mdp->mdep[idx]); 111 112 switch (MDE_TAG(np)) { 113 case MDET_LIST_END: 114 done = 1; 115 break; 116 117 case MDET_NODE: 118 if (root_name == MDE_NAME(np)) { 119 if (mdp->root_node != MDE_INVAL_ELEM_COOKIE) { 120 /* Gah .. more than one root */ 121 goto cleanup; 122 } 123 mdp->root_node = (mde_cookie_t)idx; 124 } 125 idx = MDE_PROP_INDEX(np); 126 count ++; 127 break; 128 129 default: 130 idx++; /* ignore */ 131 } 132 } 133 134 /* 135 * Ensure there is a root node 136 */ 137 if (mdp->root_node == MDE_INVAL_ELEM_COOKIE) { 138 goto cleanup; 139 } 140 141 /* 142 * Register the counts 143 */ 144 145 mdp->element_count = idx+1; /* include LIST_END */ 146 mdp->node_count = count; 147 148 /* 149 * Final sanity check that everything adds up 150 */ 151 if (mdp->element_count != (mdp->node_blk_size/MD_ELEMENT_SIZE)) 152 goto cleanup; 153 154 mdp->md_magic = LIBMD_MAGIC; 155 156 return ((md_t *)mdp); 157 158 cleanup:; 159 /* 160 * Clean up here - including a name hash if 161 * we build one. 162 */ 163 cleanup_nohash:; 164 mdp->freep(mdp, sizeof (md_impl_t)); 165 return (NULL); 166 } 167