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