aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/yaffs2/files/mkyaffs2image.patch
blob: e588a2c0b6b51f47455451facdc62c5721ad3b30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
 * 
 * mkyaffs2image hacks by NCB
 *
 * Changes by Sergey Kubushin flagged KSI
 *
 */
 
/* KSI:
 * All this nightmare should be rewritten from ground up. Why save return
 * values if nobody checks them? The read/write function returns only one
 * error, -1. Positive return value does NOT mean read/write operation has
 * been completed successfully. If somebody opens files, he MUST close them
 * when they are not longer needed. Only those brave enough can write 64
 * bytes from a yaffs_PackedTags2 structure. The list is too long, there is
 * enough bugs here to write a couple of thick books on how NOT to write
 * programs...
 *
 * And BTW, what was one supposed to do with that file that this horror
 * occasionally managed to generate?
 */
Index: yaffs2/utils/mkyaffs2image.c
===================================================================
--- yaffs2.orig/utils/mkyaffs2image.c
+++ yaffs2/utils/mkyaffs2image.c
@@ -29,10 +29,10 @@
 #include <dirent.h>
 #include <string.h>
 #include <unistd.h>
+#include <mtd/mtd-user.h>
 #include "yaffs_ecc.h"
 #include "yaffs_guts.h"
 
-#include "yaffs_tagsvalidity.h"
 #include "yaffs_packedtags2.h"
 
 unsigned yaffs_traceMask=0;
@@ -41,9 +41,46 @@ unsigned yaffs_traceMask=0;
 
 #define chunkSize 2048
 #define spareSize 64
-
+#define PT2_BYTES 25
+ 
 const char * mkyaffsimage_c_version = "$Id: mkyaffs2image.c,v 1.5 2010-01-11 21:43:18 charles Exp $";
 
+static int	layout_no;
+
+static struct nand_oobinfo oob_layout[] = {
+        /* KSI:
+         * Dummy "raw" layout - no ECC, all the bytes are free. Does NOT
+         * really work, only used for compatibility with CVS YAFFS2 that
+         * never ever worked with any stock MTD.
+         */
+        {
+        	.useecc = MTD_NANDECC_AUTOPLACE,
+        	.eccbytes = 0,
+        	.eccpos = {},
+        	.oobfree = { {0, 64} }
+        },
+        /* KSI:
+         * Regular MTD AUTOPLACED ECC for large page NAND devices, the
+         * only one existing in stock MTD so far. It corresponds to layout# 1
+         * in command line arguments. Any other layouts could be added to
+         * the list when they made their way in kernel's MTD. The structure
+         * is simply copied from kernel's drivers/mtd/nand/nand_base.c as-is.
+         */
+        {
+        	.useecc = MTD_NANDECC_AUTOPLACE,
+        	.eccbytes = 24,
+        	.eccpos = {
+	        	40, 41, 42, 43, 44, 45, 46, 47,
+	        	48, 49, 50, 51, 52, 53, 54, 55,
+	        	56, 57, 58, 59, 60, 61, 62, 63},
+        	.oobfree = { {2, 38} }
+        },
+        /* End-of-list marker */
+        {
+                .useecc = -1,
+        }
+};
+
 
 typedef struct
 {
@@ -57,7 +94,7 @@ static objItem obj_list[MAX_OBJECTS];
 static int n_obj = 0;
 static int obj_id = YAFFS_NOBJECT_BUCKETS + 1;
 
-static int nObjects, nDirectories, nPages;
+static int nObjects = 0, nDirectories = 0, nPages = 0;
 
 static int outFile;
 
@@ -121,6 +158,11 @@ static int find_obj_in_list(dev_t dev, i
 	return -1;
 }
 
+/* KSI:
+ * No big endian for now. This is left for a later time. The existing code
+ * is FUBAR.
+ */
+#if 0
 /* This little function converts a little endian tag to a big endian tag.
  * NOTE: The tag is not usable after this other than calculating the CRC
  * with.
@@ -153,11 +195,56 @@ static void little_to_big_endian(yaffs_T
     tags->asBytes[7] = temp.asBytes[7];
 #endif
 }
+#endif
+
+void nandmtd2_pt2buf(unsigned char *buf, yaffs_PackedTags2 *pt)
+{
+	int		i, j = 0, k, n;
+	unsigned char	pt2_byte_buf[PT2_BYTES];
+	
+	*((unsigned int *) &pt2_byte_buf[0]) = pt->t.sequenceNumber;
+	*((unsigned int *) &pt2_byte_buf[4]) = pt->t.objectId;
+	*((unsigned int *) &pt2_byte_buf[8]) = pt->t.chunkId;
+	*((unsigned int *) &pt2_byte_buf[12]) = pt->t.byteCount;
+	pt2_byte_buf[16] = pt->ecc.colParity;
+	pt2_byte_buf[17] = pt->ecc.lineParity & 0xff;
+	pt2_byte_buf[18] = (pt->ecc.lineParity >> 8) & 0xff;
+	pt2_byte_buf[19] = (pt->ecc.lineParity >> 16) & 0xff;
+	pt2_byte_buf[20] = (pt->ecc.lineParity >> 24) & 0xff;
+	pt2_byte_buf[21] = pt->ecc.lineParityPrime & 0xff;
+	pt2_byte_buf[22] = (pt->ecc.lineParityPrime >> 8) & 0xff;
+	pt2_byte_buf[23] = (pt->ecc.lineParityPrime >> 16) & 0xff;
+	pt2_byte_buf[24] = (pt->ecc.lineParityPrime >> 24) & 0xff;
+
+	k = oob_layout[layout_no].oobfree[j][0];
+	n = oob_layout[layout_no].oobfree[j][1];
+		
+	if (n == 0) {
+		fprintf(stderr, "No OOB space for tags");
+		exit(-1);
+	}
+                                
+	for (i = 0; i < PT2_BYTES; i++) {
+		if (n == 0) {
+			j++;
+			k = oob_layout[layout_no].oobfree[j][0];
+			n = oob_layout[layout_no].oobfree[j][1];
+			if (n == 0) {
+				fprintf(stderr, "No OOB space for tags");
+				exit(-1);
+			}
+		}
+		buf[k++] = pt2_byte_buf[i];
+		n--;
+	}
+}
 
 static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes)
 {
 	yaffs_ExtendedTags t;
 	yaffs_PackedTags2 pt;
+	unsigned char	spare_buf[spareSize];
+
 
 	error = write(outFile,data,chunkSize);
 	if(error < 0) return error;
@@ -175,18 +262,27 @@ static int write_chunk(__u8 *data, __u32
 // added NCB **CHECK**
 	t.chunkUsed = 1;
 
+/* KSI: Broken anyway -- e.g. &t is pointer to a wrong type... */
+#if 0
 	if (convert_endian)
 	{
-    	    little_to_big_endian(&t);
+		little_to_big_endian(&t);
 	}
+#endif
 
 	nPages++;
 
-	yaffs_PackTags2(&pt,&t,1);
-	
-//	return write(outFile,&pt,sizeof(yaffs_PackedTags2));
-	return write(outFile,&pt,spareSize);
-	
+	yaffs_PackTags2(&pt,&t,1);
+
+	memset(spare_buf, 0xff, sizeof(spare_buf));
+
+	if (layout_no == 0) {
+		memcpy(spare_buf, &pt, sizeof(yaffs_PackedTags2));
+	} else {
+		nandmtd2_pt2buf(spare_buf, &pt);
+	}
+
+	return write(outFile,spare_buf,spareSize);
 }
 
 #define SWAP32(x)   ((((x) & 0x000000FF) << 24) | \
@@ -197,6 +293,8 @@ static int write_chunk(__u8 *data, __u32
 #define SWAP16(x)   ((((x) & 0x00FF) << 8) | \
                      (((x) & 0xFF00) >> 8))
         
+/* KSI: Removed for now. TBD later when the proper util (from scratch) is written */
+#if 0
 // This one is easier, since the types are more standard. No funky shifts here.
 static void object_header_little_to_big_endian(yaffs_ObjectHeader* oh)
 {
@@ -254,6 +352,7 @@ static void object_header_little_to_big_
     oh->roomToGrow[11] = SWAP32(oh->roomToGrow[11]);
 #endif
 }
+#endif
 
 static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias)
 {
@@ -298,10 +397,13 @@ static int write_object_header(int objId
 		strncpy(oh->alias,alias,YAFFS_MAX_ALIAS_LENGTH);
 	}
 
+/* KSI: FUBAR. Left for a leter time. */
+#if 0
 	if (convert_endian)
 	{
     		object_header_little_to_big_endian(oh);
 	}
+#endif
 	
 	return write_chunk(bytes,objId,0,0xffff);
 	
@@ -317,7 +419,7 @@ static int process_directory(int parent,
 	nDirectories++;
 	
 	dir = opendir(path);
-	
+
 	if(dir)
 	{
 		while((entry = readdir(dir)) != NULL)
@@ -401,12 +503,12 @@ static int process_directory(int parent,
 									   error = nBytes;
 									   
 									printf("%d data chunks written\n",chunk);
+        								close(h);
 								}
 								else
 								{
 									perror("Error opening file");
 								}
-								close(h);
 								
 							}							
 														
@@ -446,58 +548,82 @@ static int process_directory(int parent,
 				}
 			}
 		}
+		/* KSI:
+		 * Who is supposed to close those open directories in this
+		 * recursive function, lord Byron? Stock "ulimit -n" is 1024
+		 * and e.g. stock Fedora /etc directory has more that 1024
+		 * directories...
+		 */
+		closedir(dir);
 	}
 	
 	return 0;
 
 }
 
+void usage(void)
+{
+	printf("usage: mkyaffs2image layout# dir image_file [convert]\n");
+	printf("	layout#    NAND OOB layout # (0 - raw, 1 - nand_oob_64)\n");
+	printf("	dir        the directory tree to be converted\n");
+	printf("	image_file the output file to hold the image\n");
+	printf("	'convert'  make a big-endian img on a little-endian machine. BROKEN !\n");
+	exit(1);
+}
 
 int main(int argc, char *argv[])
 {
 	struct stat stats;
+	int	i;
 	
 	printf("mkyaffs2image: image building tool for YAFFS2 built "__DATE__"\n");
 	
-	if(argc < 3)
+	if ((argc < 4) || (sscanf(argv[1], "%u", &layout_no) != 1))
 	{
-		printf("usage: mkyaffs2image dir image_file [convert]\n");
-		printf("           dir        the directory tree to be converted\n");
-		printf("           image_file the output file to hold the image\n");
-        printf("           'convert'  produce a big-endian image from a little-endian machine\n");
-		exit(1);
+	        usage();
 	}
 
-    if ((argc == 4) && (!strncmp(argv[3], "convert", strlen("convert"))))
-    {
-        convert_endian = 1;
-    }
+	i = 0;
+	
+	while (oob_layout[i].useecc != -1)
+	        i++;
+	        
+        if (layout_no >= i)
+                usage();
+
+	if ((argc == 5) && (!strncmp(argv[4], "convert", strlen("convert"))))
+	{
+	        /* KSI: Broken as of now. TBD. Fail. */
+	        usage();
+                convert_endian = 1;
+        }
     
-	if(stat(argv[1],&stats) < 0)
+	if(stat(argv[2],&stats) < 0)
 	{
-		printf("Could not stat %s\n",argv[1]);
+		printf("Could not stat %s\n",argv[2]);
 		exit(1);
 	}
 	
 	if(!S_ISDIR(stats.st_mode))
 	{
-		printf(" %s is not a directory\n",argv[1]);
+		printf(" %s is not a directory\n",argv[2]);
 		exit(1);
 	}
 	
-	outFile = open(argv[2],O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE);
+	outFile = open(argv[3],O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE);
 	
 	
 	if(outFile < 0)
 	{
-		printf("Could not open output file %s\n",argv[2]);
+		printf("Could not open output file %s\n",argv[3]);
 		exit(1);
 	}
 	
-	printf("Processing directory %s into image file %s\n",argv[1],argv[2]);
+	printf("Processing directory %s into image file %s\n",argv[2],argv[3]);
 	error =  write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL);
+
 	if(error)
-	error = process_directory(YAFFS_OBJECTID_ROOT,argv[1]);
+	error = process_directory(YAFFS_OBJECTID_ROOT,argv[2]);
 	
 	close(outFile);