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:
7 * * Yaffs is using inband tags.
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.
18 #include <sys/types.h>
27 #undef CONFIG_YAFFS_PROVIDE_DEFS
28 #undef CONFIG_YAFFSFS_PROVIDE_VALUES
33 #include "yaffs_nandsim_file.h"
34 #include "yaffs_guts.h"
35 #include "yaffs_trace.h"
36 #include "yaffs_packedtags2.h"
40 * These are the sizes in the simulator file.
42 #define PAGE_DATA_SIZE 2048
43 #define PAGE_SPARE_SIZE 64
44 #define PAGE_SIZE (PAGE_DATA_SIZE + PAGE_SPARE_SIZE)
47 /* Some stub definitions to get building to work. */
48 int simulate_power_failure = 0;
51 static char *input_dir;
52 static char *output_file;
53 static char *working_file;
54 static char endian = 'l';
55 static int no_tags_ecc = 0;
56 static int inband_tags = 0;
59 static int record_size;
60 static int total_written;
62 static void usage(const char *prog_name)
64 printf("Usage: %s options\n", prog_name);
65 printf("\t-i name input_directory\n");
66 printf("\t-o name output_file\n");
67 printf("\t-w name working_file\n");
68 printf("\t-b big endian output\n");
69 printf("\t-I strore tags in flash data area (inband_tags)\n");
70 printf("\t-N do not apply ECC to tags in OOB area (no_tags_ecc)\n");
74 static void parse_args(int argc, char *argv[])
79 while ((c = getopt(argc, argv, "bi:o:w:hIN")) != -1) {
82 case 'h': usage(argv[0]); break;
83 case 'i': input_dir = strdup(optarg); break;
84 case 'o': output_file = strdup(optarg); break;
85 case 'w': working_file = strdup(optarg); break;
86 case 'b': endian = 'b'; break;
87 case 'I': inband_tags = 1; break;
88 case 'N': no_tags_ecc = 1; break;
94 static int process_file(const char *from_path, const char *to_path, unsigned mode)
98 unsigned char buffer[8000];
104 hin = open(from_path, O_RDONLY);
106 perror ("opening input file");
109 hout = yaffs_open(to_path, O_CREAT | O_TRUNC | O_RDWR, 0666);
112 printf("failed to create yaffs file %s\n", to_path);
116 while ((nread = read(hin, buffer, sizeof(buffer))) > 0) {
117 nwritten = yaffs_write(hout, buffer, nread);
119 if (nwritten != nread) {
120 printf("Only wrote %d bytes out of %d\n", nwritten, nread);
126 ret = yaffs_fdatasync(hout);
128 printf("data sytnc failed\n");
132 ret = yaffs_fchmod(hout, mode);
134 printf("chmod failed\n");
138 ret = yaffs_close(hout);
140 printf("close failed\n");
147 static int process_directory(const char *from_dir, const char *to_dir)
152 struct dirent *entry;
154 printf("Processing directory %s into %s\n", from_dir, to_dir);
156 dir = opendir(from_dir);
158 printf("opendir failed on %s", from_dir);
162 while((entry = readdir(dir)) != NULL && error >= 0) {
169 //printf("Got entry %s\n", entry->d_name);
171 /* Ignore . and .. */
172 if(strcmp(entry->d_name, ".") == 0 ||
173 strcmp(entry->d_name, "..") == 0)
176 if (snprintf(from_path, sizeof(from_path),
177 "%s/%s", from_dir,entry->d_name) >= (int)sizeof(from_path)) {
178 printf("path too long for %s/%s\n", from_dir, entry->d_name);
182 if (snprintf(to_path, sizeof(to_path),
183 "%s/%s",to_dir,entry->d_name) >= (int)sizeof(to_path)) {
184 printf("path too long for %s/%s\n",to_dir,entry->d_name);
189 if (lstat(from_path,&stats) < 0)
196 mode = stats.st_mode & 0777;
198 if (S_ISDIR(stats.st_mode)) {
199 printf("Directory create %s, mode %03o\n", to_path, mode);
200 ret = yaffs_mkdir(to_path, mode);
201 printf("Directory create %s, mode %03o : result %d\n",
205 printf("directory creation failed\n");
208 process_directory(from_path, to_path);
209 } else if (S_ISREG(stats.st_mode)) {
210 ret = process_file(from_path, to_path, mode);
211 printf("Copy file %s to %s, mode %03o : result %d\n",
212 from_path, to_path, mode, ret);
214 printf("file copy failed\n");
219 printf("Unhandled object type %d\n", stats.st_mode);
229 int is_all_ff(unsigned char *buffer, int n)
242 * Write the data to output, skipping over the spare bytes.
243 * Stop writing when we get to blank flash.
245 int generate_output_file(const char *working_file, const char *output_file)
247 unsigned char buffer[PAGE_SIZE];
253 inh = open(working_file, O_RDONLY);
254 outh = open(output_file, O_CREAT | O_TRUNC | O_RDWR, 0666);
256 while ((nread = read(inh, buffer, PAGE_SIZE)) > 0) {
257 if (nread != PAGE_SIZE) {
258 printf("working file not properly sized\n");
262 if(is_all_ff(buffer, PAGE_DATA_SIZE)) {
263 printf("End of data found\n");
267 /* Write the data part. */
268 nwritten = write(outh, buffer, PAGE_DATA_SIZE);
270 if (nwritten != PAGE_DATA_SIZE) {
271 printf("short write\n");
275 total_written += nwritten;
277 /* Now if there are OOB tags then write the OOB tags part too */
279 /* Read the oob bytes. In the simulator these are
280 * stored at offset 26 in the 64-byte spare area.
281 * We must therefore copy them from this location to
284 nwritten = write(outh, buffer + PAGE_DATA_SIZE + 26, tags_size);
286 if (nwritten != tags_size) {
287 printf("short write\n");
291 total_written += nwritten;
298 return total_written;
302 int main(int argc, char *argv[])
304 struct yaffs_dev * dev;
307 yaffs_trace_mask = 0;
309 parse_args(argc, argv);
311 if (!input_dir || !output_file || !working_file) {
312 printf("Need input directory , output file and working file\n");
316 printf("Generating image from %s into file %s using working file %s\n",
317 input_dir, output_file, working_file);
318 printf("Output file is in %s endian\n",
319 (endian == 'l') ? "little" : "big");
322 * Determine oob tags_size.
326 else if (no_tags_ecc)
327 tags_size = sizeof(struct yaffs_packed_tags2_tags_only);
329 tags_size = sizeof(struct yaffs_packed_tags2);
331 record_size = PAGE_DATA_SIZE + tags_size;
335 * Create the Yaffs working file using the simulator.
337 unlink(working_file);
338 dev = yaffs_nandsim_install_drv("yroot",
345 printf("Failed to create yaffs working file\n");
350 * Disable checkpointing to create an image without checkpoint data.
352 dev->param.skip_checkpt_rd = 1;
353 dev->param.skip_checkpt_wr = 1;
356 * Set up stored endian: 1 = little endian, 2 = big endian.
359 dev->param.stored_endian = (endian == 'l') ? 1 : 2;
360 dev->param.no_tags_ecc = no_tags_ecc;
363 ret = yaffs_mount("yroot");
365 printf("yaffs_mount returned %d\n", ret);
367 process_directory(input_dir, "yroot");
369 yaffs_unmount("yroot");
371 printf("Generating output file\n");
373 ret = generate_output_file(working_file, output_file);
376 printf("Wrote %d bytes (%d pages of %d bytes each) to output\n",
377 total_written, total_written/record_size, record_size);
379 printf("The image has inband tags.\n");
380 printf("This means it is structured a records of %d bytes per page\n", record_size);
381 printf("This should be written to the data portion of the page\n");
383 printf("The image has out of band tags with%s ECC on the tags\n",
384 no_tags_ecc ? " NO" : "");
385 printf("This means it has %d tags bytes per record to be written in the oob area\n", tags_size);
386 printf("Each record is %d bytes.\n"
387 "The first %d bytes are data for the data datea and\n"
388 "the last %d bytes are tags for the oob (spare) area\n",
389 record_size, PAGE_DATA_SIZE, tags_size);