*** empty log message ***
[yaffs/.git] / utils / mkyaffs.c
1 /*
2  * YAFFS: Yet another FFS. A NAND-flash specific file system. 
3  * mkyaffs.c Format a chunk of NAND for YAFFS.
4  *
5  * Copyright (C) 2002 Aleph One Ltd.
6  *   for Toby Churchill Ltd and Brightstar Engineering
7  *
8  * Created by Charles Manning <charles@aleph1.co.uk>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  *  Acknowledgement:
15  *  This file is crafted from nandtest.c by  Miguel Freitas (miguel@cetuc.puc-rio.br)
16  *  and Steven J. Hill (sjhill@cotw.com)
17  *
18  * Overview:
19  * Formatting a YAFFS device is very simple. Just erase all undamaged blocks. 
20  * NB Don't erase blocks maked as damaged.
21  */
22
23 #define _GNU_SOURCE
24 #include <ctype.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <time.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <sys/ioctl.h>
32 #include <sys/types.h>
33 #include <asm/types.h>
34 #include <linux/config.h>
35 #include <linux/mtd/mtd.h>
36
37 const char *mkyaffs_c_version = "$Id: mkyaffs.c,v 1.8 2003-03-12 19:54:07 charles Exp $";
38
39 // countBits is a quick way of counting the number of bits in a byte.
40 // ie. countBits[n] holds the number of 1 bits in a byte with the value n.
41
42 static const char countBits[256] =
43 {
44 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
45 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
46 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
47 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
48 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
49 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
50 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
51 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
52 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
53 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
54 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
55 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
56 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
57 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
58 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
59 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
60 };
61
62 /*
63  * Buffer arrays used for running tests
64  */
65
66 unsigned char oobbuf[16];
67 unsigned char imgpage[528];
68
69 /*
70  * OOB layout
71  */
72
73 struct nand_oobinfo yaffs_oobinfo = {
74         useecc: 1,
75         eccpos: {8, 9, 10, 13, 14, 15}
76 };
77
78 struct nand_oobinfo yaffs_noeccinfo = {
79         useecc: 0,
80 };
81
82
83 /*
84  * Main program
85  */
86 int main(int argc, char **argv)
87 {
88         unsigned long addr;
89         unsigned long offset;
90         int fd;
91         int img=-1;
92         int optcnt = 1;
93         int usemtdecc = 0;
94         int imglen = 0;
95         int showHelp = 0;
96         struct mtd_oob_buf oob = {0, 16, (unsigned char *) &oobbuf};
97         mtd_info_t meminfo;
98         erase_info_t erase;
99         struct nand_oobinfo oobsel;
100
101         if (argc > 1 && strcmp (argv[optcnt], "-?") == 0) {
102                 showHelp = 1;
103         }
104
105         if (argc > 1 && strcmp (argv[optcnt], "-h") == 0) {
106                 showHelp = 1;
107         }
108         
109         if (argc > 1 && strcmp (argv[optcnt], "-e") == 0) {
110                 optcnt++;
111                 usemtdecc = 1;
112         }
113         
114         printf("argc %d sh %d optcnt %d\n",argc, showHelp, optcnt);
115         
116         /* Make sure a device was specified */
117         if(showHelp || argc < (optcnt + 1)) {
118                 printf("usage: %s [-e] <mtdname> [image name]\n", argv[0]);
119                 printf("  -e         Use mtd ecc. Default: do not use mtd ecc\n");
120                 printf("  mtdname    Name of mtd device\n");
121                 printf("  image name Name of optional image file\n\n");
122                 printf("Function: Formats a NAND mtd device for YAFFS. If the optional\n"
123                        "image file is specified, then the file system is loaded with\n"
124                        "this image.\n\n");
125                 exit(1);
126         }
127
128         if( argc > (optcnt + 1) &&
129             (img = open(argv[optcnt + 1],O_RDONLY)) == -1) {
130                 perror("opening image file");
131                 exit(1);
132         }
133         
134         if(img >= 0){
135            imglen = lseek(img,0,SEEK_END);
136            if(imglen %528){
137                 printf("Image not a multiple of 528 bytes\n");
138                 exit(1);
139            }
140         }
141         
142         lseek(img,0,SEEK_SET);
143
144         /* Open the device */
145         if((fd = open(argv[optcnt], O_RDWR)) == -1) {
146                 perror("opening flash");
147                 exit(1);
148         }
149
150         /* Fill in MTD device capability structure */
151         if(ioctl(fd, MEMGETINFO, &meminfo) != 0) {
152                 perror("MEMGETINFO");
153                 close(fd);
154                 exit(1);
155         }
156
157         // set the appropriate oob layout selector
158         oobsel = usemtdecc ? yaffs_oobinfo : yaffs_noeccinfo;
159         if (ioctl (fd, MEMSETOOBSEL, &oobsel) != 0) {
160                 perror ("MEMSETOOBSEL");
161                 close (fd);
162                 exit (1);
163         } 
164
165         /* Make sure device page sizes are valid */
166         if( !(meminfo.oobsize == 16 && meminfo.oobblock == 512)) 
167         {
168                 printf("Unknown flash (not normal NAND)\n");
169                 close(fd);
170                 exit(1);
171         }
172         
173         if(imglen >= 0 &&
174            (imglen/528 +32)*512 > meminfo.size){
175                 printf("Image is too big for NAND\n");
176                 exit(1);
177         }
178         
179         
180         printf("Erasing and programming NAND\n");
181         for(addr = 0; addr < meminfo.size; addr += meminfo.erasesize)
182         {
183                 /* Read the OOB data to determine if the block is valid.
184                  * If the block is damaged, then byte 5 of the OOB data will
185                  * have at least 2 zero bits.
186                  */
187                 oob.start = addr;
188                 oob.length = 16;
189                 oob.ptr = oobbuf;
190                 if (ioctl(fd, MEMREADOOB, &oob) != 0) 
191                 {
192                         perror("ioctl(MEMREADOOB)");
193                         close(fd);
194                         exit(1);
195                 }
196                 
197                 if(countBits[oobbuf[5]] < 7)
198                 {
199                         printf("Block at 0x08%lx is damaged and is not being formatted\n",addr);
200                 }
201                 else
202                 {
203                         /* Erase this block */
204                         erase.start = addr;
205                         erase.length = meminfo.erasesize;
206                         printf("Erasing block at 0x08%lx\n",addr);
207                         if(ioctl(fd, MEMERASE, &erase) != 0) 
208                         {
209                                 perror("\nMTD Erase failure\n");
210                                 close(fd);
211                                 exit(1);
212                         }
213                         
214                         /* Do some programming, but not in the first block */
215                         
216                         if(addr){
217                                 for(offset = 0; offset <meminfo.erasesize; offset+=512)
218                                 {
219                                         if(read(img,imgpage,528) == 528){
220                                                 if (usemtdecc) {
221                                                         imgpage[512+8] = 0xff;
222                                                         imgpage[512+9] = 0xff;
223                                                         imgpage[512+10] = 0xff;
224                                                         imgpage[512+13] = 0xff;
225                                                         imgpage[512+14] = 0xff;
226                                                         imgpage[512+15] = 0xff;
227                                                 }
228                                                 oob.start = addr+offset;
229                                                 oob.length=16;
230                                                 oob.ptr=&imgpage[512];
231                                                 ioctl(fd,MEMWRITEOOB,&oob);
232
233                                                 lseek(fd,addr+offset,SEEK_SET);
234                                                 write(fd,imgpage,512);
235                                         }
236                                 }
237                         }
238                         
239                 }
240
241         }
242
243
244
245         /* All the tests succeeded */
246         printf("OK\n");
247         close(fd);
248         return 0;
249 }
250