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 *
md_init_intern(uint64_t * ptr,void * (* allocp)(size_t),void (* freep)(void *,size_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