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
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.
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]
23 * Copyright (c) 1994, by Sun Microsytems, Inc.
26 #pragma ident "%Z%%M% %I% %E% SMI"
31 * Unoptimized versions, always dereference a cell through _GET_INT32()
35 #define LONG_SIGN_BIT 0x80000000
37 static tnf_ref32_t
*vaddr_to_phys(TNF
*, tnf_ref32_t
*, tnf_ref32_t
);
40 * Return target cell referred to via src_val from src_cell, after
41 * checking that target is valid (block was not reused). Return NULL
44 * NOTE: We must check if the destination is within the valid_bytes
45 * range of its block, so as to correctly handle tnfxtract'ed files:
46 * the block containing the target cell may have been copied out
47 * before the block containing the source cell.
51 vaddr_to_phys(TNF
*tnf
, tnf_ref32_t
*src_cell
, tnf_ref32_t src_val
)
55 tnf_uint32_t src_gen
, dst_gen
, exp_gen
;
56 tnf_int32_t gen_delta
;
57 tnf_ref32_t src_off
, exp_off
, dst_off
, *dst_blk
, *dst_cell
;
58 tnf_uint32_t bytes_valid
;
60 base
= tnf
->file_start
;
61 shft
= tnf
->generation_shift
;
62 mask
= tnf
->address_mask
;
64 /* Generation of source cell */
65 /* LINTED pointer cast */
66 src_gen
= _GET_BLOCK_GENERATION(tnf
, _GET_BLOCK(tnf
, src_cell
));
67 /* Physical file offset of source cell */
68 src_off
= (tnf_ref32_t
)((char *)src_cell
- base
);
69 /* Expected (unadjusted) file offset of destination cell */
70 exp_off
= src_off
+ src_val
;
71 /* Generation delta */
72 gen_delta
= (tnf_int32_t
)((unsigned)exp_off
>> shft
);
73 if ((exp_off
& LONG_SIGN_BIT
) == LONG_SIGN_BIT
) {
74 /* sign bit was a 1 - so restore sign */
75 gen_delta
|= ((unsigned)mask
<< (32 - shft
));
77 /* Expected destination generation */
78 exp_gen
= src_gen
+ gen_delta
;
79 /* Physical file offset of destination cell */
80 dst_off
= (tnf_ref32_t
)((unsigned)exp_off
& mask
);
82 /* Destination cell */
83 /* LINTED pointer cast */
84 dst_cell
= (tnf_ref32_t
*)(base
+ dst_off
);
85 /* Destination block */
86 /* LINTED pointer cast */
87 dst_blk
= _GET_BLOCK(tnf
, dst_cell
);
88 /* Generation of destination cell */
89 /* LINTED pointer cast */
90 dst_gen
= _GET_BLOCK_GENERATION(tnf
, dst_blk
);
91 /* Bytes valid in destination block */
92 /* LINTED pointer cast */
93 bytes_valid
= _GET_BLOCK_BYTES_VALID(tnf
, dst_blk
);
95 if ((src_gen
== (tnf_uint32_t
)TNF_TAG_GENERATION_NUM
) ||
96 (dst_gen
== (tnf_uint32_t
)TNF_TAG_GENERATION_NUM
) ||
97 ((dst_gen
== exp_gen
) &&
98 ((char *)dst_cell
- (char *)dst_blk
) < bytes_valid
))
101 return ((tnf_ref32_t
*)NULL
);
105 * Return the target referent of a cell, chasing forwarding references.
106 * Return TNF_NULL if cell is a TNF_NULL forwarding reference.
110 _tnf_get_ref32(TNF
*tnf
, tnf_ref32_t
*cell
)
112 tnf_ref32_t ref32
, reftemp
;
114 ref32
= _GET_INT32(tnf
, cell
);
116 if (TNF_REF32_IS_NULL(ref32
))
119 if (TNF_REF32_IS_RSVD(ref32
)) {
120 _tnf_error(tnf
, TNF_ERR_BADREFTYPE
);
124 if (TNF_REF32_IS_PAIR(ref32
)) {
125 /* We chase the high (tag) half */
128 tag16
= TNF_REF32_TAG16(ref32
);
130 if (TNF_TAG16_IS_ABS(tag16
)) {
131 cell
= (tnf_ref32_t
*)
132 ((char *)tnf
->file_start
133 /* LINTED pointer cast may result in improper alignment */
134 + TNF_TAG16_ABS16(tag16
));
135 ref32
= _GET_INT32(tnf
, cell
);
137 } else if (TNF_TAG16_IS_REL(tag16
)) {
138 cell
= vaddr_to_phys(tnf
, cell
,
139 (tnf_ref32_t
) TNF_TAG16_REF16(tag16
));
140 if (cell
== TNF_NULL
)
142 ref32
= _GET_INT32(tnf
, cell
);
145 _tnf_error(tnf
, TNF_ERR_BADREFTYPE
);
149 } else if (TNF_REF32_IS_PERMANENT(ref32
)) {
150 /* permanent space pointer */
151 reftemp
= TNF_REF32_VALUE(ref32
);
152 reftemp
= TNF_REF32_SIGN_EXTEND(reftemp
);
153 /* LINTED pointer cast may result in improper alignment */
154 cell
= (tnf_ref32_t
*) ((char *)tnf
->file_start
+ reftemp
);
155 ref32
= _GET_INT32(tnf
, cell
);
157 } else { /* full/tag reclaimable space reference */
158 cell
= vaddr_to_phys(tnf
, cell
, TNF_REF32_VALUE(ref32
));
159 if (cell
== TNF_NULL
)
161 ref32
= _GET_INT32(tnf
, cell
);
164 /* chase intermediate forwarding references */
165 while (ref32
&& TNF_REF32_IS_FWD(ref32
)) {
166 if (TNF_REF32_IS_PERMANENT(ref32
)) {
167 reftemp
= TNF_REF32_VALUE(ref32
);
168 reftemp
= TNF_REF32_SIGN_EXTEND(reftemp
);
169 cell
= (tnf_ref32_t
*) ((char *)tnf
->file_start
+
170 /* LINTED pointer cast may result in improper alignment */
174 cell
= vaddr_to_phys(tnf
, cell
, TNF_REF32_VALUE(ref32
));
175 if (cell
== TNF_NULL
)
178 ref32
= _GET_INT32(tnf
, cell
);
185 * Return the target referent of ref16 contained in cell.
186 * Return TNF_NULL if cell doesn't have a ref16.
190 _tnf_get_ref16(TNF
*tnf
, tnf_ref32_t
*cell
)
192 tnf_ref32_t ref32
, reftemp
;
194 ref32
= _GET_INT32(tnf
, cell
);
196 if (TNF_REF32_IS_PAIR(ref32
)) {
199 ref16
= TNF_REF32_REF16(ref32
);
201 if (TNF_REF16_VALUE(ref16
) == TNF_NULL
)
202 /* No ref16 was stored */
205 cell
= vaddr_to_phys(tnf
, cell
,
206 (tnf_ref32_t
) TNF_REF16_VALUE(ref16
));
207 if (cell
== TNF_NULL
)
209 ref32
= _GET_INT32(tnf
, cell
);
211 } else /* not a pair pointer */
214 /* chase intermediate forwarding references */
215 while (ref32
&& TNF_REF32_IS_FWD(ref32
)) {
216 if (TNF_REF32_IS_PERMANENT(ref32
)) {
217 reftemp
= TNF_REF32_VALUE(ref32
);
218 reftemp
= TNF_REF32_SIGN_EXTEND(reftemp
);
219 cell
= (tnf_ref32_t
*) ((char *)tnf
->file_start
+
220 /* LINTED pointer cast may result in improper alignment */
224 cell
= vaddr_to_phys(tnf
, cell
, TNF_REF32_VALUE(ref32
));
225 if (cell
== TNF_NULL
)
228 ref32
= _GET_INT32(tnf
, cell
);