|
14
|
1 /* |
|
|
2 * YAFFS: Yet another FFS. A NAND-flash specific file system. |
|
|
3 * |
|
|
4 * yaffs_packedtags2.c: Tags packing for YAFFS2 |
|
|
5 * |
|
|
6 * Copyright (C) 2002 Aleph One Ltd. |
|
|
7 * |
|
|
8 * Created by Charles Manning <charles@aleph1.co.uk> |
|
|
9 * |
|
|
10 * |
|
|
11 * This program is free software; you can redistribute it and/or |
|
|
12 * modify it under the terms of the GNU Lesser General Public License |
|
|
13 * version 2.1 as published by the Free Software Foundation. |
|
|
14 */ |
|
|
15 |
|
6
|
16 #include "yaffs_packedtags2.h" |
|
|
17 #include "yportenv.h" |
|
14
|
18 #include "yaffs_tagsvalidity.h" |
|
|
19 |
|
|
20 |
|
|
21 |
|
|
22 // This code packs a set of extended tags into a binary structure for NAND storage |
|
|
23 |
|
|
24 // Some of the information is "extra" struff which can be packed in to speed scanning |
|
|
25 // This is defined by having the EXTRA_HEADER_INFO_FLAG set. |
|
|
26 |
|
|
27 |
|
|
28 // Extra flags applied to chunkId |
|
|
29 |
|
|
30 #define EXTRA_HEADER_INFO_FLAG 0x80000000 |
|
|
31 #define EXTRA_SHRINK_FLAG 0x40000000 |
|
|
32 #define EXTRA_SPARE_FLAGS 0x30000000 |
|
|
33 |
|
|
34 #define ALL_EXTRA_FLAGS 0xF0000000 |
|
|
35 |
|
|
36 |
|
|
37 |
|
|
38 // Also, the top 4 bits of the object Id are set to the object type. |
|
|
39 #define EXTRA_OBJECT_TYPE_SHIFT (28) |
|
|
40 #define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT) |
|
|
41 |
|
6
|
42 |
|
|
43 |
|
7
|
44 static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 *pt) |
|
|
45 { |
|
|
46 T(YAFFS_TRACE_MTD,(TSTR("packed tags obj %d chunk %d byte %d seq %d"TENDSTR),pt->t.objectId,pt->t.chunkId,pt->t.byteCount,pt->t.sequenceNumber)); |
|
|
47 } |
|
6
|
48 |
|
7
|
49 static void yaffs_DumpTags2(const yaffs_ExtendedTags *t) |
|
|
50 { |
|
|
51 T(YAFFS_TRACE_MTD,(TSTR("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"TENDSTR), |
|
|
52 t->eccResult, t->blockBad, t->chunkUsed, t->objectId, t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber, t->sequenceNumber)); |
|
|
53 |
|
|
54 } |
|
|
55 |
|
|
56 void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t) |
|
6
|
57 { |
|
|
58 pt->t.chunkId = t->chunkId; |
|
|
59 pt->t.sequenceNumber = t->sequenceNumber; |
|
|
60 pt->t.byteCount = t->byteCount; |
|
|
61 pt->t.objectId = t->objectId; |
|
|
62 |
|
14
|
63 if(t->chunkId == 0 && t->extraHeaderInfoAvailable) |
|
|
64 { |
|
|
65 // Store the extra header info instead |
|
|
66 pt->t.chunkId = EXTRA_HEADER_INFO_FLAG | t->extraParentObjectId; // We save the parent object in the chunkId |
|
|
67 if(t->extraIsShrinkHeader) |
|
|
68 { |
|
|
69 pt->t.chunkId |= EXTRA_SHRINK_FLAG; |
|
|
70 } |
|
|
71 |
|
|
72 pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK; |
|
|
73 pt->t.objectId |= (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT); |
|
|
74 |
|
|
75 if(t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) |
|
|
76 { |
|
|
77 pt->t.byteCount = t->extraEquivalentObjectId; |
|
|
78 } |
|
|
79 else if(t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) |
|
|
80 { |
|
|
81 pt->t.byteCount = t->extraFileLength; |
|
|
82 } |
|
|
83 else |
|
|
84 { |
|
|
85 pt->t.byteCount = 0; |
|
|
86 } |
|
|
87 } |
|
|
88 |
|
7
|
89 yaffs_DumpPackedTags2(pt); |
|
|
90 yaffs_DumpTags2(t); |
|
|
91 |
|
6
|
92 yaffs_ECCCalculateOther((unsigned char *)&pt->t,sizeof(yaffs_PackedTags2TagsPart),&pt->ecc); |
|
|
93 |
|
|
94 } |
|
|
95 |
|
14
|
96 void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt) |
|
6
|
97 { |
|
|
98 |
|
|
99 |
|
14
|
100 memset(t,0,sizeof(yaffs_ExtendedTags)); |
|
|
101 |
|
|
102 yaffs_InitialiseTags(t); |
|
|
103 |
|
|
104 if(pt->t.sequenceNumber != 0xFFFFFFFF) |
|
6
|
105 { |
|
|
106 // Page is in use |
|
|
107 yaffs_ECCOther ecc; |
|
|
108 yaffs_ECCCalculateOther((unsigned char *)&pt->t,sizeof(yaffs_PackedTags2TagsPart),&ecc); |
|
|
109 t->eccResult = yaffs_ECCCorrectOther((unsigned char *)&pt->t,sizeof(yaffs_PackedTags2TagsPart),&pt->ecc,&ecc); |
|
|
110 t->blockBad = 0; |
|
|
111 t->chunkUsed = 1; |
|
|
112 t->objectId = pt->t.objectId; |
|
|
113 t->chunkId = pt->t.chunkId; |
|
|
114 t->byteCount = pt->t.byteCount; |
|
|
115 t->chunkDeleted = 0; |
|
|
116 t->serialNumber = 0; |
|
|
117 t->sequenceNumber = pt->t.sequenceNumber; |
|
14
|
118 |
|
|
119 // Do extra header info stuff |
|
|
120 |
|
|
121 if(pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) |
|
|
122 { |
|
|
123 t->chunkId = 0; |
|
|
124 t->byteCount = 0; |
|
|
125 |
|
|
126 t->extraHeaderInfoAvailable = 1; |
|
|
127 t->extraParentObjectId = pt->t.chunkId & (~(ALL_EXTRA_FLAGS)); |
|
|
128 t->extraIsShrinkHeader = (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0; |
|
|
129 t->extraObjectType = pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT; |
|
|
130 t->objectId &= ~EXTRA_OBJECT_TYPE_MASK; |
|
|
131 |
|
|
132 if(t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) |
|
|
133 { |
|
|
134 t->extraEquivalentObjectId = pt->t.byteCount; |
|
|
135 } |
|
|
136 else |
|
|
137 { |
|
|
138 t->extraFileLength = pt->t.byteCount; |
|
|
139 } |
|
|
140 } |
|
6
|
141 } |
|
7
|
142 |
|
|
143 yaffs_DumpPackedTags2(pt); |
|
|
144 yaffs_DumpTags2(t); |
|
|
145 |
|
6
|
146 } |
|
|
147 |