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