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