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