91a3c9d04ac5b7a3077fc7f442b5ba1538e10329
[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 cost char *mkyaffs_c_version = "$Id: mkyaffs.c,v 1.3 2002-09-27 20:50:50 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 /*
71  * Main program
72  */
73 int main(int argc, char **argv)
74 {
75         unsigned long addr;
76         unsigned long offset;
77         int bs, fd, i;
78         int img=-1;
79         int imglen = 0;
80         struct mtd_oob_buf oob = {0, 16, (unsigned char *) &oobbuf};
81         mtd_info_t meminfo;
82         erase_info_t erase;
83
84         /* Make sure a device was specified */
85         if(argc < 2) {
86                 printf("usage: %s <mtdname> [image name]\n", argv[0]);
87                 exit(1);
88         }
89         
90         if(argc > 2 && 
91            (img = open(argv[2],O_RDONLY)) == -1)        {
92                 perror("opening image file");
93                 exit(1);
94         }
95         
96         if(img >= 0){
97            imglen = lseek(img,0,SEEK_END);
98            if(imglen %528){
99                 printf("Image not a multiple of 528 bytes\n");
100                 exit(1);
101            }
102         }
103         
104         lseek(img,0,SEEK_SET);
105
106         /* Open the device */
107         if((fd = open(argv[1], O_RDWR)) == -1) {
108                 perror("opening flash");
109                 exit(1);
110         }
111
112         /* Fill in MTD device capability structure */
113         if(ioctl(fd, MEMGETINFO, &meminfo) != 0) {
114                 perror("MEMGETINFO");
115                 close(fd);
116                 exit(1);
117         }
118
119         /* Make sure device page sizes are valid */
120         if( !(meminfo.oobsize == 16 && meminfo.oobblock == 512)) 
121         {
122                 printf("Unknown flash (not normal NAND)\n");
123                 close(fd);
124                 exit(1);
125         }
126         
127         if(imglen >= 0 &&
128            (imglen/528 +32)*512 > meminfo.size){
129                 printf("Image is too big for NAND\n");
130                 exit(1);
131         }
132         
133         
134         printf("Erasing and programming NAND\n");
135         for(addr = 0; addr < meminfo.size; addr += meminfo.erasesize)
136         {
137                 /* Read the OOB data to determine if the block is valid.
138                  * If the block is damaged, then byte 5 of the OOB data will
139                  * have at least 2 zero bits.
140                  */
141                 oob.start = addr;
142                 oob.length = 16;
143                 oob.ptr = oobbuf;
144                 if (ioctl(fd, MEMREADOOB, &oob) != 0) 
145                 {
146                         perror("ioctl(MEMREADOOB)");
147                         close(fd);
148                         exit(1);
149                 }
150                 
151                 if(countBits[oobbuf[5]] < 7)
152                 {
153                         printf("Block at 0x08%lx is damaged and is not being formatted\n",addr);
154                 }
155                 else
156                 {
157                         /* Erase this block */
158                         erase.start = addr;
159                         erase.length = meminfo.erasesize;
160                         printf("Erasing block at 0x08%lx\n",addr);
161                         if(ioctl(fd, MEMERASE, &erase) != 0) 
162                         {
163                                 perror("\nMTD Erase failure\n");
164                                 close(fd);
165                                 exit(1);
166                         }
167                         
168                         /* Do some programming, but not in the first block */
169                         
170                         if(addr){
171                                 for(offset = 0; offset <meminfo.erasesize; offset+=512)
172                                 {
173                                         if(read(img,imgpage,528) == 528){
174                                                 lseek(fd,addr+offset,SEEK_SET);
175                                                 write(fd,imgpage,512);
176                                                 oob.start = addr+offset;
177                                                 oob.length=16;
178                                                 oob.ptr=&imgpage[512];
179                                                 ioctl(fd,MEMWRITEOOB,&oob);
180                                         }
181                                 }
182                         }
183                         
184                 }
185
186         }
187
188
189
190         /* All the tests succeeded */
191         printf("OK\n");
192         close(fd);
193         return 0;
194 }
195