xref: /onnv-gate/usr/src/cmd/ldmad/mdesc_lib.c (revision 11596:e9010337bcd3)
1*11596SJason.Beloro@Sun.COM /*
2*11596SJason.Beloro@Sun.COM  * CDDL HEADER START
3*11596SJason.Beloro@Sun.COM  *
4*11596SJason.Beloro@Sun.COM  * The contents of this file are subject to the terms of the
5*11596SJason.Beloro@Sun.COM  * Common Development and Distribution License (the "License").
6*11596SJason.Beloro@Sun.COM  * You may not use this file except in compliance with the License.
7*11596SJason.Beloro@Sun.COM  *
8*11596SJason.Beloro@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*11596SJason.Beloro@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*11596SJason.Beloro@Sun.COM  * See the License for the specific language governing permissions
11*11596SJason.Beloro@Sun.COM  * and limitations under the License.
12*11596SJason.Beloro@Sun.COM  *
13*11596SJason.Beloro@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*11596SJason.Beloro@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*11596SJason.Beloro@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*11596SJason.Beloro@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*11596SJason.Beloro@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*11596SJason.Beloro@Sun.COM  *
19*11596SJason.Beloro@Sun.COM  * CDDL HEADER END
20*11596SJason.Beloro@Sun.COM  */
21*11596SJason.Beloro@Sun.COM 
22*11596SJason.Beloro@Sun.COM /*
23*11596SJason.Beloro@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*11596SJason.Beloro@Sun.COM  * Use is subject to license terms.
25*11596SJason.Beloro@Sun.COM  */
26*11596SJason.Beloro@Sun.COM 
27*11596SJason.Beloro@Sun.COM #include <strings.h>
28*11596SJason.Beloro@Sun.COM #include <stdio.h>
29*11596SJason.Beloro@Sun.COM #include <unistd.h>
30*11596SJason.Beloro@Sun.COM #include <stdlib.h>
31*11596SJason.Beloro@Sun.COM #include <strings.h>
32*11596SJason.Beloro@Sun.COM #include <note.h>
33*11596SJason.Beloro@Sun.COM #include <errno.h>
34*11596SJason.Beloro@Sun.COM #include <sys/mdesc.h>
35*11596SJason.Beloro@Sun.COM #include <sys/mdesc_impl.h>
36*11596SJason.Beloro@Sun.COM #include <sys/sysmacros.h>
37*11596SJason.Beloro@Sun.COM #include "mdesc_mutable.h"
38*11596SJason.Beloro@Sun.COM 
39*11596SJason.Beloro@Sun.COM static void md_free_prop(mmd_t *mdp, md_prop_t *propp);
40*11596SJason.Beloro@Sun.COM static void md_free_string(mmd_t *mdp, md_string_t *msp);
41*11596SJason.Beloro@Sun.COM static void md_free_data_block(mmd_t *mdp, md_data_block_t *mdbp);
42*11596SJason.Beloro@Sun.COM 
43*11596SJason.Beloro@Sun.COM static uint32_t
md_byte_hash(uint8_t * bp,int len)44*11596SJason.Beloro@Sun.COM md_byte_hash(uint8_t *bp, int len)
45*11596SJason.Beloro@Sun.COM {
46*11596SJason.Beloro@Sun.COM 	uint32_t hash = 0;
47*11596SJason.Beloro@Sun.COM 	int i;
48*11596SJason.Beloro@Sun.COM 
49*11596SJason.Beloro@Sun.COM 	for (i = 0; i < len; i++) {
50*11596SJason.Beloro@Sun.COM 		/* 5 bit rotation */
51*11596SJason.Beloro@Sun.COM 		hash = (hash >> 27) | (hash << 5) | bp[i];
52*11596SJason.Beloro@Sun.COM 	}
53*11596SJason.Beloro@Sun.COM 
54*11596SJason.Beloro@Sun.COM 	return (hash);
55*11596SJason.Beloro@Sun.COM }
56*11596SJason.Beloro@Sun.COM 
57*11596SJason.Beloro@Sun.COM static md_string_t *
md_find_string(mmd_t * mdp,char * strp,uint32_t * hashp)58*11596SJason.Beloro@Sun.COM md_find_string(mmd_t *mdp, char *strp, uint32_t *hashp)
59*11596SJason.Beloro@Sun.COM {
60*11596SJason.Beloro@Sun.COM 	md_string_t *msp;
61*11596SJason.Beloro@Sun.COM 	uint32_t hash;
62*11596SJason.Beloro@Sun.COM 
63*11596SJason.Beloro@Sun.COM 	hash = md_byte_hash((uint8_t *)strp, strlen(strp));
64*11596SJason.Beloro@Sun.COM 
65*11596SJason.Beloro@Sun.COM 	if (hashp != NULL)
66*11596SJason.Beloro@Sun.COM 		*hashp = hash;
67*11596SJason.Beloro@Sun.COM 
68*11596SJason.Beloro@Sun.COM 	CHAIN_ITER(mdp->string_list, msp) {
69*11596SJason.Beloro@Sun.COM 		if (msp->hash == hash && strcmp(msp->strp, strp) == 0)
70*11596SJason.Beloro@Sun.COM 			return (msp);
71*11596SJason.Beloro@Sun.COM 	}
72*11596SJason.Beloro@Sun.COM 
73*11596SJason.Beloro@Sun.COM 	return (NULL);
74*11596SJason.Beloro@Sun.COM }
75*11596SJason.Beloro@Sun.COM 
76*11596SJason.Beloro@Sun.COM static md_string_t *
md_new_string(mmd_t * mdp,char * strp)77*11596SJason.Beloro@Sun.COM md_new_string(mmd_t *mdp, char *strp)
78*11596SJason.Beloro@Sun.COM {
79*11596SJason.Beloro@Sun.COM 	md_string_t *msp;
80*11596SJason.Beloro@Sun.COM 	uint32_t hash;
81*11596SJason.Beloro@Sun.COM 
82*11596SJason.Beloro@Sun.COM 	msp = md_find_string(mdp, strp, &hash);
83*11596SJason.Beloro@Sun.COM 	if (msp == NULL) {
84*11596SJason.Beloro@Sun.COM 		msp = calloc(1, sizeof (md_string_t));
85*11596SJason.Beloro@Sun.COM 		if (msp == NULL)
86*11596SJason.Beloro@Sun.COM 			return (NULL);
87*11596SJason.Beloro@Sun.COM 		msp->strp = strdup(strp);
88*11596SJason.Beloro@Sun.COM 		if (msp->strp == NULL) {
89*11596SJason.Beloro@Sun.COM 			free(msp);
90*11596SJason.Beloro@Sun.COM 			return (NULL);
91*11596SJason.Beloro@Sun.COM 		}
92*11596SJason.Beloro@Sun.COM 		msp->size = strlen(strp) + 1;
93*11596SJason.Beloro@Sun.COM 		msp->hash = hash;
94*11596SJason.Beloro@Sun.COM 		msp->ref_cnt = 0;
95*11596SJason.Beloro@Sun.COM 		msp->build_offset = MD_OFFSET_UNDEF;
96*11596SJason.Beloro@Sun.COM 		CHAIN_ADD(mdp->string_list, msp);
97*11596SJason.Beloro@Sun.COM 	}
98*11596SJason.Beloro@Sun.COM 	msp->ref_cnt++;
99*11596SJason.Beloro@Sun.COM 
100*11596SJason.Beloro@Sun.COM 	return (msp);
101*11596SJason.Beloro@Sun.COM }
102*11596SJason.Beloro@Sun.COM 
103*11596SJason.Beloro@Sun.COM static md_data_block_t *
md_find_data_block(mmd_t * mdp,uint8_t * datap,int len,uint32_t * hashp)104*11596SJason.Beloro@Sun.COM md_find_data_block(mmd_t *mdp, uint8_t *datap, int len, uint32_t *hashp)
105*11596SJason.Beloro@Sun.COM {
106*11596SJason.Beloro@Sun.COM 	md_data_block_t *dbp;
107*11596SJason.Beloro@Sun.COM 	uint32_t hash;
108*11596SJason.Beloro@Sun.COM 
109*11596SJason.Beloro@Sun.COM 	hash = md_byte_hash(datap, len);
110*11596SJason.Beloro@Sun.COM 
111*11596SJason.Beloro@Sun.COM 	if (hashp != NULL)
112*11596SJason.Beloro@Sun.COM 		*hashp = hash;
113*11596SJason.Beloro@Sun.COM 
114*11596SJason.Beloro@Sun.COM 	CHAIN_ITER(mdp->data_block_list, dbp) {
115*11596SJason.Beloro@Sun.COM 		if (dbp->size == len &&
116*11596SJason.Beloro@Sun.COM 		    dbp->hash == hash && bcmp(dbp->datap, datap, len) == 0)
117*11596SJason.Beloro@Sun.COM 			return (dbp);
118*11596SJason.Beloro@Sun.COM 	}
119*11596SJason.Beloro@Sun.COM 
120*11596SJason.Beloro@Sun.COM 	return (NULL);
121*11596SJason.Beloro@Sun.COM }
122*11596SJason.Beloro@Sun.COM 
123*11596SJason.Beloro@Sun.COM static md_data_block_t *
md_new_data_block(mmd_t * mdp,uint8_t * bufp,int len)124*11596SJason.Beloro@Sun.COM md_new_data_block(mmd_t *mdp, uint8_t *bufp, int len)
125*11596SJason.Beloro@Sun.COM {
126*11596SJason.Beloro@Sun.COM 	md_data_block_t *dbp;
127*11596SJason.Beloro@Sun.COM 	uint32_t	hash;
128*11596SJason.Beloro@Sun.COM 
129*11596SJason.Beloro@Sun.COM 	dbp = md_find_data_block(mdp, bufp, len, &hash);
130*11596SJason.Beloro@Sun.COM 	if (dbp == NULL) {
131*11596SJason.Beloro@Sun.COM 		dbp = calloc(1, sizeof (md_data_block_t));
132*11596SJason.Beloro@Sun.COM 		if (dbp == NULL)
133*11596SJason.Beloro@Sun.COM 			return (NULL);
134*11596SJason.Beloro@Sun.COM 		dbp->datap = malloc(len);
135*11596SJason.Beloro@Sun.COM 		if (dbp->datap == NULL) {
136*11596SJason.Beloro@Sun.COM 			free(dbp);
137*11596SJason.Beloro@Sun.COM 			return (NULL);
138*11596SJason.Beloro@Sun.COM 		}
139*11596SJason.Beloro@Sun.COM 		(void) memcpy(dbp->datap, bufp, len);
140*11596SJason.Beloro@Sun.COM 		dbp->size = len;
141*11596SJason.Beloro@Sun.COM 		dbp->hash = hash;
142*11596SJason.Beloro@Sun.COM 		dbp->ref_cnt = 0;
143*11596SJason.Beloro@Sun.COM 		dbp->build_offset = MD_OFFSET_UNDEF;
144*11596SJason.Beloro@Sun.COM 		CHAIN_ADD(mdp->data_block_list, dbp);
145*11596SJason.Beloro@Sun.COM 	}
146*11596SJason.Beloro@Sun.COM 	dbp->ref_cnt++;
147*11596SJason.Beloro@Sun.COM 
148*11596SJason.Beloro@Sun.COM 	return (dbp);
149*11596SJason.Beloro@Sun.COM }
150*11596SJason.Beloro@Sun.COM 
151*11596SJason.Beloro@Sun.COM md_node_t *
md_new_node(mmd_t * mdp,char * sp)152*11596SJason.Beloro@Sun.COM md_new_node(mmd_t *mdp, char *sp)
153*11596SJason.Beloro@Sun.COM {
154*11596SJason.Beloro@Sun.COM 	md_node_t *nodep;
155*11596SJason.Beloro@Sun.COM 
156*11596SJason.Beloro@Sun.COM 	nodep = calloc(1, sizeof (md_node_t));
157*11596SJason.Beloro@Sun.COM 	if (nodep == NULL)
158*11596SJason.Beloro@Sun.COM 		return (NULL);
159*11596SJason.Beloro@Sun.COM 	nodep->typep = md_new_string(mdp, sp);
160*11596SJason.Beloro@Sun.COM 	if (nodep->typep == NULL) {
161*11596SJason.Beloro@Sun.COM 		free(nodep);
162*11596SJason.Beloro@Sun.COM 		return (NULL);
163*11596SJason.Beloro@Sun.COM 	}
164*11596SJason.Beloro@Sun.COM 	CHAIN_ADD(mdp->node_list, nodep);
165*11596SJason.Beloro@Sun.COM 
166*11596SJason.Beloro@Sun.COM 	return (nodep);
167*11596SJason.Beloro@Sun.COM }
168*11596SJason.Beloro@Sun.COM 
169*11596SJason.Beloro@Sun.COM static md_prop_t *
md_new_property(mmd_t * mdp,md_node_t * nodep,uint8_t type,char * sp)170*11596SJason.Beloro@Sun.COM md_new_property(mmd_t *mdp, md_node_t *nodep, uint8_t type, char *sp)
171*11596SJason.Beloro@Sun.COM {
172*11596SJason.Beloro@Sun.COM 	md_prop_t *propp;
173*11596SJason.Beloro@Sun.COM 
174*11596SJason.Beloro@Sun.COM 	propp = calloc(1, sizeof (md_prop_t));
175*11596SJason.Beloro@Sun.COM 	if (propp == NULL)
176*11596SJason.Beloro@Sun.COM 		return (NULL);
177*11596SJason.Beloro@Sun.COM 	propp->type = type;
178*11596SJason.Beloro@Sun.COM 	propp->sp = md_new_string(mdp, sp);
179*11596SJason.Beloro@Sun.COM 	if (propp->sp == NULL) {
180*11596SJason.Beloro@Sun.COM 		free(propp);
181*11596SJason.Beloro@Sun.COM 		return (NULL);
182*11596SJason.Beloro@Sun.COM 	}
183*11596SJason.Beloro@Sun.COM 
184*11596SJason.Beloro@Sun.COM 	CHAIN_ADD(nodep->prop_list, propp);
185*11596SJason.Beloro@Sun.COM 
186*11596SJason.Beloro@Sun.COM 	return (propp);
187*11596SJason.Beloro@Sun.COM }
188*11596SJason.Beloro@Sun.COM 
189*11596SJason.Beloro@Sun.COM int
md_add_value_property(mmd_t * mdp,md_node_t * nodep,char * sp,uint64_t value)190*11596SJason.Beloro@Sun.COM md_add_value_property(mmd_t *mdp, md_node_t *nodep, char *sp, uint64_t value)
191*11596SJason.Beloro@Sun.COM {
192*11596SJason.Beloro@Sun.COM 	md_prop_t *propp;
193*11596SJason.Beloro@Sun.COM 
194*11596SJason.Beloro@Sun.COM 	propp = md_new_property(mdp, nodep, MDET_PROP_VAL, sp);
195*11596SJason.Beloro@Sun.COM 	if (propp == NULL)
196*11596SJason.Beloro@Sun.COM 		return (ENOMEM);
197*11596SJason.Beloro@Sun.COM 	propp->d.value = value;
198*11596SJason.Beloro@Sun.COM 	return (0);
199*11596SJason.Beloro@Sun.COM }
200*11596SJason.Beloro@Sun.COM 
201*11596SJason.Beloro@Sun.COM int
md_add_string_property(mmd_t * mdp,md_node_t * nodep,char * sp,char * bufp)202*11596SJason.Beloro@Sun.COM md_add_string_property(mmd_t *mdp, md_node_t *nodep, char *sp, char *bufp)
203*11596SJason.Beloro@Sun.COM {
204*11596SJason.Beloro@Sun.COM 	md_prop_t *propp;
205*11596SJason.Beloro@Sun.COM 	md_data_block_t *dbp;
206*11596SJason.Beloro@Sun.COM 
207*11596SJason.Beloro@Sun.COM 	dbp = md_new_data_block(mdp, (uint8_t *)bufp, strlen(bufp) + 1);
208*11596SJason.Beloro@Sun.COM 	if (dbp == NULL)
209*11596SJason.Beloro@Sun.COM 		return (ENOMEM);
210*11596SJason.Beloro@Sun.COM 	propp = md_new_property(mdp, nodep, MDET_PROP_STR, sp);
211*11596SJason.Beloro@Sun.COM 	if (propp == NULL) {
212*11596SJason.Beloro@Sun.COM 		md_free_data_block(mdp, dbp);
213*11596SJason.Beloro@Sun.COM 		return (NULL);
214*11596SJason.Beloro@Sun.COM 	}
215*11596SJason.Beloro@Sun.COM 	propp->d.dbp = dbp;
216*11596SJason.Beloro@Sun.COM 	return (0);
217*11596SJason.Beloro@Sun.COM }
218*11596SJason.Beloro@Sun.COM 
219*11596SJason.Beloro@Sun.COM int
md_add_data_property(mmd_t * mdp,md_node_t * nodep,char * sp,int len,uint8_t * bufp)220*11596SJason.Beloro@Sun.COM md_add_data_property(mmd_t *mdp, md_node_t *nodep, char *sp, int len,
221*11596SJason.Beloro@Sun.COM     uint8_t *bufp)
222*11596SJason.Beloro@Sun.COM {
223*11596SJason.Beloro@Sun.COM 	md_prop_t *propp;
224*11596SJason.Beloro@Sun.COM 	md_data_block_t *dbp;
225*11596SJason.Beloro@Sun.COM 
226*11596SJason.Beloro@Sun.COM 	dbp = md_new_data_block(mdp, bufp, len);
227*11596SJason.Beloro@Sun.COM 	if (dbp == NULL)
228*11596SJason.Beloro@Sun.COM 		return (ENOMEM);
229*11596SJason.Beloro@Sun.COM 
230*11596SJason.Beloro@Sun.COM 	propp = md_new_property(mdp, nodep, MDET_PROP_DAT, sp);
231*11596SJason.Beloro@Sun.COM 	if (propp == NULL) {
232*11596SJason.Beloro@Sun.COM 		md_free_data_block(mdp, dbp);
233*11596SJason.Beloro@Sun.COM 		return (ENOMEM);
234*11596SJason.Beloro@Sun.COM 	}
235*11596SJason.Beloro@Sun.COM 	propp->d.dbp = dbp;
236*11596SJason.Beloro@Sun.COM 	return (0);
237*11596SJason.Beloro@Sun.COM }
238*11596SJason.Beloro@Sun.COM 
239*11596SJason.Beloro@Sun.COM static int
md_add_arc_property(mmd_t * mdp,md_node_t * nodep,char * arcnamep,md_node_t * tgtnodep)240*11596SJason.Beloro@Sun.COM md_add_arc_property(mmd_t *mdp, md_node_t *nodep, char *arcnamep,
241*11596SJason.Beloro@Sun.COM     md_node_t *tgtnodep)
242*11596SJason.Beloro@Sun.COM {
243*11596SJason.Beloro@Sun.COM 	md_prop_t *propp;
244*11596SJason.Beloro@Sun.COM 
245*11596SJason.Beloro@Sun.COM 	propp = md_new_property(mdp, nodep, MDET_PROP_ARC, arcnamep);
246*11596SJason.Beloro@Sun.COM 	if (propp == NULL)
247*11596SJason.Beloro@Sun.COM 		return (ENOMEM);
248*11596SJason.Beloro@Sun.COM 	propp->d.arc.is_ptr = B_TRUE;
249*11596SJason.Beloro@Sun.COM 	propp->d.arc.val.nodep = tgtnodep;
250*11596SJason.Beloro@Sun.COM 	return (0);
251*11596SJason.Beloro@Sun.COM }
252*11596SJason.Beloro@Sun.COM 
253*11596SJason.Beloro@Sun.COM md_node_t *
md_link_new_node(mmd_t * mdp,char * nodenamep,md_node_t * parentnodep,char * linktonewp,char * linkbackp)254*11596SJason.Beloro@Sun.COM md_link_new_node(mmd_t *mdp, char *nodenamep, md_node_t *parentnodep,
255*11596SJason.Beloro@Sun.COM     char *linktonewp, char *linkbackp)
256*11596SJason.Beloro@Sun.COM {
257*11596SJason.Beloro@Sun.COM 	md_node_t *nodep;
258*11596SJason.Beloro@Sun.COM 
259*11596SJason.Beloro@Sun.COM 	nodep = md_new_node(mdp, nodenamep);
260*11596SJason.Beloro@Sun.COM 	if (nodep == NULL)
261*11596SJason.Beloro@Sun.COM 		return (NULL);
262*11596SJason.Beloro@Sun.COM 
263*11596SJason.Beloro@Sun.COM 	ASSERT(linktonewp != NULL);
264*11596SJason.Beloro@Sun.COM 	ASSERT(parentnodep != NULL && !parentnodep->deleted);
265*11596SJason.Beloro@Sun.COM 
266*11596SJason.Beloro@Sun.COM 	if (md_add_arc_property(mdp, parentnodep, linktonewp, nodep) != 0) {
267*11596SJason.Beloro@Sun.COM 		return (NULL);
268*11596SJason.Beloro@Sun.COM 	}
269*11596SJason.Beloro@Sun.COM 
270*11596SJason.Beloro@Sun.COM 	if (linkbackp != NULL) {
271*11596SJason.Beloro@Sun.COM 		if (md_add_arc_property(mdp,
272*11596SJason.Beloro@Sun.COM 		    nodep, linkbackp, parentnodep) != 0) {
273*11596SJason.Beloro@Sun.COM 			return (NULL);
274*11596SJason.Beloro@Sun.COM 		}
275*11596SJason.Beloro@Sun.COM 	}
276*11596SJason.Beloro@Sun.COM 
277*11596SJason.Beloro@Sun.COM 	return (nodep);
278*11596SJason.Beloro@Sun.COM }
279*11596SJason.Beloro@Sun.COM 
280*11596SJason.Beloro@Sun.COM void
md_destroy(mmd_t * mdp)281*11596SJason.Beloro@Sun.COM md_destroy(mmd_t *mdp)
282*11596SJason.Beloro@Sun.COM {
283*11596SJason.Beloro@Sun.COM 	md_node_t *nodep;
284*11596SJason.Beloro@Sun.COM 
285*11596SJason.Beloro@Sun.COM 	for (nodep = CHAIN_START(mdp->node_list); nodep != NULL; ) {
286*11596SJason.Beloro@Sun.COM 		md_node_t *tmp_nodep;
287*11596SJason.Beloro@Sun.COM 
288*11596SJason.Beloro@Sun.COM 		tmp_nodep = nodep->nextp;
289*11596SJason.Beloro@Sun.COM 		md_free_node(mdp, nodep);
290*11596SJason.Beloro@Sun.COM 
291*11596SJason.Beloro@Sun.COM 		nodep = tmp_nodep;
292*11596SJason.Beloro@Sun.COM 	}
293*11596SJason.Beloro@Sun.COM 
294*11596SJason.Beloro@Sun.COM 	/* should have deleted all the string refs by here */
295*11596SJason.Beloro@Sun.COM 	ASSERT(CHAIN_LENGTH(mdp->string_list) == 0);
296*11596SJason.Beloro@Sun.COM 	free(mdp);
297*11596SJason.Beloro@Sun.COM }
298*11596SJason.Beloro@Sun.COM 
299*11596SJason.Beloro@Sun.COM void
md_free_node(mmd_t * mdp,md_node_t * nodep)300*11596SJason.Beloro@Sun.COM md_free_node(mmd_t *mdp, md_node_t *nodep)
301*11596SJason.Beloro@Sun.COM {
302*11596SJason.Beloro@Sun.COM 	md_prop_t *propp;
303*11596SJason.Beloro@Sun.COM 
304*11596SJason.Beloro@Sun.COM 	if (nodep->typep != NULL)
305*11596SJason.Beloro@Sun.COM 		md_free_string(mdp, nodep->typep);
306*11596SJason.Beloro@Sun.COM 
307*11596SJason.Beloro@Sun.COM 	for (propp = CHAIN_START(nodep->prop_list); propp != NULL; ) {
308*11596SJason.Beloro@Sun.COM 		md_prop_t *tmp_propp;
309*11596SJason.Beloro@Sun.COM 
310*11596SJason.Beloro@Sun.COM 		tmp_propp = propp->nextp;
311*11596SJason.Beloro@Sun.COM 		md_free_prop(mdp, propp);
312*11596SJason.Beloro@Sun.COM 
313*11596SJason.Beloro@Sun.COM 		propp = tmp_propp;
314*11596SJason.Beloro@Sun.COM 	}
315*11596SJason.Beloro@Sun.COM 
316*11596SJason.Beloro@Sun.COM 	free(nodep);
317*11596SJason.Beloro@Sun.COM }
318*11596SJason.Beloro@Sun.COM 
319*11596SJason.Beloro@Sun.COM static void
md_free_prop(mmd_t * mdp,md_prop_t * propp)320*11596SJason.Beloro@Sun.COM md_free_prop(mmd_t *mdp, md_prop_t *propp)
321*11596SJason.Beloro@Sun.COM {
322*11596SJason.Beloro@Sun.COM 	if (propp->sp != NULL)
323*11596SJason.Beloro@Sun.COM 		md_free_string(mdp, propp->sp);
324*11596SJason.Beloro@Sun.COM 
325*11596SJason.Beloro@Sun.COM 	switch (propp->type) {
326*11596SJason.Beloro@Sun.COM 	case MDET_PROP_VAL:
327*11596SJason.Beloro@Sun.COM 		break;
328*11596SJason.Beloro@Sun.COM 
329*11596SJason.Beloro@Sun.COM 	case MDET_PROP_ARC:
330*11596SJason.Beloro@Sun.COM 		break;
331*11596SJason.Beloro@Sun.COM 
332*11596SJason.Beloro@Sun.COM 	case MDET_PROP_STR:
333*11596SJason.Beloro@Sun.COM 	case MDET_PROP_DAT:
334*11596SJason.Beloro@Sun.COM 		md_free_data_block(mdp, propp->d.dbp);
335*11596SJason.Beloro@Sun.COM 		break;
336*11596SJason.Beloro@Sun.COM 
337*11596SJason.Beloro@Sun.COM 	default:
338*11596SJason.Beloro@Sun.COM 		ASSERT(B_FALSE);
339*11596SJason.Beloro@Sun.COM 	}
340*11596SJason.Beloro@Sun.COM 
341*11596SJason.Beloro@Sun.COM 	free(propp);
342*11596SJason.Beloro@Sun.COM }
343*11596SJason.Beloro@Sun.COM 
344*11596SJason.Beloro@Sun.COM static void
md_free_string(mmd_t * mdp,md_string_t * msp)345*11596SJason.Beloro@Sun.COM md_free_string(mmd_t *mdp, md_string_t *msp)
346*11596SJason.Beloro@Sun.COM {
347*11596SJason.Beloro@Sun.COM 	ASSERT(msp->ref_cnt > 0);
348*11596SJason.Beloro@Sun.COM 
349*11596SJason.Beloro@Sun.COM 	msp->ref_cnt--;
350*11596SJason.Beloro@Sun.COM 
351*11596SJason.Beloro@Sun.COM 	if (msp->ref_cnt == 0) {
352*11596SJason.Beloro@Sun.COM 		free(msp->strp);
353*11596SJason.Beloro@Sun.COM 		mdp->string_list.startp = msp->nextp;
354*11596SJason.Beloro@Sun.COM 		free(msp);
355*11596SJason.Beloro@Sun.COM 	}
356*11596SJason.Beloro@Sun.COM }
357*11596SJason.Beloro@Sun.COM 
358*11596SJason.Beloro@Sun.COM static void
md_free_data_block(mmd_t * mdp,md_data_block_t * mdbp)359*11596SJason.Beloro@Sun.COM md_free_data_block(mmd_t *mdp, md_data_block_t *mdbp)
360*11596SJason.Beloro@Sun.COM {
361*11596SJason.Beloro@Sun.COM 	ASSERT(mdbp->ref_cnt > 0);
362*11596SJason.Beloro@Sun.COM 
363*11596SJason.Beloro@Sun.COM 	mdbp->ref_cnt--;
364*11596SJason.Beloro@Sun.COM 
365*11596SJason.Beloro@Sun.COM 	if (mdbp->ref_cnt == 0) {
366*11596SJason.Beloro@Sun.COM 		free(mdbp->datap);
367*11596SJason.Beloro@Sun.COM 		mdp->data_block_list.startp = mdbp->nextp;
368*11596SJason.Beloro@Sun.COM 		free(mdbp);
369*11596SJason.Beloro@Sun.COM 	}
370*11596SJason.Beloro@Sun.COM }
371*11596SJason.Beloro@Sun.COM 
372*11596SJason.Beloro@Sun.COM mmd_t *
md_new_md(void)373*11596SJason.Beloro@Sun.COM md_new_md(void)
374*11596SJason.Beloro@Sun.COM {
375*11596SJason.Beloro@Sun.COM 	return ((mmd_t *)calloc(1, sizeof (mmd_t)));
376*11596SJason.Beloro@Sun.COM }
377*11596SJason.Beloro@Sun.COM 
378*11596SJason.Beloro@Sun.COM static void
md_fix_name(md_element_t * mdep,md_prop_t * propp)379*11596SJason.Beloro@Sun.COM md_fix_name(md_element_t *mdep, md_prop_t *propp)
380*11596SJason.Beloro@Sun.COM {
381*11596SJason.Beloro@Sun.COM 	mdep->name_len = htomd8(propp->sp->size - 1);
382*11596SJason.Beloro@Sun.COM 	mdep->name_offset = htomd32(propp->sp->build_offset);
383*11596SJason.Beloro@Sun.COM }
384*11596SJason.Beloro@Sun.COM 
385*11596SJason.Beloro@Sun.COM void
create_mde(md_element_t * mdep,int type,md_node_t * nodep,md_prop_t * propp)386*11596SJason.Beloro@Sun.COM create_mde(md_element_t *mdep, int type, md_node_t *nodep, md_prop_t *propp)
387*11596SJason.Beloro@Sun.COM {
388*11596SJason.Beloro@Sun.COM 	(void) memset(mdep, 0, MD_ELEMENT_SIZE);
389*11596SJason.Beloro@Sun.COM 	mdep->tag = htomd8(type);
390*11596SJason.Beloro@Sun.COM 
391*11596SJason.Beloro@Sun.COM 	switch (type) {
392*11596SJason.Beloro@Sun.COM 	case MDET_NODE:
393*11596SJason.Beloro@Sun.COM 		mdep->d.prop_idx = htomd32(nodep->next_index);
394*11596SJason.Beloro@Sun.COM 		mdep->name_len = htomd8(nodep->typep->size - 1);
395*11596SJason.Beloro@Sun.COM 		mdep->name_offset = htomd32(nodep->typep->build_offset);
396*11596SJason.Beloro@Sun.COM 		break;
397*11596SJason.Beloro@Sun.COM 
398*11596SJason.Beloro@Sun.COM 	case MDET_PROP_ARC:
399*11596SJason.Beloro@Sun.COM 		ASSERT(propp->d.arc.is_ptr);
400*11596SJason.Beloro@Sun.COM 		mdep->d.prop_idx = htomd64(propp->d.arc.val.nodep->build_index);
401*11596SJason.Beloro@Sun.COM 		md_fix_name(mdep, propp);
402*11596SJason.Beloro@Sun.COM 		break;
403*11596SJason.Beloro@Sun.COM 
404*11596SJason.Beloro@Sun.COM 	case MDET_PROP_VAL:
405*11596SJason.Beloro@Sun.COM 		mdep->d.prop_val = htomd64(propp->d.value);
406*11596SJason.Beloro@Sun.COM 		md_fix_name(mdep, propp);
407*11596SJason.Beloro@Sun.COM 		break;
408*11596SJason.Beloro@Sun.COM 
409*11596SJason.Beloro@Sun.COM 	case MDET_PROP_STR:
410*11596SJason.Beloro@Sun.COM 	case MDET_PROP_DAT:
411*11596SJason.Beloro@Sun.COM 		mdep->d.prop_data.offset = htomd32(propp->d.dbp->build_offset);
412*11596SJason.Beloro@Sun.COM 		mdep->d.prop_data.len = htomd32(propp->d.dbp->size);
413*11596SJason.Beloro@Sun.COM 		md_fix_name(mdep, propp);
414*11596SJason.Beloro@Sun.COM 		break;
415*11596SJason.Beloro@Sun.COM 
416*11596SJason.Beloro@Sun.COM 	case MDET_NULL:
417*11596SJason.Beloro@Sun.COM 	case MDET_NODE_END:
418*11596SJason.Beloro@Sun.COM 	case MDET_LIST_END:
419*11596SJason.Beloro@Sun.COM 		break;
420*11596SJason.Beloro@Sun.COM 
421*11596SJason.Beloro@Sun.COM 	default:
422*11596SJason.Beloro@Sun.COM 		ASSERT(B_FALSE);
423*11596SJason.Beloro@Sun.COM 	}
424*11596SJason.Beloro@Sun.COM }
425*11596SJason.Beloro@Sun.COM 
426*11596SJason.Beloro@Sun.COM int
md_gen_bin(mmd_t * mdp,uint8_t ** bufvalp)427*11596SJason.Beloro@Sun.COM md_gen_bin(mmd_t *mdp, uint8_t **bufvalp)
428*11596SJason.Beloro@Sun.COM {
429*11596SJason.Beloro@Sun.COM 	uint32_t offset;
430*11596SJason.Beloro@Sun.COM 	md_node_t *nodep;
431*11596SJason.Beloro@Sun.COM 	md_data_block_t *mdbp;
432*11596SJason.Beloro@Sun.COM 	md_string_t *msp;
433*11596SJason.Beloro@Sun.COM 	md_header_t *mdhp;
434*11596SJason.Beloro@Sun.COM 	md_element_t *mdep;
435*11596SJason.Beloro@Sun.COM 	uint32_t strings_size;
436*11596SJason.Beloro@Sun.COM 	uint32_t data_block_size;
437*11596SJason.Beloro@Sun.COM 	int total_size;
438*11596SJason.Beloro@Sun.COM 	uint8_t *bufferp;
439*11596SJason.Beloro@Sun.COM 	uint8_t *string_bufferp;
440*11596SJason.Beloro@Sun.COM 	uint8_t *data_block_bufferp;
441*11596SJason.Beloro@Sun.COM 
442*11596SJason.Beloro@Sun.COM 	/*
443*11596SJason.Beloro@Sun.COM 	 * Skip through strings to compute offsets.
444*11596SJason.Beloro@Sun.COM 	 */
445*11596SJason.Beloro@Sun.COM 	offset = 0;
446*11596SJason.Beloro@Sun.COM 	for (msp = CHAIN_START(mdp->string_list); msp != NULL;
447*11596SJason.Beloro@Sun.COM 	    msp = msp->nextp) {
448*11596SJason.Beloro@Sun.COM 		msp->build_offset = offset;
449*11596SJason.Beloro@Sun.COM 		offset += msp->size;
450*11596SJason.Beloro@Sun.COM 	}
451*11596SJason.Beloro@Sun.COM 	strings_size = P2ROUNDUP(offset, MD_ALIGNMENT_SIZE);
452*11596SJason.Beloro@Sun.COM 
453*11596SJason.Beloro@Sun.COM 	/*
454*11596SJason.Beloro@Sun.COM 	 * Skip through data blocks to compute offsets.
455*11596SJason.Beloro@Sun.COM 	 */
456*11596SJason.Beloro@Sun.COM 
457*11596SJason.Beloro@Sun.COM 	offset = 0;
458*11596SJason.Beloro@Sun.COM 	for (mdbp = CHAIN_START(mdp->data_block_list); mdbp != NULL;
459*11596SJason.Beloro@Sun.COM 	    mdbp = mdbp->nextp) {
460*11596SJason.Beloro@Sun.COM 		mdbp->build_offset = offset;
461*11596SJason.Beloro@Sun.COM 		offset += mdbp->size;
462*11596SJason.Beloro@Sun.COM 		offset = P2ROUNDUP(offset, MD_ALIGNMENT_SIZE);
463*11596SJason.Beloro@Sun.COM 	}
464*11596SJason.Beloro@Sun.COM 	data_block_size = P2ROUNDUP(offset, MD_ALIGNMENT_SIZE);
465*11596SJason.Beloro@Sun.COM 
466*11596SJason.Beloro@Sun.COM 	/*
467*11596SJason.Beloro@Sun.COM 	 * Compute the MD elements required to build the element list.
468*11596SJason.Beloro@Sun.COM 	 * For each node there is a node start and end, and one
469*11596SJason.Beloro@Sun.COM 	 * element for each property.
470*11596SJason.Beloro@Sun.COM 	 */
471*11596SJason.Beloro@Sun.COM 
472*11596SJason.Beloro@Sun.COM 	offset = 0;
473*11596SJason.Beloro@Sun.COM 	for (nodep = CHAIN_START(mdp->node_list); nodep != NULL;
474*11596SJason.Beloro@Sun.COM 	    nodep = nodep->nextp) {
475*11596SJason.Beloro@Sun.COM 		nodep->build_index = offset;
476*11596SJason.Beloro@Sun.COM 		offset += 2 + CHAIN_LENGTH(nodep->prop_list);
477*11596SJason.Beloro@Sun.COM 		nodep->next_index = offset;
478*11596SJason.Beloro@Sun.COM 	}
479*11596SJason.Beloro@Sun.COM 	offset += 1;	/* add the LIST_END element */
480*11596SJason.Beloro@Sun.COM 
481*11596SJason.Beloro@Sun.COM 	total_size = MD_HEADER_SIZE + offset * MD_ELEMENT_SIZE +
482*11596SJason.Beloro@Sun.COM 	    strings_size + data_block_size;
483*11596SJason.Beloro@Sun.COM 
484*11596SJason.Beloro@Sun.COM 	/*
485*11596SJason.Beloro@Sun.COM 	 * Allocate output buffer.
486*11596SJason.Beloro@Sun.COM 	 */
487*11596SJason.Beloro@Sun.COM 
488*11596SJason.Beloro@Sun.COM 	bufferp = calloc(total_size, sizeof (uint8_t));
489*11596SJason.Beloro@Sun.COM 	if (bufferp == NULL)
490*11596SJason.Beloro@Sun.COM 		return (0);
491*11596SJason.Beloro@Sun.COM 
492*11596SJason.Beloro@Sun.COM 	/* LINTED */
493*11596SJason.Beloro@Sun.COM 	mdhp = (md_header_t *)bufferp;
494*11596SJason.Beloro@Sun.COM 
495*11596SJason.Beloro@Sun.COM 	string_bufferp = bufferp + MD_HEADER_SIZE + offset * MD_ELEMENT_SIZE;
496*11596SJason.Beloro@Sun.COM 	data_block_bufferp = string_bufferp + strings_size;
497*11596SJason.Beloro@Sun.COM 
498*11596SJason.Beloro@Sun.COM 	mdhp->transport_version = htomd32(MD_TRANSPORT_VERSION);
499*11596SJason.Beloro@Sun.COM 	mdhp->node_blk_sz = htomd32(offset * MD_ELEMENT_SIZE);
500*11596SJason.Beloro@Sun.COM 	mdhp->name_blk_sz = htomd32(strings_size);
501*11596SJason.Beloro@Sun.COM 	mdhp->data_blk_sz = htomd32(data_block_size);
502*11596SJason.Beloro@Sun.COM 
503*11596SJason.Beloro@Sun.COM 	/*
504*11596SJason.Beloro@Sun.COM 	 * Build the element list.
505*11596SJason.Beloro@Sun.COM 	 * For each node there is a node start and end, and one
506*11596SJason.Beloro@Sun.COM 	 * element for each property.
507*11596SJason.Beloro@Sun.COM 	 */
508*11596SJason.Beloro@Sun.COM 
509*11596SJason.Beloro@Sun.COM 	offset = 0;
510*11596SJason.Beloro@Sun.COM 	/* LINTED */
511*11596SJason.Beloro@Sun.COM 	mdep = (md_element_t *)(bufferp + MD_HEADER_SIZE);
512*11596SJason.Beloro@Sun.COM 	for (nodep = CHAIN_START(mdp->node_list); nodep != NULL;
513*11596SJason.Beloro@Sun.COM 	    nodep = nodep->nextp) {
514*11596SJason.Beloro@Sun.COM 		md_prop_t *propp;
515*11596SJason.Beloro@Sun.COM 
516*11596SJason.Beloro@Sun.COM 		create_mde(mdep, MDET_NODE, nodep, NULL);
517*11596SJason.Beloro@Sun.COM 		mdep++;
518*11596SJason.Beloro@Sun.COM 
519*11596SJason.Beloro@Sun.COM 		for (propp = CHAIN_START(nodep->prop_list); propp != NULL;
520*11596SJason.Beloro@Sun.COM 		    propp = propp->nextp) {
521*11596SJason.Beloro@Sun.COM 			create_mde(mdep, propp->type, nodep, propp);
522*11596SJason.Beloro@Sun.COM 			mdep++;
523*11596SJason.Beloro@Sun.COM 		}
524*11596SJason.Beloro@Sun.COM 
525*11596SJason.Beloro@Sun.COM 		create_mde(mdep, MDET_NODE_END, NULL, NULL);
526*11596SJason.Beloro@Sun.COM 		mdep++;
527*11596SJason.Beloro@Sun.COM 	}
528*11596SJason.Beloro@Sun.COM 
529*11596SJason.Beloro@Sun.COM 	create_mde(mdep, MDET_LIST_END, NULL, NULL);
530*11596SJason.Beloro@Sun.COM 	mdep++;
531*11596SJason.Beloro@Sun.COM 
532*11596SJason.Beloro@Sun.COM 	/*
533*11596SJason.Beloro@Sun.COM 	 * Quick sanity check.
534*11596SJason.Beloro@Sun.COM 	 */
535*11596SJason.Beloro@Sun.COM 
536*11596SJason.Beloro@Sun.COM 	ASSERT(((uint8_t *)mdep) == ((uint8_t *)string_bufferp));
537*11596SJason.Beloro@Sun.COM 
538*11596SJason.Beloro@Sun.COM 	/*
539*11596SJason.Beloro@Sun.COM 	 * Skip through strings and stash them..
540*11596SJason.Beloro@Sun.COM 	 */
541*11596SJason.Beloro@Sun.COM 
542*11596SJason.Beloro@Sun.COM 	offset = 0;
543*11596SJason.Beloro@Sun.COM 	for (msp = CHAIN_START(mdp->string_list); msp != NULL;
544*11596SJason.Beloro@Sun.COM 	    msp = msp->nextp) {
545*11596SJason.Beloro@Sun.COM 		(void) memcpy(string_bufferp + msp->build_offset, msp->strp,
546*11596SJason.Beloro@Sun.COM 		    msp->size);
547*11596SJason.Beloro@Sun.COM 	}
548*11596SJason.Beloro@Sun.COM 
549*11596SJason.Beloro@Sun.COM 	/*
550*11596SJason.Beloro@Sun.COM 	 * Skip through data blocks and stash them.
551*11596SJason.Beloro@Sun.COM 	 */
552*11596SJason.Beloro@Sun.COM 
553*11596SJason.Beloro@Sun.COM 	offset = 0;
554*11596SJason.Beloro@Sun.COM 	for (mdbp = CHAIN_START(mdp->data_block_list); mdbp != NULL;
555*11596SJason.Beloro@Sun.COM 	    mdbp = mdbp->nextp) {
556*11596SJason.Beloro@Sun.COM 		(void) memcpy(data_block_bufferp + mdbp->build_offset,
557*11596SJason.Beloro@Sun.COM 		    mdbp->datap, mdbp->size);
558*11596SJason.Beloro@Sun.COM 	}
559*11596SJason.Beloro@Sun.COM 
560*11596SJason.Beloro@Sun.COM 	*bufvalp = bufferp;
561*11596SJason.Beloro@Sun.COM 	return (total_size);
562*11596SJason.Beloro@Sun.COM }
563