Home | History | Annotate | Download | only in yaffs2
      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