xref: /titanic_52/usr/src/uts/common/tnf/tnf_writer.c (revision 7fd791373689a6af05e27efec3b1ab556e02aa23)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *	Copyright (c) 1994, by Sun Microsytems, Inc.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #ifndef DEBUG
29 #define	NDEBUG	1
30 #endif
31 
32 #ifdef _KERNEL
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/tnf_com.h>
36 #include <sys/tnf_writer.h>
37 #include <sys/debug.h>
38 #include "tnf_types.h"
39 #include "tnf_trace.h"
40 #else	/* _KERNEL */
41 #include <stdlib.h>
42 #include <string.h>
43 #include <tnf/com.h>
44 #include <tnf/writer.h>
45 #include <assert.h>
46 #include "tnf_types.h"
47 #include <tnf_trace.h>
48 #endif	/* _KERNEL */
49 
50 /*
51  * Defines
52  */
53 
54 #ifdef _KERNEL
55 #define	TNF_ASSERT(expr)	ASSERT(expr)
56 #else
57 #define	TNF_ASSERT(expr)	assert(expr)
58 #endif
59 
60 /*
61  * Local functions
62  */
63 
64 static tnf_record_p tnf_root_tag_1(tnf_ops_t *, tnf_tag_data_t *);
65 
66 /*
67  * TNF tag version 1
68  */
69 
70 tnf_tag_version_t __tnf_tag_version_1_info =  {
71 	sizeof (tnf_tag_version_t),
72 	sizeof (tnf_tag_data_t)
73 };
74 
75 /*
76  * Pure abstract types
77  */
78 
79 TNF_ABSTRACT_TAG(tnf_inline);
80 TNF_ABSTRACT_TAG(tnf_tagged);
81 
82 /*
83  * Scalar types
84  */
85 
86 static tnf_tag_data_t	**std_scalar_properties[] = {
87 	&TAG_DATA(tnf_inline),
88 	&TAG_DATA(tnf_scalar),
89 	0};
90 
91 tnf_tag_data_t	***tnf_scalar_properties = std_scalar_properties;
92 
93 TNF_SCALAR_TAG(tnf_scalar, 0, 0, TNF_UNKNOWN);
94 
95 TNF_STD_SCALAR_TAG(tnf_char, TNF_UNKNOWN); /* XXX */
96 TNF_STD_SCALAR_TAG(tnf_int8, TNF_INT32);
97 TNF_STD_SCALAR_TAG(tnf_uint8, TNF_UINT32);
98 TNF_STD_SCALAR_TAG(tnf_int16, TNF_INT32);
99 TNF_STD_SCALAR_TAG(tnf_uint16, TNF_UINT32);
100 TNF_STD_SCALAR_TAG(tnf_int32, TNF_INT32);
101 TNF_STD_SCALAR_TAG(tnf_uint32, TNF_UINT32);
102 TNF_STD_SCALAR_TAG(tnf_int64, TNF_INT64);
103 TNF_STD_SCALAR_TAG(tnf_uint64, TNF_UINT64);
104 
105 TNF_STD_SCALAR_TAG(tnf_float32, TNF_FLOAT32);
106 TNF_STD_SCALAR_TAG(tnf_float64, TNF_FLOAT64);
107 
108 /*
109  * Array types
110  */
111 
112 static tnf_tag_data_t	**array_properties[] = {
113 	&TAG_DATA(tnf_array),
114 	0
115 };
116 static tnf_tag_data_t	***abstract_array_properties = array_properties;
117 
118 static tnf_tag_data_t	**std_array_properties[] = {
119 	&TAG_DATA(tnf_array),
120 	&TAG_DATA(tnf_tagged),
121 	0
122 };
123 /* Exported */
124 tnf_tag_data_t	***tnf_array_properties = std_array_properties;
125 
126 /* Exported */
127 tnf_tag_data_t	**tnf_array_slots[] = {
128 	&TAG_DATA(tnf_tag),
129 	&TAG_DATA(tnf_self_size),
130 	0
131 };
132 
133 TNF_ARRAY_TAG(tnf_array, TNF_NULL, abstract_array_properties,
134 			TNF_NULL, TNF_UNKNOWN);
135 
136 TNF_STD_ARRAY_TAG(tnf_string, tnf_char, TNF_STRING);
137 TNF_STD_ARRAY_TAG(tnf_type_array, tnf_type, TNF_ARRAY);
138 TNF_STD_ARRAY_TAG(tnf_name_array, tnf_name, TNF_ARRAY);
139 
140 /*
141  * Derived types
142  */
143 
144 static tnf_tag_data_t	**derived_properties[] = {
145 	&TAG_DATA(tnf_derived),
146 	0
147 };
148 /* Exported */
149 tnf_tag_data_t	***tnf_derived_properties = derived_properties;
150 
151 TNF_DERIVED_TAG(tnf_derived, TNF_NULL,
152 		tnf_derived_properties, TNF_NULL, TNF_NULL, TNF_UNKNOWN);
153 
154 TNF_STD_DERIVED_TAG(tnf_align, tnf_uint32,
155 		tnf_derived_properties, TNF_UINT32);
156 
157 TNF_STD_DERIVED_TAG(tnf_derived_base, tnf_type,
158 		tnf_derived_properties, TNF_OPAQUE);
159 
160 TNF_STD_DERIVED_TAG(tnf_element_type, tnf_type,
161 		tnf_derived_properties, TNF_OPAQUE);
162 
163 TNF_STD_DERIVED_TAG(tnf_header_size, tnf_uint32,
164 		tnf_derived_properties, TNF_UINT32);
165 
166 TNF_STD_DERIVED_TAG(tnf_name, tnf_string,
167 		tnf_derived_properties, TNF_STRING);
168 
169 #if defined(_LP64)
170 
171 TNF_STD_DERIVED_TAG(tnf_opaque, tnf_uint64,
172 		tnf_derived_properties, TNF_OPAQUE);
173 
174 #else
175 
176 TNF_STD_DERIVED_TAG(tnf_opaque, tnf_uint32,
177 		tnf_derived_properties, TNF_OPAQUE);
178 
179 #endif /* defined(_LP64) */
180 
181 TNF_STD_DERIVED_TAG(tnf_properties, tnf_type_array,
182 		tnf_derived_properties, TNF_ARRAY);
183 
184 TNF_STD_DERIVED_TAG(tnf_self_size, tnf_uint32,
185 		tnf_derived_properties, TNF_UINT32);
186 
187 TNF_STD_DERIVED_TAG(tnf_size, tnf_ulong,
188 		tnf_derived_properties, TNF_ULONG);
189 
190 TNF_STD_DERIVED_TAG(tnf_slot_names, tnf_name_array,
191 		tnf_derived_properties, TNF_ARRAY);
192 
193 TNF_STD_DERIVED_TAG(tnf_slot_types, tnf_type_array,
194 		tnf_derived_properties, TNF_ARRAY);
195 
196 TNF_STD_DERIVED_TAG(tnf_tag, tnf_type,
197 		tnf_derived_properties, TNF_OPAQUE);
198 
199 TNF_STD_DERIVED_TAG(tnf_tag_arg, tnf_tagged,
200 		tnf_derived_properties, TNF_OPAQUE);
201 
202 TNF_STD_DERIVED_TAG(tnf_type_size, tnf_uint32,
203 		tnf_derived_properties, TNF_UINT32);
204 
205 /*
206  * Struct types
207  */
208 
209 static tnf_tag_data_t	**no_properties[] = { 0 };
210 tnf_tag_data_t	***tnf_no_properties = no_properties;
211 
212 static tnf_tag_data_t	**no_slots[] = { 0 };
213 
214 static tnf_tag_data_t	**std_struct_properties[] = {
215 	&TAG_DATA(tnf_tagged),
216 	&TAG_DATA(tnf_struct),
217 	0};
218 /* Exported */
219 tnf_tag_data_t	***tnf_struct_properties = std_struct_properties;
220 
221 TNF_STRUCT_TAG(tnf_struct, tnf_no_properties, no_slots, 0, 0);
222 
223 /*
224  * File header - CAUTION - has to be in sync with com.h
225  */
226 
227 static char	*file_header_slot_names[] = {
228 	TNF_N_TAG,
229 	TNF_N_FILE_VERSION,
230 	TNF_N_FILE_HEADER_SIZE,
231 	TNF_N_FILE_LOGICAL_SIZE,
232 	TNF_N_BLOCK_HEADER_SIZE,
233 	TNF_N_BLOCK_SIZE,
234 	TNF_N_DIRECTORY_SIZE,
235 	TNF_N_BLOCK_COUNT,
236 	TNF_N_BLOCKS_VALID,
237 	/* XXX add writer-specific opaque slots here for reader */
238 	0};
239 
240 static tnf_tag_data_t	**file_header_slots[] = {
241 	&TAG_DATA(tnf_tag),		/* tag			*/
242 	&TAG_DATA(tnf_uint32),		/* file_version 	*/
243 	&TAG_DATA(tnf_uint32),		/* file_header_size	*/
244 	&TAG_DATA(tnf_uint32),		/* file_logical_size	*/
245 	&TAG_DATA(tnf_uint32),		/* block_header_size 	*/
246 	&TAG_DATA(tnf_uint32),		/* block_size 		*/
247 	&TAG_DATA(tnf_uint32),		/* directory_size 	*/
248 	&TAG_DATA(tnf_uint32),		/* block_count 		*/
249 	&TAG_DATA(tnf_uint32),		/* blocks_valid 	*/
250 	/* XXX add writer-specific opaque slots here for reader */
251 	0};
252 
253 /* size of tnf_file_header has the size of the magic number subtracted */
254 TNF_STD_STRUCT_TAG(tnf_file_header,
255 		file_header_slots,
256 		file_header_slot_names,
257 		sizeof (tnf_buf_file_header_t) - sizeof (tnf_uint32_t));
258 
259 /*
260  * Block header - CAUTION - has to be in sync with com.h
261  */
262 
263 static char	*block_header_slot_names[] = {
264 	TNF_N_TAG,
265 	TNF_N_GENERATION,
266 	TNF_N_BYTES_VALID,
267 	"A_lock",			/* XXX */
268 	"B_lock",			/* XXX */
269 	"next_block",			/* XXX */
270 	0};
271 
272 static tnf_tag_data_t	**block_header_slots[] = {
273 	&TAG_DATA(tnf_tag),		/* tag			*/
274 	&TAG_DATA(tnf_uint32),		/* generation		*/
275 	&TAG_DATA(tnf_uint16),		/* bytes_valid		*/
276 	&TAG_DATA(tnf_uint8),		/* A_lock 		*/
277 	&TAG_DATA(tnf_uint8),		/* B_lock		*/
278 	&TAG_DATA(tnf_opaque),		/* next_block 		*/
279 	0};
280 
281 TNF_STD_STRUCT_TAG(tnf_block_header,
282 		block_header_slots,
283 		block_header_slot_names,
284 		sizeof (tnf_block_header_t));
285 
286 /*
287  * Metatypes
288  */
289 
290 static tnf_tag_data_t	**type_properties[] = {
291 	&TAG_DATA(tnf_tagged),
292 	&TAG_DATA(tnf_struct),
293 	&TAG_DATA(tnf_type),
294 	0};
295 /* Exported */
296 tnf_tag_data_t	***tnf_type_properties = type_properties;
297 
298 static tnf_tag_data_t	**type_slots[] = {
299 	&TAG_DATA(tnf_tag),
300 	&TAG_DATA(tnf_name),
301 	&TAG_DATA(tnf_properties),
302 	0};
303 
304 TNF_METATAG(tnf_type, tnf_type_properties, type_slots, tnf_struct_tag_1);
305 
306 static tnf_tag_data_t	**array_type_slots[] = {
307 	&TAG_DATA(tnf_tag),
308 	&TAG_DATA(tnf_name),
309 	&TAG_DATA(tnf_properties),
310 	&TAG_DATA(tnf_slot_types),
311 	&TAG_DATA(tnf_header_size),
312 	&TAG_DATA(tnf_element_type),
313 	0};
314 
315 TNF_METATAG(tnf_array_type, tnf_type_properties,
316 		array_type_slots, tnf_struct_tag_1);
317 
318 static tnf_tag_data_t	**derived_type_slots[] = {
319 	&TAG_DATA(tnf_tag),
320 	&TAG_DATA(tnf_name),
321 	&TAG_DATA(tnf_properties),
322 	&TAG_DATA(tnf_derived_base),
323 	0};
324 
325 TNF_METATAG(tnf_derived_type, tnf_type_properties,
326 		derived_type_slots, tnf_struct_tag_1);
327 
328 static tnf_tag_data_t	**scalar_type_slots[] = {
329 	&TAG_DATA(tnf_tag),
330 	&TAG_DATA(tnf_name),
331 	&TAG_DATA(tnf_properties),
332 	&TAG_DATA(tnf_type_size),
333 	&TAG_DATA(tnf_align),
334 	0};
335 
336 TNF_METATAG(tnf_scalar_type, tnf_type_properties,
337 		scalar_type_slots, tnf_struct_tag_1);
338 
339 static tnf_tag_data_t	**struct_type_slots[] = {
340 	&TAG_DATA(tnf_tag),
341 	&TAG_DATA(tnf_name),
342 	&TAG_DATA(tnf_properties),
343 	&TAG_DATA(tnf_slot_types),
344 	&TAG_DATA(tnf_type_size),
345 	&TAG_DATA(tnf_slot_names),
346 	0};
347 
348 TNF_METATAG(tnf_struct_type, tnf_type_properties,
349 		struct_type_slots, tnf_root_tag_1);
350 
351 
352 /*
353  * Generic tnf reference - does checking on whether destination is
354  * a permanent block or not
355  */
356 
357 #ifdef _KERNEL
358 
359 /*ARGSUSED0*/
360 tnf_ref32_t
361 tnf_ref32_1(tnf_ops_t *ops, tnf_record_p item, tnf_record_p reference)
362 {
363 	tnf_ref32_t 		offset_delta, gen_delta;
364 	tnf_block_header_t	*dest_header_p, *src_header_p;
365 	tnf_ref32_t		result;
366 	unsigned int		offset_shift =
367 		/* LINTED pointer cast may result in improper alignment */
368 		((tnf_buf_file_header_t *)tnf_buf)->com.file_log_size;
369 
370 	dest_header_p = (tnf_block_header_t *)
371 		((uintptr_t)item & TNF_BLOCK_MASK);
372 
373 	if (((char *)dest_header_p < (tnf_buf + TNF_DIRECTORY_SIZE)) ||
374 	    (dest_header_p->generation == TNF_TAG_GENERATION_NUM)) {
375 		/* reference to a permanent block */
376 		/* LINTED ast from 64-bit integer to 32-bit integer */
377 		offset_delta = (tnf_ref32_t)(item - tnf_buf);
378 
379 		return (TNF_REF32_MAKE_PERMANENT(offset_delta));
380 	} else {
381 		/* reference to a reclaimable block */
382 		/* LINTED ast from 64-bit integer to 32-bit integer */
383 		offset_delta = (tnf_ref32_t)(item - reference);
384 
385 		src_header_p =  (tnf_block_header_t *)
386 			((uintptr_t)reference & TNF_BLOCK_MASK);
387 		gen_delta = dest_header_p->generation -
388 			src_header_p->generation;
389 
390 		result = (gen_delta << offset_shift) + offset_delta;
391 		return (TNF_REF32_MAKE_RECLAIMABLE(result));
392 	}
393 }
394 
395 #else
396 
397 /*ARGSUSED0*/
398 tnf_ref32_t
399 tnf_ref32_1(tnf_ops_t *ops, tnf_record_p item, tnf_record_p reference)
400 {
401 	volatile char 		*file_start = _tnfw_b_control->tnf_buffer;
402 	tnf_ref32_t 		offset_delta, gen_delta;
403 	tnf_block_header_t	*dest_header_p, *src_header_p;
404 	tnf_ref32_t		result;
405 	unsigned int		offset_shift =
406 		/* LINTED pointer cast may result in improper alignment */
407 		((tnf_buf_file_header_t *)file_start)->com.file_log_size;
408 
409 	dest_header_p = (tnf_block_header_t *)
410 		((uintptr_t)item & TNF_BLOCK_MASK);
411 
412 	if (((char *)dest_header_p < (file_start + TNFW_B_FW_ZONE)) ||
413 	    (dest_header_p->generation == TNF_TAG_GENERATION_NUM)) {
414 		/* reference to a permanent block */
415 		/* LINTED ast from 64-bit integer to 32-bit integer */
416 		offset_delta = (tnf_ref32_t)(item - (tnf_record_p) file_start);
417 
418 		return (TNF_REF32_MAKE_PERMANENT(offset_delta));
419 	} else {
420 		/* reference to a reclaimable block */
421 		/* LINTED ast from 64-bit integer to 32-bit integer */
422 		offset_delta = (tnf_ref32_t)(item - reference);
423 
424 		src_header_p =  (tnf_block_header_t *)
425 			((uintptr_t)reference & TNF_BLOCK_MASK);
426 		gen_delta = dest_header_p->generation -
427 			src_header_p->generation;
428 
429 		result = (gen_delta << offset_shift) + offset_delta;
430 		return (TNF_REF32_MAKE_RECLAIMABLE(result));
431 	}
432 }
433 
434 #endif
435 
436 /*
437  * Tag descriptors
438  */
439 
440 /*
441  * Write instances of tnf_type
442  */
443 
444 tnf_record_p
445 tnf_abstract_tag_1(tnf_ops_t *ops, tnf_tag_data_t *tag_data)
446 {
447 	tnf_tag_data_t		*metatag_data;
448 	tnf_record_p		metatag_index;
449 	tnf_type_prototype_t	*buffer;
450 	enum tnf_alloc_mode	saved_mode;
451 
452 	saved_mode = ops->mode;
453 	ops->mode = TNF_ALLOC_FIXED;
454 	/* LINTED assignment of 32-bit integer to 8-bit integer */
455 	ALLOC(ops, sizeof (*buffer), buffer, tag_data->tag_index,
456 		saved_mode);
457 
458 	metatag_data = TAG_DATA(tnf_type);
459 	metatag_index = metatag_data->tag_index ? metatag_data->tag_index :
460 		metatag_data->tag_desc(ops, metatag_data);
461 
462 	ASSIGN(buffer, tag,		metatag_index);
463 	ASSIGN(buffer, name, 		tag_data->tag_name);
464 	ASSIGN(buffer, properties,	tag_data->tag_props);
465 	/* LINTED assignment of 32-bit integer to 8-bit integer */
466 	ops->mode = saved_mode;
467 	return (tag_data->tag_index);
468 }
469 
470 /*
471  * Write instances of tnf_scalar_type
472  */
473 
474 tnf_record_p
475 tnf_scalar_tag_1(tnf_ops_t *ops, tnf_tag_data_t *tag_data)
476 {
477 	tnf_tag_data_t		*metatag_data;
478 	tnf_record_p		metatag_index;
479 	enum tnf_alloc_mode	saved_mode;
480 	tnf_scalar_type_prototype_t *buffer;
481 
482 	saved_mode = ops->mode;
483 	ops->mode = TNF_ALLOC_FIXED;
484 	/* LINTED assignment of 32-bit integer to 8-bit integer */
485 	ALLOC(ops, sizeof (*buffer), buffer, tag_data->tag_index,
486 	    saved_mode);
487 
488 	metatag_data = TAG_DATA(tnf_scalar_type);
489 	metatag_index = metatag_data->tag_index ? metatag_data->tag_index :
490 		metatag_data->tag_desc(ops, metatag_data);
491 
492 	ASSIGN(buffer, tag, 		metatag_index);
493 	ASSIGN(buffer, name, 		tag_data->tag_name);
494 	ASSIGN(buffer, properties, 	tag_data->tag_props);
495 	/* LINTED assignment of 32-bit integer to 8-bit integer */
496 	ASSIGN(buffer, type_size, 	tag_data->tag_size);
497 	/* LINTED assignment of 64-bit integer to 32-bit integer */
498 	ASSIGN(buffer, align, 		tag_data->tag_align);
499 
500 	/* LINTED assignment of 32-bit integer to 8-bit integer */
501 	ops->mode = saved_mode;
502 	return (tag_data->tag_index);
503 }
504 
505 /*
506  * Write instances of tnf_derived_type
507  */
508 
509 tnf_record_p
510 tnf_derived_tag_1(tnf_ops_t *ops, tnf_tag_data_t *tag_data)
511 {
512 	tnf_tag_data_t		*metatag_data;
513 	tnf_record_p		metatag_index;
514 	enum tnf_alloc_mode	saved_mode;
515 	tnf_derived_type_prototype_t *buffer;
516 
517 	saved_mode = ops->mode;
518 	ops->mode = TNF_ALLOC_FIXED;
519 	/* LINTED assignment of 32-bit integer to 8-bit integer */
520 	ALLOC(ops, sizeof (*buffer), buffer, tag_data->tag_index,
521 	    saved_mode);
522 
523 	metatag_data = TAG_DATA(tnf_derived_type);
524 	metatag_index = metatag_data->tag_index ? metatag_data->tag_index:
525 		metatag_data->tag_desc(ops, metatag_data);
526 
527 	ASSIGN(buffer, tag,		metatag_index);
528 	ASSIGN(buffer, name,		tag_data->tag_name);
529 	ASSIGN(buffer, properties, 	tag_data->tag_props);
530 	ASSIGN(buffer, derived_base,	tag_data->tag_base);
531 	/* LINTED assignment of 32-bit integer to 8-bit integer */
532 	ops->mode = saved_mode;
533 	return (tag_data->tag_index);
534 }
535 
536 /*
537  * Write instances of tnf_struct_type (except root)
538  */
539 
540 tnf_record_p
541 tnf_struct_tag_1(tnf_ops_t *ops, tnf_tag_data_t *tag_data)
542 {
543 	tnf_tag_data_t		*metatag_data;
544 	tnf_record_p		metatag_index;
545 	enum tnf_alloc_mode	saved_mode;
546 	tnf_struct_type_prototype_t *buffer;
547 
548 	saved_mode = ops->mode;
549 	ops->mode = TNF_ALLOC_FIXED;
550 	/* LINTED assignment of 32-bit integer to 8-bit integer */
551 	ALLOC(ops, sizeof (*buffer), buffer, tag_data->tag_index,
552 	    saved_mode);
553 
554 	metatag_data = TAG_DATA(tnf_struct_type);
555 	metatag_index = metatag_data->tag_index ? metatag_data->tag_index:
556 		metatag_data->tag_desc(ops, metatag_data);
557 
558 	ASSIGN(buffer, tag,		metatag_index);
559 	ASSIGN(buffer, name,		tag_data->tag_name);
560 	ASSIGN(buffer, properties, 	tag_data->tag_props);
561 	ASSIGN(buffer, slot_types, 	tag_data->tag_slots);
562 	/* LINTED assignment of 64-bit integer to 32-bit integer */
563 	ASSIGN(buffer, type_size, 	tag_data->tag_size);
564 	ASSIGN(buffer, slot_names, 	tag_data->tag_slot_names);
565 	/* LINTED assignment of 32-bit integer to 8-bit integer */
566 	ops->mode = saved_mode;
567 	return (tag_data->tag_index);
568 }
569 
570 /*
571  * Write instances of tnf_array_type
572  */
573 
574 tnf_record_p
575 tnf_array_tag_1(tnf_ops_t *ops, tnf_tag_data_t	*tag_data)
576 {
577 	tnf_tag_data_t 		*metatag_data;
578 	tnf_record_p 		metatag_index;
579 	enum tnf_alloc_mode	saved_mode;
580 	tnf_array_type_prototype_t 	*buffer;
581 
582 	saved_mode = ops->mode;
583 	ops->mode = TNF_ALLOC_FIXED;
584 	/* LINTED assignment of 32-bit integer to 8-bit integer */
585 	ALLOC(ops, sizeof (*buffer), buffer, tag_data->tag_index,
586 	    saved_mode);
587 
588 	metatag_data = TAG_DATA(tnf_array_type);
589 	metatag_index = metatag_data->tag_index ? metatag_data->tag_index :
590 		metatag_data->tag_desc(ops, metatag_data);
591 
592 	ASSIGN(buffer, tag, 		metatag_index);
593 	ASSIGN(buffer, name, 		tag_data->tag_name);
594 	ASSIGN(buffer, properties, 	tag_data->tag_props);
595 	ASSIGN(buffer, slot_types, 	tag_data->tag_slots);
596 	/* LINTED assignment of 64-bit integer to 32-bit integer */
597 	ASSIGN(buffer, header_size, 	tag_data->tag_size);
598 	ASSIGN(buffer, element_type, 	tag_data->tag_base);
599 	/* LINTED assignment of 32-bit integer to 8-bit integer */
600 	ops->mode = saved_mode;
601 	return (tag_data->tag_index);
602 }
603 
604 /*
605  * Write the root metatype, and some critical bootstrap types
606  */
607 
608 static tnf_record_p
609 tnf_root_tag_1(tnf_ops_t *ops, tnf_tag_data_t *tag_data)
610 {
611 	enum tnf_alloc_mode	saved_mode;
612 	tnf_tag_t		*fw_p;
613 	tnf_struct_type_prototype_t *buffer;
614 
615 	saved_mode = ops->mode;
616 	ops->mode = TNF_ALLOC_FIXED;
617 	/* LINTED assignment of 32-bit integer to 8-bit integer */
618 	ALLOC(ops, sizeof (*buffer), buffer, tag_data->tag_index,
619 	    saved_mode);
620 
621 	/*
622 	 * update the root forwarding pointer to point to this root
623 	 * CAUTION: Do this before anything else...
624 	 */
625 
626 #ifdef _KERNEL
627 	/* LINTED pointer cast may result in improper alignment */
628 	fw_p = (tnf_tag_t *)(tnf_buf + TNF_DIRENT_ROOT);
629 	*fw_p = tnf_ref32(ops, tag_data->tag_index, (tnf_record_p)fw_p);
630 	tag_data->tag_index = (tnf_record_p)fw_p;
631 #else
632 	/* LINTED pointer cast may result in improper alignment */
633 	fw_p = (tnf_tag_t *)_tnf_buf_headers_p->fw_root;
634 	if (fw_p) {
635 		*fw_p = tnf_ref32(ops, tag_data->tag_index,
636 		    (tnf_record_p) fw_p);
637 		tag_data->tag_index = (tnf_record_p)fw_p;
638 	}
639 #endif
640 
641 #ifdef _KERNEL
642 	/* LINTED constant truncated by assignment */
643 	buffer->tag = TNF_ROOT_TAG;
644 #else
645 	ASSIGN(buffer, tag,		tag_data->tag_index); /* ROOT */
646 #endif
647 	ASSIGN(buffer, name,		tag_data->tag_name);
648 	ASSIGN(buffer, properties, 	tag_data->tag_props);
649 	ASSIGN(buffer, slot_types, 	tag_data->tag_slots);
650 	/* LINTED assignment of 64-bit integer to 32-bit integer */
651 	ASSIGN(buffer, type_size, 	tag_data->tag_size);
652 	ASSIGN(buffer, slot_names, 	tag_data->tag_slot_names);
653 
654 	/*
655 	 * Write some additional bootstrap types
656 	 */
657 	{
658 		static tnf_tag_data_t *bootstrap_types[] = {
659 			&_TAG_DATA(tnf_uint16),
660 			&_TAG_DATA(tnf_int32),
661 			&_TAG_DATA(tnf_tag),
662 			&_TAG_DATA(tnf_file_header),
663 			&_TAG_DATA(tnf_block_header),
664 			0};
665 		tnf_tag_data_t **list_p, *tag_p;
666 
667 		list_p = bootstrap_types;
668 
669 		while (tag_p = *list_p++) {
670 			if (!tag_p->tag_index) /* not written */
671 				tag_p->tag_desc(ops, tag_p);
672 		}
673 	}
674 
675 
676 	/*
677 	 * fix for circularity in filling in file header tag and block
678 	 * header tag.  REMIND: should also fix tag_index of
679 	 * file_header.
680 	 */
681 
682 #ifdef _KERNEL
683 
684 	/* LINTED pointer cast may result in improper alignment */
685 	fw_p = (tnf_tag_t *)(tnf_buf + TNF_DIRENT_FILE_HEADER);
686 	*fw_p = tnf_ref32(ops, _TAG_DATA(tnf_file_header).tag_index,
687 	    (tnf_record_p)fw_p);
688 
689 	/* LINTED pointer cast may result in improper alignment */
690 	fw_p = (tnf_tag_t *)(tnf_buf + TNF_DIRENT_BLOCK_HEADER);
691 	*fw_p = tnf_ref32(ops, _TAG_DATA(tnf_block_header).tag_index,
692 	    (tnf_record_p)fw_p);
693 
694 #else
695 
696 	/* LINTED pointer cast may result in improper alignment */
697 	fw_p = (tnf_tag_t *)_tnf_buf_headers_p->fw_file_header;
698 	if (fw_p) {
699 		*fw_p = tnf_ref32(ops, _TAG_DATA(tnf_file_header).tag_index,
700 		    (tnf_record_p)fw_p);
701 	}
702 	/* LINTED pointer cast may result in improper alignment */
703 	fw_p = (tnf_tag_t *)_tnf_buf_headers_p->fw_block_header;
704 	if (fw_p) {
705 		*fw_p = tnf_ref32(ops, _TAG_DATA(tnf_block_header).tag_index,
706 		    (tnf_record_p) fw_p);
707 	}
708 
709 #endif
710 
711 	/* LINTED assignment of 32-bit integer to 8-bit integer */
712 	ops->mode = saved_mode;
713 	return (tag_data->tag_index);
714 }
715 
716 
717 /*
718  * Data encoders
719  */
720 
721 /*
722  * Strings and derivatives
723  */
724 
725 tnf_reference_t
726 tnf_string_1(tnf_ops_t *ops, const char *string, tnf_record_p reference,
727 		tnf_tag_data_t	*tag_data)
728 {
729 	tnf_record_p 	tag_index;
730 	size_t		string_size, record_size;
731 	tnf_array_header_t *bufhdr;
732 
733 	tag_index = tag_data->tag_index ? tag_data->tag_index :
734 		tag_data->tag_desc(ops, tag_data);
735 
736 	if (!string)
737 		return ((tnf_reference_t)TNF_NULL);
738 
739 	string_size = strlen(string); /* excludes terminating NUL */
740 	if (string_size > TNF_STRING_LIMIT)
741 		string_size = TNF_STRING_LIMIT;
742 	/* Allocate space for terminating NUL as well */
743 	record_size = sizeof (*bufhdr) + TNF_STRING_ROUNDUP(string_size + 1);
744 
745 	ALLOC2(ops, record_size, bufhdr, ops->mode);
746 
747 	ASSIGN(bufhdr, tag, 		tag_index);
748 	/* LINTED assignment of 64-bit integer to 32-bit integer */
749 	ASSIGN(bufhdr, self_size, 	record_size);
750 
751 #ifdef _KERNEL
752 	(void) bcopy((caddr_t)string, (char *)bufhdr + sizeof (*bufhdr),
753 	    string_size);
754 #else
755 	(void) memcpy((char *)bufhdr + sizeof (*bufhdr), string, string_size);
756 #endif
757 	/* NUL-terminate */
758 	((char *)bufhdr + sizeof (*bufhdr))[string_size] = '\0';
759 
760 	return (tnf_ref32(ops, (tnf_record_p)bufhdr, reference));
761 }
762 
763 /*
764  * Array of strings and derivatives
765  */
766 
767 tnf_reference_t
768 tnf_string_array_1(tnf_ops_t *ops, char	**strings, tnf_record_p reference,
769 			tnf_tag_data_t	*tag_data)
770 {
771 	tnf_record_p 	tag_index;
772 	size_t		record_size;
773 	char		**tmp;
774 	tnf_reference_t	*ref_p;
775 	tnf_array_header_t 	*bufhdr;
776 
777 	tag_index = tag_data->tag_index ? tag_data->tag_index :
778 		tag_data->tag_desc(ops, tag_data);
779 
780 	if (!strings)
781 		return ((tnf_reference_t)TNF_NULL);
782 
783 	record_size = sizeof (*bufhdr);
784 	tmp = strings;
785 	while (*tmp++)
786 		record_size += sizeof (tnf_string_t);
787 
788 	ALLOC2(ops, record_size, bufhdr, ops->mode);
789 
790 	ASSIGN(bufhdr, tag, 		tag_index);
791 	/* LINTED assignment of 64-bit integer to 32-bit integer */
792 	ASSIGN(bufhdr, self_size, 	record_size);
793 
794 	tmp = strings;
795 	/* LINTED pointer cast may result in improper alignment */
796 	ref_p = (tnf_reference_t *)((char *)bufhdr + sizeof (*bufhdr));
797 	while (*tmp) {
798 		*ref_p = tnf_string(ops, *tmp, (tnf_record_p)ref_p);
799 		tmp++;
800 		ref_p++;
801 	}
802 
803 	return (tnf_ref32(ops, (tnf_record_p) bufhdr, reference));
804 }
805 
806 /*
807  * Type record as generic (not tag) reference
808  */
809 
810 tnf_reference_t
811 tnf_tag_element_1(tnf_ops_t *ops, tnf_tag_data_t **tag_data_p,
812 		tnf_record_p reference, tnf_tag_data_t *aux_tag_data)
813 {
814 	tnf_tag_data_t	*tag_data;
815 
816 	if (aux_tag_data)
817 		if (!aux_tag_data->tag_index)
818 			aux_tag_data->tag_desc(ops, aux_tag_data);
819 
820 	/* tnf_derived has derived_base == TNF_NULL */
821 	if (!tag_data_p)
822 		return ((tnf_reference_t)TNF_NULL);
823 
824 	tag_data = *tag_data_p;
825 	if (!tag_data->tag_index)
826 		tag_data->tag_desc(ops, tag_data);
827 
828 	return (tnf_ref32(ops, tag_data->tag_index, reference));
829 }
830 
831 
832 /*
833  * Array of type records as generic (not tag) references
834  */
835 
836 tnf_reference_t
837 tnf_tag_array_1(tnf_ops_t		*ops,
838 		tnf_tag_data_t		***tag_data_array,
839 		tnf_record_p		reference,
840 		tnf_tag_data_t		*tag_data)
841 {
842 	tnf_record_p 	tag_index;
843 	size_t		record_size;
844 	tnf_array_header_t 	*bufhdr;
845 	tnf_tag_data_t	***tmp;
846 	tnf_reference_t	*ref_p;
847 
848 	tag_index = tag_data->tag_index ? tag_data->tag_index :
849 		tag_data->tag_desc(ops, tag_data);
850 
851 	if (!tag_data_array)
852 		return ((tnf_reference_t)TNF_NULL);
853 
854 	record_size = sizeof (*bufhdr);
855 	tmp = tag_data_array;
856 	while (*tmp++)
857 		record_size += sizeof (tnf_reference_t);
858 
859 	ALLOC2(ops, record_size, bufhdr, ops->mode);
860 
861 	ASSIGN(bufhdr, tag, 		tag_index);
862 	/* LINTED assignment of 64-bit integer to 32-bit integer */
863 	ASSIGN(bufhdr, self_size, 	record_size);
864 
865 	tmp = tag_data_array;
866 	/* LINTED pointer cast may result in improper alignment */
867 	ref_p = (tnf_reference_t *)((char *)bufhdr + sizeof (*bufhdr));
868 	while (*tmp) {
869 		*ref_p = tnf_tag_element_1(ops, *tmp, (tnf_record_p)ref_p,
870 		    TNF_NULL);
871 		tmp++;
872 		ref_p++;
873 	}
874 
875 	return (tnf_ref32(ops, (tnf_record_p)bufhdr, reference));
876 }
877 
878 /*
879  * Array of properties (type records)
880  */
881 
882 tnf_reference_t
883 tnf_tag_properties_1(tnf_ops_t		*ops,
884 		tnf_tag_data_t		****tag_data_array,
885 		tnf_record_p		reference,
886 		tnf_tag_data_t		*tag_data)
887 {
888 	if (!(tag_data->tag_index))
889 		tag_data->tag_desc(ops, tag_data);
890 
891 	if (!tag_data_array)
892 		return ((tnf_reference_t)TNF_NULL);
893 
894 	return (tnf_tag_array_1(ops, *tag_data_array, reference, tag_data));
895 }
896 
897 #ifdef _KERNEL
898 /*
899  * Initialize all core tag pointers defined in this file.
900  * CAUTION: tnf_tag_core_init is a function for kernel compilation.
901  */
902 
903 void
904 tnf_tag_core_init(void)
905 {
906 #endif
907 	TAG_SET(tnf_inline);
908 	TAG_SET(tnf_tagged);
909 
910 	TAG_SET(tnf_scalar);
911 	TAG_SET(tnf_char);
912 	TAG_SET(tnf_int8);
913 	TAG_SET(tnf_uint8);
914 	TAG_SET(tnf_int16);
915 	TAG_SET(tnf_uint16);
916 	TAG_SET(tnf_int32);
917 	TAG_SET(tnf_uint32);
918 	TAG_SET(tnf_int64);
919 	TAG_SET(tnf_uint64);
920 
921 	TAG_SET(tnf_float32);
922 	TAG_SET(tnf_float64);
923 
924 	TAG_SET(tnf_array);
925 	TAG_SET(tnf_string);
926 	TAG_SET(tnf_type_array);
927 	TAG_SET(tnf_name_array);
928 
929 	TAG_SET(tnf_derived);
930 	TAG_SET(tnf_align);
931 	TAG_SET(tnf_derived_base);
932 	TAG_SET(tnf_element_type);
933 	TAG_SET(tnf_header_size);
934 	TAG_SET(tnf_name);
935 	TAG_SET(tnf_opaque);
936 	TAG_SET(tnf_properties);
937 	TAG_SET(tnf_self_size);
938 	TAG_SET(tnf_size);
939 	TAG_SET(tnf_slot_names);
940 	TAG_SET(tnf_slot_types);
941 	TAG_SET(tnf_tag);
942 	TAG_SET(tnf_tag_arg);
943 	TAG_SET(tnf_type_size);
944 
945 	TAG_SET(tnf_struct);
946 	TAG_SET(tnf_file_header);
947 	TAG_SET(tnf_block_header);
948 
949 	TAG_SET(tnf_type);
950 	TAG_SET(tnf_array_type);
951 	TAG_SET(tnf_derived_type);
952 	TAG_SET(tnf_scalar_type);
953 	TAG_SET(tnf_struct_type);
954 
955 #ifdef _KERNEL
956 
957 	/* Snap exported properties */
958 	tnf_user_struct_properties = std_struct_properties;
959 
960 }
961 
962 #else	/* _KERNEL */
963 
964 tnf_tag_data_t ***tnf_user_struct_properties = std_struct_properties;
965 
966 #endif	/* _KERNEL */
967