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