2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2011 Aleph One Ltd.
5 * for Toby Churchill Ltd and Brightstar Engineering
7 * Created by Charles Manning <charles@aleph1.co.uk>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
14 #include "yaffs_packedtags2.h"
16 #include "yaffs_trace.h"
18 /* This code packs a set of extended tags into a binary structure for
22 /* Some of the information is "extra" struff which can be packed in to
24 * This is defined by having the EXTRA_HEADER_INFO_FLAG set.
27 /* Extra flags applied to chunk_id */
29 #define EXTRA_HEADER_INFO_FLAG 0x80000000
30 #define EXTRA_SHRINK_FLAG 0x40000000
31 #define EXTRA_SHADOWS_FLAG 0x20000000
32 #define EXTRA_SPARE_FLAGS 0x10000000
34 #define ALL_EXTRA_FLAGS 0xf0000000
36 /* Also, the top 4 bits of the object Id are set to the object type. */
37 #define EXTRA_OBJECT_TYPE_SHIFT (28)
38 #define EXTRA_OBJECT_TYPE_MASK ((0x0f) << EXTRA_OBJECT_TYPE_SHIFT)
40 static void yaffs_dump_packed_tags2_tags_only(
41 const struct yaffs_packed_tags2_tags_only
*ptt
)
43 yaffs_trace(YAFFS_TRACE_MTD
,
44 "packed tags obj %d chunk %d byte %d seq %d",
45 ptt
->obj_id
, ptt
->chunk_id
, ptt
->n_bytes
, ptt
->seq_number
);
48 static void yaffs_dump_packed_tags2(const struct yaffs_packed_tags2
*pt
)
50 yaffs_dump_packed_tags2_tags_only(&pt
->t
);
53 static void yaffs_dump_tags2(const struct yaffs_ext_tags
*t
)
55 yaffs_trace(YAFFS_TRACE_MTD
,
56 "ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d",
57 t
->ecc_result
, t
->block_bad
, t
->chunk_used
, t
->obj_id
,
58 t
->chunk_id
, t
->n_bytes
, t
->is_deleted
, t
->serial_number
,
63 static int yaffs_check_tags_extra_packable(const struct yaffs_ext_tags
*t
)
65 if (t
->chunk_id
!= 0 || !t
->extra_available
)
68 /* Check if the file size is too long to store */
69 if (t
->extra_obj_type
== YAFFS_OBJECT_TYPE_FILE
&&
70 (t
->extra_file_size
>> 31) != 0)
75 void yaffs_pack_tags2_tags_only(struct yaffs_packed_tags2_tags_only
*ptt
,
76 const struct yaffs_ext_tags
*t
)
78 ptt
->chunk_id
= t
->chunk_id
;
79 ptt
->seq_number
= t
->seq_number
;
80 ptt
->n_bytes
= t
->n_bytes
;
81 ptt
->obj_id
= t
->obj_id
;
83 /* Only store extra tags for object headers.
84 * If it is a file then only store if the file size is short\
87 if (yaffs_check_tags_extra_packable(t
)) {
88 /* Store the extra header info instead */
89 /* We save the parent object in the chunk_id */
90 ptt
->chunk_id
= EXTRA_HEADER_INFO_FLAG
| t
->extra_parent_id
;
91 if (t
->extra_is_shrink
)
92 ptt
->chunk_id
|= EXTRA_SHRINK_FLAG
;
94 ptt
->chunk_id
|= EXTRA_SHADOWS_FLAG
;
96 ptt
->obj_id
&= ~EXTRA_OBJECT_TYPE_MASK
;
97 ptt
->obj_id
|= (t
->extra_obj_type
<< EXTRA_OBJECT_TYPE_SHIFT
);
99 if (t
->extra_obj_type
== YAFFS_OBJECT_TYPE_HARDLINK
)
100 ptt
->n_bytes
= t
->extra_equiv_id
;
101 else if (t
->extra_obj_type
== YAFFS_OBJECT_TYPE_FILE
)
102 ptt
->n_bytes
= (unsigned) t
->extra_file_size
;
107 yaffs_dump_packed_tags2_tags_only(ptt
);
111 void yaffs_pack_tags2(struct yaffs_packed_tags2
*pt
,
112 const struct yaffs_ext_tags
*t
, int tags_ecc
)
114 yaffs_pack_tags2_tags_only(&pt
->t
, t
);
117 yaffs_ecc_calc_other((unsigned char *)&pt
->t
,
118 sizeof(struct yaffs_packed_tags2_tags_only
),
122 void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags
*t
,
123 struct yaffs_packed_tags2_tags_only
*ptt
)
125 memset(t
, 0, sizeof(struct yaffs_ext_tags
));
127 if (ptt
->seq_number
== 0xffffffff)
132 t
->obj_id
= ptt
->obj_id
;
133 t
->chunk_id
= ptt
->chunk_id
;
134 t
->n_bytes
= ptt
->n_bytes
;
136 t
->serial_number
= 0;
137 t
->seq_number
= ptt
->seq_number
;
139 /* Do extra header info stuff */
140 if (ptt
->chunk_id
& EXTRA_HEADER_INFO_FLAG
) {
144 t
->extra_available
= 1;
145 t
->extra_parent_id
= ptt
->chunk_id
& (~(ALL_EXTRA_FLAGS
));
146 t
->extra_is_shrink
= ptt
->chunk_id
& EXTRA_SHRINK_FLAG
? 1 : 0;
147 t
->extra_shadows
= ptt
->chunk_id
& EXTRA_SHADOWS_FLAG
? 1 : 0;
148 t
->extra_obj_type
= ptt
->obj_id
>> EXTRA_OBJECT_TYPE_SHIFT
;
149 t
->obj_id
&= ~EXTRA_OBJECT_TYPE_MASK
;
151 if (t
->extra_obj_type
== YAFFS_OBJECT_TYPE_HARDLINK
)
152 t
->extra_equiv_id
= ptt
->n_bytes
;
154 t
->extra_file_size
= ptt
->n_bytes
;
156 yaffs_dump_packed_tags2_tags_only(ptt
);
160 void yaffs_unpack_tags2(struct yaffs_ext_tags
*t
, struct yaffs_packed_tags2
*pt
,
163 enum yaffs_ecc_result ecc_result
= YAFFS_ECC_RESULT_NO_ERROR
;
165 if (pt
->t
.seq_number
!= 0xffffffff && tags_ecc
) {
166 /* Chunk is in use and we need to do ECC */
168 struct yaffs_ecc_other ecc
;
170 yaffs_ecc_calc_other((unsigned char *)&pt
->t
,
171 sizeof(struct yaffs_packed_tags2_tags_only
),
174 yaffs_ecc_correct_other((unsigned char *)&pt
->t
,
175 sizeof(struct yaffs_packed_tags2_tags_only
),
179 ecc_result
= YAFFS_ECC_RESULT_NO_ERROR
;
182 ecc_result
= YAFFS_ECC_RESULT_FIXED
;
185 ecc_result
= YAFFS_ECC_RESULT_UNFIXED
;
188 ecc_result
= YAFFS_ECC_RESULT_UNKNOWN
;
191 yaffs_unpack_tags2_tags_only(t
, &pt
->t
);
193 t
->ecc_result
= ecc_result
;
195 yaffs_dump_packed_tags2(pt
);