Add endian feature to image maker and do some tidy up.
[yaffs2.git] / direct / test-framework / yaffs2_image_maker / yaffs2_image_maker.c
1 /*
2  * An image maker that creates a file that creates a Yaffs2 image file
3  * can be programmed into NAND.
4  * This assumes that the device has the following properties:
5  * * 2k bytes per page
6  * * 64  pages per block
7  * * Yaffs is using inband tags.
8  *
9  * Note that this utility first generates a "working file" which is
10  * a simulation of the NAND. It then generates an output file which
11  * can be programmed into flash.
12  *
13  */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <fcntl.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <dirent.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <assert.h>
25
26 #if 1
27 #undef CONFIG_YAFFS_PROVIDE_DEFS
28 #undef CONFIG_YAFFSFS_PROVIDE_VALUES
29 #endif
30
31 #include "yaffsfs.h"
32
33 #include "yaffs_nandsim_file.h"
34 #include "yaffs_guts.h"
35 #include "yaffs_trace.h"
36
37
38 /*
39  * These are the sizes in the simulator file.
40  */
41 #define PAGE_DATA_SIZE  2048
42 #define PAGE_SPARE_SIZE 64
43 #define PAGE_SIZE       (PAGE_DATA_SIZE + PAGE_SPARE_SIZE)
44
45
46 /* Some stub definitions to get building to work. */
47 int simulate_power_failure = 0;
48 int random_seed = 0;
49
50 static char *input_dir;
51 static char *output_file;
52 static char *working_file;
53 static char endian = 'l';
54
55 static void usage(const char *prog_name)
56 {
57         printf("Usage: %s options\n", prog_name);
58         printf("\t-i name input_directory\n");
59         printf("\t-o name output_file\n");
60         printf("\t-w name working_file\n");
61         printf("\t-b      big endian output\n");
62 }
63
64 static void parse_args(int argc, char *argv[])
65 {
66         int c;
67
68         opterr = 0;
69         while ((c = getopt(argc, argv, "bi:o:w:h")) != -1) {
70                 switch (c) {
71                 default:
72                 case 'h': usage(argv[0]); break;
73                 case 'i': input_dir = strdup(optarg); break;
74                 case 'o': output_file = strdup(optarg); break;
75                 case 'w': working_file = strdup(optarg); break;
76                 case 'b': endian = 'b'; break;
77                 }
78         }
79 }
80
81
82 static int process_file(const char *from_path, const char *to_path, unsigned mode)
83 {
84         int hin;
85         int hout;
86         unsigned char buffer[8000];
87         int nread;
88         int nwritten;
89         int nbytes = 0;
90         int ret;
91
92         hin = open(from_path, O_RDONLY);
93         if (hin < 0) {
94                 perror ("opening input file");
95                 return -1;
96         }
97         hout = yaffs_open(to_path, O_CREAT | O_TRUNC | O_RDWR, 0666);
98
99         if(hout < 0) {
100                 printf("failed to create yaffs file %s\n", to_path);
101                 return -1;
102         }
103
104         while ((nread = read(hin, buffer, sizeof(buffer))) > 0) {
105                 nwritten = yaffs_write(hout, buffer, nread);
106
107                 if (nwritten != nread) {
108                         printf("Only wrote %d bytes out of %d\n", nwritten, nread);
109                         return -1;
110                 }
111                 nbytes += nwritten;
112         }
113
114         ret = yaffs_fdatasync(hout);
115         if (ret < 0) {
116                 printf("data sytnc failed\n");
117                 return -1;
118         }
119
120         ret = yaffs_fchmod(hout, mode);
121         if (ret < 0) {
122                 printf("chmod failed\n");
123                 return -1;
124         }
125
126         ret = yaffs_close(hout);
127         if (ret < 0) {
128                 printf("close failed\n");
129                 return -1;
130         }
131
132         return nbytes;
133 }
134
135 static int process_directory(const char *from_dir, const char *to_dir)
136 {
137         int error = 0;
138
139         DIR *dir;
140         struct dirent *entry;
141
142         printf("Processing directory %s into %s\n", from_dir, to_dir);
143
144         dir = opendir(from_dir);
145         if(!dir) {
146                 printf("opendir failed on %s", from_dir);
147                 return -1;
148         }
149
150         while((entry = readdir(dir)) != NULL  && error >= 0) {
151                 char from_path[500];
152                 char to_path[500];
153                 struct stat stats;
154                 unsigned  mode;
155                 int ret;
156
157                 //printf("Got entry %s\n", entry->d_name);
158
159                 /* Ignore . and .. */
160                 if(strcmp(entry->d_name, ".") == 0 ||
161                    strcmp(entry->d_name, "..") == 0)
162                    continue;
163
164                 if (snprintf(from_path, sizeof(from_path),
165                             "%s/%s", from_dir,entry->d_name) >= (int)sizeof(from_path)) {
166                         printf("path too long for %s/%s\n", from_dir, entry->d_name);
167                         error = -1;
168                         continue;
169                 }
170                 if (snprintf(to_path, sizeof(to_path),
171                             "%s/%s",to_dir,entry->d_name) >= (int)sizeof(to_path)) {
172                         printf("path too long for %s/%s\n",to_dir,entry->d_name);
173                         error = -1;
174                         continue;
175                 }
176
177                 if (lstat(from_path,&stats) < 0)
178                 {
179                         perror("lstat");
180                         error = -1;
181                         continue;
182                 }
183
184                 mode = stats.st_mode & 0777;
185
186                 if (S_ISDIR(stats.st_mode)) {
187                         printf("Directory create %s, mode %03o\n", to_path, mode);
188                         ret = yaffs_mkdir(to_path, mode);
189                         printf("Directory create %s, mode %03o : result %d\n",
190                                 to_path, mode, ret);
191
192                         if (ret < 0) {
193                                 printf("directory creation failed\n");
194                                 error = -1;
195                         }
196                         process_directory(from_path, to_path);
197                 } else if (S_ISREG(stats.st_mode)) {
198                         ret = process_file(from_path, to_path, mode);
199                         printf("Copy file %s to %s, mode %03o : result %d\n",
200                                 from_path, to_path, mode, ret);
201                         if (ret < 0) {
202                                 printf("file copy failed\n");
203                                 error = -1;
204                         }
205
206                 } else {
207                         printf("Unhandled object type %d\n", stats.st_mode);
208                 }
209         }
210
211         closedir(dir);
212
213         return 0;
214
215 }
216
217 int is_all_ff(unsigned char *buffer, int n)
218 {
219         while (n > 0) {
220                 if (*buffer != 0xff)
221                         return 0;
222                 buffer++;
223                 n--;
224         }
225
226         return 1;
227 }
228
229 /*
230  * Write the data to output, skipping over the spare bytes.
231  * Stop writing when we get to blank flash.
232  */
233 int generate_output_file(const char *working_file, const char *output_file)
234 {
235         unsigned char buffer[PAGE_SIZE];
236         int inh;
237         int outh;
238         int nread;
239         int nwritten;
240         int total = 0;
241
242         inh = open(working_file, O_RDONLY);
243         outh = open(output_file, O_CREAT | O_TRUNC | O_RDWR, 0666);
244
245         while ((nread = read(inh, buffer, PAGE_SIZE)) > 0) {
246                 if (nread != PAGE_SIZE) {
247                         printf("working file not properly sized\n");
248                         return -1;
249                 }
250
251                 if(is_all_ff(buffer, PAGE_DATA_SIZE)) {
252                         printf("End of data found\n");
253                         break;
254                 }
255
256                 nwritten = write(outh, buffer, PAGE_DATA_SIZE);
257
258                 if (nwritten != PAGE_DATA_SIZE) {
259                         printf("short write\n");
260                         return -1;
261                 }
262
263                 total+= nwritten;
264         }
265
266         close(inh);
267         close(outh);
268
269         return total;
270 }
271
272
273 int main(int argc, char *argv[])
274 {
275         struct yaffs_dev * dev;
276         int ret;
277
278         yaffs_trace_mask = 0;
279
280         parse_args(argc, argv);
281
282         if (!input_dir || !output_file || !working_file) {
283                 printf("Need input directory , output file and working file\n");
284                 exit(1);
285         }
286
287         printf("Generating image from %s into file %s using working file %s\n",
288                 input_dir, output_file, working_file);
289         printf("Output file is in %s endian\n",
290                 (endian == 'l') ? "little" : "big");
291
292         /*
293          * Create the Yaffs working file using the simulator.
294          */
295         unlink(working_file);
296         dev = yaffs_nandsim_install_drv("yroot",
297                                         working_file,
298                                         2048,
299                                         10,
300                                         1);
301
302         if (!dev) {
303                 printf("Failed to create yaffs working file\n");
304                 exit(1);
305         }
306
307         /*
308          * Disable checkpointing to create an image without checkpoint data.
309          */
310         dev->param.skip_checkpt_rd = 1;
311         dev->param.skip_checkpt_wr = 1;
312
313         /*
314          * Set up stored endian: 1 = little endian, 2 = big endian.
315          */
316         dev->param.stored_endian = (endian == 'l') ? 1 : 2;
317
318         ret = yaffs_mount("yroot");
319
320         printf("yaffs_mount returned %d\n", ret);
321
322         process_directory(input_dir, "yroot");
323
324         yaffs_unmount("yroot");
325
326         printf("Generating output file\n");
327
328         ret = generate_output_file(working_file, output_file);
329
330         printf("wrote %d bytes to output\n", ret);
331
332         if (ret < 0)
333                 exit(1);
334
335         return 0;
336 }