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 (at) 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 16 #include "yaffs_packedtags2.h" 17 #include "yportenv.h" 18 #include "yaffs_tagsvalidity.h" 19 20 /* This code packs a set of extended tags into a binary structure for 21 * NAND storage 22 */ 23 24 /* Some of the information is "extra" struff which can be packed in to 25 * speed scanning 26 * This is defined by having the EXTRA_HEADER_INFO_FLAG set. 27 */ 28 29 /* Extra flags applied to chunkId */ 30 31 #define EXTRA_HEADER_INFO_FLAG 0x80000000 32 #define EXTRA_SHRINK_FLAG 0x40000000 33 #define EXTRA_SHADOWS_FLAG 0x20000000 34 #define EXTRA_SPARE_FLAGS 0x10000000 35 36 #define ALL_EXTRA_FLAGS 0xF0000000 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 42 #ifndef CONFIG_YAFFS_DOES_ECC 43 #define YAFFS_IGNORE_TAGS_ECC 1 44 #endif 45 46 static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt) 47 { 48 T(YAFFS_TRACE_MTD, 49 (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR), 50 pt->t.objectId, pt->t.chunkId, pt->t.byteCount, 51 pt->t.sequenceNumber)); 52 } 53 54 static void yaffs_DumpTags2(const yaffs_ExtendedTags * t) 55 { 56 T(YAFFS_TRACE_MTD, 57 (TSTR 58 ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte " 59 "%d del %d ser %d seq %d" 60 TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId, 61 t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber, 62 t->sequenceNumber)); 63 64 } 65 66 void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t) 67 { 68 pt->t.chunkId = t->chunkId; 69 pt->t.sequenceNumber = t->sequenceNumber; 70 pt->t.byteCount = t->byteCount; 71 pt->t.objectId = t->objectId; 72 73 if (t->chunkId == 0 && t->extraHeaderInfoAvailable) { 74 /* Store the extra header info instead */ 75 /* We save the parent object in the chunkId */ 76 pt->t.chunkId = EXTRA_HEADER_INFO_FLAG 77 | t->extraParentObjectId; 78 if (t->extraIsShrinkHeader) { 79 pt->t.chunkId |= EXTRA_SHRINK_FLAG; 80 } 81 if (t->extraShadows) { 82 pt->t.chunkId |= EXTRA_SHADOWS_FLAG; 83 } 84 85 pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK; 86 pt->t.objectId |= 87 (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT); 88 89 if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) { 90 pt->t.byteCount = t->extraEquivalentObjectId; 91 } else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) { 92 pt->t.byteCount = t->extraFileLength; 93 } else { 94 pt->t.byteCount = 0; 95 } 96 } 97 98 yaffs_DumpPackedTags2(pt); 99 yaffs_DumpTags2(t); 100 101 #ifndef YAFFS_IGNORE_TAGS_ECC 102 { 103 yaffs_ECCCalculateOther((unsigned char *)&pt->t, 104 sizeof(yaffs_PackedTags2TagsPart), 105 &pt->ecc); 106 } 107 #endif 108 } 109 110 void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt) 111 { 112 113 memset(t, 0, sizeof(yaffs_ExtendedTags)); 114 115 yaffs_InitialiseTags(t); 116 117 if (pt->t.sequenceNumber != 0xFFFFFFFF) { 118 /* Page is in use */ 119 #ifdef YAFFS_IGNORE_TAGS_ECC 120 { 121 t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; 122 } 123 #else 124 { 125 yaffs_ECCOther ecc; 126 int result; 127 yaffs_ECCCalculateOther((unsigned char *)&pt->t, 128 sizeof 129 (yaffs_PackedTags2TagsPart), 130 &ecc); 131 result = 132 yaffs_ECCCorrectOther((unsigned char *)&pt->t, 133 sizeof 134 (yaffs_PackedTags2TagsPart), 135 &pt->ecc, &ecc); 136 switch(result){ 137 case 0: 138 t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; 139 break; 140 case 1: 141 t->eccResult = YAFFS_ECC_RESULT_FIXED; 142 break; 143 case -1: 144 t->eccResult = YAFFS_ECC_RESULT_UNFIXED; 145 break; 146 default: 147 t->eccResult = YAFFS_ECC_RESULT_UNKNOWN; 148 } 149 } 150 #endif 151 t->blockBad = 0; 152 t->chunkUsed = 1; 153 t->objectId = pt->t.objectId; 154 t->chunkId = pt->t.chunkId; 155 t->byteCount = pt->t.byteCount; 156 t->chunkDeleted = 0; 157 t->serialNumber = 0; 158 t->sequenceNumber = pt->t.sequenceNumber; 159 160 /* Do extra header info stuff */ 161 162 if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) { 163 t->chunkId = 0; 164 t->byteCount = 0; 165 166 t->extraHeaderInfoAvailable = 1; 167 t->extraParentObjectId = 168 pt->t.chunkId & (~(ALL_EXTRA_FLAGS)); 169 t->extraIsShrinkHeader = 170 (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0; 171 t->extraShadows = 172 (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0; 173 t->extraObjectType = 174 pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT; 175 t->objectId &= ~EXTRA_OBJECT_TYPE_MASK; 176 177 if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) { 178 t->extraEquivalentObjectId = pt->t.byteCount; 179 } else { 180 t->extraFileLength = pt->t.byteCount; 181 } 182 } 183 } 184 185 yaffs_DumpPackedTags2(pt); 186 yaffs_DumpTags2(t); 187 188 } 189