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