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
64static tnf_record_p tnf_root_tag_1(tnf_ops_t *, tnf_tag_data_t *);
65
66/*
67 * TNF tag version 1
68 */
69
70tnf_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
79TNF_ABSTRACT_TAG(tnf_inline);
80TNF_ABSTRACT_TAG(tnf_tagged);
81
82/*
83 * Scalar types
84 */
85
86static tnf_tag_data_t	**std_scalar_properties[] = {
87	&TAG_DATA(tnf_inline),
88	&TAG_DATA(tnf_scalar),
89	0};
90
91tnf_tag_data_t	***tnf_scalar_properties = std_scalar_properties;
92
93TNF_SCALAR_TAG(tnf_scalar, 0, 0, TNF_UNKNOWN);
94
95TNF_STD_SCALAR_TAG(tnf_char, TNF_UNKNOWN); /* XXX */
96TNF_STD_SCALAR_TAG(tnf_int8, TNF_INT32);
97TNF_STD_SCALAR_TAG(tnf_uint8, TNF_UINT32);
98TNF_STD_SCALAR_TAG(tnf_int16, TNF_INT32);
99TNF_STD_SCALAR_TAG(tnf_uint16, TNF_UINT32);
100TNF_STD_SCALAR_TAG(tnf_int32, TNF_INT32);
101TNF_STD_SCALAR_TAG(tnf_uint32, TNF_UINT32);
102TNF_STD_SCALAR_TAG(tnf_int64, TNF_INT64);
103TNF_STD_SCALAR_TAG(tnf_uint64, TNF_UINT64);
104
105TNF_STD_SCALAR_TAG(tnf_float32, TNF_FLOAT32);
106TNF_STD_SCALAR_TAG(tnf_float64, TNF_FLOAT64);
107
108/*
109 * Array types
110 */
111
112static tnf_tag_data_t	**array_properties[] = {
113	&TAG_DATA(tnf_array),
114	0
115};
116static tnf_tag_data_t	***abstract_array_properties = array_properties;
117
118static tnf_tag_data_t	**std_array_properties[] = {
119	&TAG_DATA(tnf_array),
120	&TAG_DATA(tnf_tagged),
121	0
122};
123/* Exported */
124tnf_tag_data_t	***tnf_array_properties = std_array_properties;
125
126/* Exported */
127tnf_tag_data_t	**tnf_array_slots[] = {
128	&TAG_DATA(tnf_tag),
129	&TAG_DATA(tnf_self_size),
130	0
131};
132
133TNF_ARRAY_TAG(tnf_array, TNF_NULL, abstract_array_properties,
134			TNF_NULL, TNF_UNKNOWN);
135
136TNF_STD_ARRAY_TAG(tnf_string, tnf_char, TNF_STRING);
137TNF_STD_ARRAY_TAG(tnf_type_array, tnf_type, TNF_ARRAY);
138TNF_STD_ARRAY_TAG(tnf_name_array, tnf_name, TNF_ARRAY);
139
140/*
141 * Derived types
142 */
143
144static tnf_tag_data_t	**derived_properties[] = {
145	&TAG_DATA(tnf_derived),
146	0
147};
148/* Exported */
149tnf_tag_data_t	***tnf_derived_properties = derived_properties;
150
151TNF_DERIVED_TAG(tnf_derived, TNF_NULL,
152		tnf_derived_properties, TNF_NULL, TNF_NULL, TNF_UNKNOWN);
153
154TNF_STD_DERIVED_TAG(tnf_align, tnf_uint32,
155		tnf_derived_properties, TNF_UINT32);
156
157TNF_STD_DERIVED_TAG(tnf_derived_base, tnf_type,
158		tnf_derived_properties, TNF_OPAQUE);
159
160TNF_STD_DERIVED_TAG(tnf_element_type, tnf_type,
161		tnf_derived_properties, TNF_OPAQUE);
162
163TNF_STD_DERIVED_TAG(tnf_header_size, tnf_uint32,
164		tnf_derived_properties, TNF_UINT32);
165
166TNF_STD_DERIVED_TAG(tnf_name, tnf_string,
167		tnf_derived_properties, TNF_STRING);
168
169#if defined(_LP64)
170
171TNF_STD_DERIVED_TAG(tnf_opaque, tnf_uint64,
172		tnf_derived_properties, TNF_OPAQUE);
173
174#else
175
176TNF_STD_DERIVED_TAG(tnf_opaque, tnf_uint32,
177		tnf_derived_properties, TNF_OPAQUE);
178
179#endif /* defined(_LP64) */
180
181TNF_STD_DERIVED_TAG(tnf_properties, tnf_type_array,
182		tnf_derived_properties, TNF_ARRAY);
183
184TNF_STD_DERIVED_TAG(tnf_self_size, tnf_uint32,
185		tnf_derived_properties, TNF_UINT32);
186
187TNF_STD_DERIVED_TAG(tnf_size, tnf_ulong,
188		tnf_derived_properties, TNF_ULONG);
189
190TNF_STD_DERIVED_TAG(tnf_slot_names, tnf_name_array,
191		tnf_derived_properties, TNF_ARRAY);
192
193TNF_STD_DERIVED_TAG(tnf_slot_types, tnf_type_array,
194		tnf_derived_properties, TNF_ARRAY);
195
196TNF_STD_DERIVED_TAG(tnf_tag, tnf_type,
197		tnf_derived_properties, TNF_OPAQUE);
198
199TNF_STD_DERIVED_TAG(tnf_tag_arg, tnf_tagged,
200		tnf_derived_properties, TNF_OPAQUE);
201
202TNF_STD_DERIVED_TAG(tnf_type_size, tnf_uint32,
203		tnf_derived_properties, TNF_UINT32);
204
205/*
206 * Struct types
207 */
208
209static tnf_tag_data_t	**no_properties[] = { 0 };
210tnf_tag_data_t	***tnf_no_properties = no_properties;
211
212static tnf_tag_data_t	**no_slots[] = { 0 };
213
214static tnf_tag_data_t	**std_struct_properties[] = {
215	&TAG_DATA(tnf_tagged),
216	&TAG_DATA(tnf_struct),
217	0};
218/* Exported */
219tnf_tag_data_t	***tnf_struct_properties = std_struct_properties;
220
221TNF_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
227static 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
240static 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 */
254TNF_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
263static 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
272static 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
281TNF_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
290static 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 */
296tnf_tag_data_t	***tnf_type_properties = type_properties;
297
298static tnf_tag_data_t	**type_slots[] = {
299	&TAG_DATA(tnf_tag),
300	&TAG_DATA(tnf_name),
301	&TAG_DATA(tnf_properties),
302	0};
303
304TNF_METATAG(tnf_type, tnf_type_properties, type_slots, tnf_struct_tag_1);
305
306static 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
315TNF_METATAG(tnf_array_type, tnf_type_properties,
316		array_type_slots, tnf_struct_tag_1);
317
318static 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
325TNF_METATAG(tnf_derived_type, tnf_type_properties,
326		derived_type_slots, tnf_struct_tag_1);
327
328static 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
336TNF_METATAG(tnf_scalar_type, tnf_type_properties,
337		scalar_type_slots, tnf_struct_tag_1);
338
339static 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
348TNF_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*/
360tnf_ref32_t
361tnf_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*/
398tnf_ref32_t
399tnf_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
444tnf_record_p
445tnf_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
474tnf_record_p
475tnf_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
509tnf_record_p
510tnf_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
540tnf_record_p
541tnf_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
574tnf_record_p
575tnf_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
608static tnf_record_p
609tnf_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
725tnf_reference_t
726tnf_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
767tnf_reference_t
768tnf_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
810tnf_reference_t
811tnf_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
836tnf_reference_t
837tnf_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
882tnf_reference_t
883tnf_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
903void
904tnf_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
964tnf_tag_data_t ***tnf_user_struct_properties = std_struct_properties;
965
966#endif	/* _KERNEL */
967