xref: /onnv-gate/usr/src/lib/libtnf/ref.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  *	Copyright (c) 1994, by Sun Microsytems, Inc.
24*0Sstevel@tonic-gate  */
25*0Sstevel@tonic-gate 
26*0Sstevel@tonic-gate #pragma	ident	"%Z%%M%	%I%	%E% SMI"
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate #include "libtnf.h"
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate /*
31*0Sstevel@tonic-gate  * Unoptimized versions, always dereference a cell through _GET_INT32()
32*0Sstevel@tonic-gate  *
33*0Sstevel@tonic-gate  */
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #define	LONG_SIGN_BIT	0x80000000
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate static tnf_ref32_t *vaddr_to_phys(TNF *, tnf_ref32_t *, tnf_ref32_t);
38*0Sstevel@tonic-gate 
39*0Sstevel@tonic-gate /*
40*0Sstevel@tonic-gate  * Return target cell referred to via src_val from src_cell, after
41*0Sstevel@tonic-gate  * checking that target is valid (block was not reused).  Return NULL
42*0Sstevel@tonic-gate  * otherwise.
43*0Sstevel@tonic-gate  *
44*0Sstevel@tonic-gate  * NOTE: We must check if the destination is within the valid_bytes
45*0Sstevel@tonic-gate  * range of its block, so as to correctly handle tnfxtract'ed files:
46*0Sstevel@tonic-gate  * the block containing the target cell may have been copied out
47*0Sstevel@tonic-gate  * before the block containing the source cell.
48*0Sstevel@tonic-gate  */
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate static tnf_ref32_t *
vaddr_to_phys(TNF * tnf,tnf_ref32_t * src_cell,tnf_ref32_t src_val)51*0Sstevel@tonic-gate vaddr_to_phys(TNF *tnf, tnf_ref32_t *src_cell, tnf_ref32_t src_val)
52*0Sstevel@tonic-gate {
53*0Sstevel@tonic-gate 	char		*base;
54*0Sstevel@tonic-gate 	unsigned	shft, mask;
55*0Sstevel@tonic-gate 	tnf_uint32_t	src_gen, dst_gen, exp_gen;
56*0Sstevel@tonic-gate 	tnf_int32_t	gen_delta;
57*0Sstevel@tonic-gate 	tnf_ref32_t	src_off, exp_off, dst_off, *dst_blk, *dst_cell;
58*0Sstevel@tonic-gate 	tnf_uint32_t	bytes_valid;
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate 	base = tnf->file_start;
61*0Sstevel@tonic-gate 	shft = tnf->generation_shift;
62*0Sstevel@tonic-gate 	mask = tnf->address_mask;
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate 	/* Generation of source cell */
65*0Sstevel@tonic-gate 	/* LINTED pointer cast */
66*0Sstevel@tonic-gate 	src_gen = _GET_BLOCK_GENERATION(tnf, _GET_BLOCK(tnf, src_cell));
67*0Sstevel@tonic-gate 	/* Physical file offset of source cell */
68*0Sstevel@tonic-gate 	src_off = (tnf_ref32_t)((char *)src_cell - base);
69*0Sstevel@tonic-gate 	/* Expected (unadjusted) file offset of destination cell */
70*0Sstevel@tonic-gate 	exp_off = src_off + src_val;
71*0Sstevel@tonic-gate 	/* Generation delta */
72*0Sstevel@tonic-gate 	gen_delta = (tnf_int32_t)((unsigned)exp_off >> shft);
73*0Sstevel@tonic-gate 	if ((exp_off & LONG_SIGN_BIT) == LONG_SIGN_BIT) {
74*0Sstevel@tonic-gate 		/* sign bit was a 1 - so restore sign */
75*0Sstevel@tonic-gate 		gen_delta |= ((unsigned)mask << (32 - shft));
76*0Sstevel@tonic-gate 	}
77*0Sstevel@tonic-gate 	/* Expected destination generation */
78*0Sstevel@tonic-gate 	exp_gen = src_gen + gen_delta;
79*0Sstevel@tonic-gate 	/* Physical file offset of destination cell */
80*0Sstevel@tonic-gate 	dst_off = (tnf_ref32_t)((unsigned)exp_off & mask);
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 	/* Destination cell */
83*0Sstevel@tonic-gate 	/* LINTED pointer cast */
84*0Sstevel@tonic-gate 	dst_cell = (tnf_ref32_t *)(base + dst_off);
85*0Sstevel@tonic-gate 	/* Destination block */
86*0Sstevel@tonic-gate 	/* LINTED pointer cast */
87*0Sstevel@tonic-gate 	dst_blk = _GET_BLOCK(tnf, dst_cell);
88*0Sstevel@tonic-gate 	/* Generation of destination cell */
89*0Sstevel@tonic-gate 	/* LINTED pointer cast */
90*0Sstevel@tonic-gate 	dst_gen = _GET_BLOCK_GENERATION(tnf, dst_blk);
91*0Sstevel@tonic-gate 	/* Bytes valid in destination block */
92*0Sstevel@tonic-gate 	/* LINTED pointer cast */
93*0Sstevel@tonic-gate 	bytes_valid = _GET_BLOCK_BYTES_VALID(tnf, dst_blk);
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate 	if ((src_gen == (tnf_uint32_t)TNF_TAG_GENERATION_NUM) ||
96*0Sstevel@tonic-gate 	    (dst_gen == (tnf_uint32_t)TNF_TAG_GENERATION_NUM) ||
97*0Sstevel@tonic-gate 	    ((dst_gen == exp_gen) &&
98*0Sstevel@tonic-gate 		((char *)dst_cell - (char *)dst_blk) < bytes_valid))
99*0Sstevel@tonic-gate 		return (dst_cell);
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 	return ((tnf_ref32_t *)NULL);
102*0Sstevel@tonic-gate }
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate /*
105*0Sstevel@tonic-gate  * Return the target referent of a cell, chasing forwarding references.
106*0Sstevel@tonic-gate  * Return TNF_NULL if cell is a TNF_NULL forwarding reference.
107*0Sstevel@tonic-gate  */
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate tnf_ref32_t *
_tnf_get_ref32(TNF * tnf,tnf_ref32_t * cell)110*0Sstevel@tonic-gate _tnf_get_ref32(TNF *tnf, tnf_ref32_t *cell)
111*0Sstevel@tonic-gate {
112*0Sstevel@tonic-gate 	tnf_ref32_t 	ref32, reftemp;
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 	ref32 = _GET_INT32(tnf, cell);
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 	if (TNF_REF32_IS_NULL(ref32))
117*0Sstevel@tonic-gate 		return (TNF_NULL);
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	if (TNF_REF32_IS_RSVD(ref32)) {
120*0Sstevel@tonic-gate 		_tnf_error(tnf, TNF_ERR_BADREFTYPE);
121*0Sstevel@tonic-gate 		return (TNF_NULL);
122*0Sstevel@tonic-gate 	}
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	if (TNF_REF32_IS_PAIR(ref32)) {
125*0Sstevel@tonic-gate 		/* We chase the high (tag) half */
126*0Sstevel@tonic-gate 		tnf_ref16_t	tag16;
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 		tag16 = TNF_REF32_TAG16(ref32);
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 		if (TNF_TAG16_IS_ABS(tag16)) {
131*0Sstevel@tonic-gate 			cell = (tnf_ref32_t *)
132*0Sstevel@tonic-gate 				((char *)tnf->file_start
133*0Sstevel@tonic-gate /* LINTED pointer cast may result in improper alignment */
134*0Sstevel@tonic-gate 				+ TNF_TAG16_ABS16(tag16));
135*0Sstevel@tonic-gate 			ref32 = _GET_INT32(tnf, cell);
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 		} else if (TNF_TAG16_IS_REL(tag16)) {
138*0Sstevel@tonic-gate 			cell = vaddr_to_phys(tnf, cell,
139*0Sstevel@tonic-gate 					(tnf_ref32_t) TNF_TAG16_REF16(tag16));
140*0Sstevel@tonic-gate 			if (cell == TNF_NULL)
141*0Sstevel@tonic-gate 				return (TNF_NULL);
142*0Sstevel@tonic-gate 			ref32 = _GET_INT32(tnf, cell);
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate 		} else {
145*0Sstevel@tonic-gate 			_tnf_error(tnf, TNF_ERR_BADREFTYPE);
146*0Sstevel@tonic-gate 			return (TNF_NULL);
147*0Sstevel@tonic-gate 		}
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate 	} else if (TNF_REF32_IS_PERMANENT(ref32)) {
150*0Sstevel@tonic-gate 		/* permanent space pointer */
151*0Sstevel@tonic-gate 		reftemp = TNF_REF32_VALUE(ref32);
152*0Sstevel@tonic-gate 		reftemp = TNF_REF32_SIGN_EXTEND(reftemp);
153*0Sstevel@tonic-gate 		/* LINTED pointer cast may result in improper alignment */
154*0Sstevel@tonic-gate 		cell = (tnf_ref32_t *) ((char *)tnf->file_start + reftemp);
155*0Sstevel@tonic-gate 		ref32 = _GET_INT32(tnf, cell);
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate 	} else {		/* full/tag reclaimable space reference */
158*0Sstevel@tonic-gate 		cell = vaddr_to_phys(tnf, cell, TNF_REF32_VALUE(ref32));
159*0Sstevel@tonic-gate 		if (cell == TNF_NULL)
160*0Sstevel@tonic-gate 			return (TNF_NULL);
161*0Sstevel@tonic-gate 		ref32 = _GET_INT32(tnf, cell);
162*0Sstevel@tonic-gate 	}
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	/* chase intermediate forwarding references */
165*0Sstevel@tonic-gate 	while (ref32 && TNF_REF32_IS_FWD(ref32)) {
166*0Sstevel@tonic-gate 		if (TNF_REF32_IS_PERMANENT(ref32)) {
167*0Sstevel@tonic-gate 			reftemp = TNF_REF32_VALUE(ref32);
168*0Sstevel@tonic-gate 			reftemp = TNF_REF32_SIGN_EXTEND(reftemp);
169*0Sstevel@tonic-gate 			cell = (tnf_ref32_t *) ((char *)tnf->file_start +
170*0Sstevel@tonic-gate 		/* LINTED pointer cast may result in improper alignment */
171*0Sstevel@tonic-gate 							reftemp);
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate 		} else {
174*0Sstevel@tonic-gate 			cell = vaddr_to_phys(tnf, cell, TNF_REF32_VALUE(ref32));
175*0Sstevel@tonic-gate 			if (cell == TNF_NULL)
176*0Sstevel@tonic-gate 				return (TNF_NULL);
177*0Sstevel@tonic-gate 		}
178*0Sstevel@tonic-gate 		ref32 = _GET_INT32(tnf, cell);
179*0Sstevel@tonic-gate 	}
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate 	return (cell);
182*0Sstevel@tonic-gate }
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate /*
185*0Sstevel@tonic-gate  * Return the target referent of ref16 contained in cell.
186*0Sstevel@tonic-gate  * Return TNF_NULL if cell doesn't have a ref16.
187*0Sstevel@tonic-gate  */
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate tnf_ref32_t *
_tnf_get_ref16(TNF * tnf,tnf_ref32_t * cell)190*0Sstevel@tonic-gate _tnf_get_ref16(TNF *tnf, tnf_ref32_t *cell)
191*0Sstevel@tonic-gate {
192*0Sstevel@tonic-gate 	tnf_ref32_t 	ref32, reftemp;
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 	ref32 = _GET_INT32(tnf, cell);
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate 	if (TNF_REF32_IS_PAIR(ref32)) {
197*0Sstevel@tonic-gate 		tnf_ref16_t	ref16;
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 		ref16 = TNF_REF32_REF16(ref32);
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 		if (TNF_REF16_VALUE(ref16) == TNF_NULL)
202*0Sstevel@tonic-gate 			/* No ref16 was stored */
203*0Sstevel@tonic-gate 			return (TNF_NULL);
204*0Sstevel@tonic-gate 		else {
205*0Sstevel@tonic-gate 			cell = vaddr_to_phys(tnf, cell,
206*0Sstevel@tonic-gate 					(tnf_ref32_t) TNF_REF16_VALUE(ref16));
207*0Sstevel@tonic-gate 			if (cell == TNF_NULL)
208*0Sstevel@tonic-gate 				return (TNF_NULL);
209*0Sstevel@tonic-gate 			ref32 = _GET_INT32(tnf, cell);
210*0Sstevel@tonic-gate 		}
211*0Sstevel@tonic-gate 	} else			/* not a pair pointer */
212*0Sstevel@tonic-gate 		return (TNF_NULL);
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate 	/* chase intermediate forwarding references */
215*0Sstevel@tonic-gate 	while (ref32 && TNF_REF32_IS_FWD(ref32)) {
216*0Sstevel@tonic-gate 		if (TNF_REF32_IS_PERMANENT(ref32)) {
217*0Sstevel@tonic-gate 			reftemp = TNF_REF32_VALUE(ref32);
218*0Sstevel@tonic-gate 			reftemp = TNF_REF32_SIGN_EXTEND(reftemp);
219*0Sstevel@tonic-gate 			cell = (tnf_ref32_t *) ((char *)tnf->file_start +
220*0Sstevel@tonic-gate 		/* LINTED pointer cast may result in improper alignment */
221*0Sstevel@tonic-gate 							reftemp);
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 		} else {
224*0Sstevel@tonic-gate 			cell = vaddr_to_phys(tnf, cell, TNF_REF32_VALUE(ref32));
225*0Sstevel@tonic-gate 			if (cell == TNF_NULL)
226*0Sstevel@tonic-gate 				return (TNF_NULL);
227*0Sstevel@tonic-gate 		}
228*0Sstevel@tonic-gate 		ref32 = _GET_INT32(tnf, cell);
229*0Sstevel@tonic-gate 	}
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate 	return (cell);
232*0Sstevel@tonic-gate }
233