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"
39 * These are the sizes in the simulator file.
41 #define PAGE_DATA_SIZE 2048
42 #define PAGE_SPARE_SIZE 64
43 #define PAGE_SIZE (PAGE_DATA_SIZE + PAGE_SPARE_SIZE)
46 /* Some stub definitions to get building to work. */
47 int simulate_power_failure = 0;
50 static char *input_dir;
51 static char *output_file;
52 static char *working_file;
53 static char endian = 'l';
55 static void usage(const char *prog_name)
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");
64 static void parse_args(int argc, char *argv[])
69 while ((c = getopt(argc, argv, "bi:o:w:h")) != -1) {
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;
82 static int process_file(const char *from_path, const char *to_path, unsigned mode)
86 unsigned char buffer[8000];
92 hin = open(from_path, O_RDONLY);
94 perror ("opening input file");
97 hout = yaffs_open(to_path, O_CREAT | O_TRUNC | O_RDWR, 0666);
100 printf("failed to create yaffs file %s\n", to_path);
104 while ((nread = read(hin, buffer, sizeof(buffer))) > 0) {
105 nwritten = yaffs_write(hout, buffer, nread);
107 if (nwritten != nread) {
108 printf("Only wrote %d bytes out of %d\n", nwritten, nread);
114 ret = yaffs_fdatasync(hout);
116 printf("data sytnc failed\n");
120 ret = yaffs_fchmod(hout, mode);
122 printf("chmod failed\n");
126 ret = yaffs_close(hout);
128 printf("close failed\n");
135 static int process_directory(const char *from_dir, const char *to_dir)
140 struct dirent *entry;
142 printf("Processing directory %s into %s\n", from_dir, to_dir);
144 dir = opendir(from_dir);
146 printf("opendir failed on %s", from_dir);
150 while((entry = readdir(dir)) != NULL && error >= 0) {
157 //printf("Got entry %s\n", entry->d_name);
159 /* Ignore . and .. */
160 if(strcmp(entry->d_name, ".") == 0 ||
161 strcmp(entry->d_name, "..") == 0)
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);
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);
177 if (lstat(from_path,&stats) < 0)
184 mode = stats.st_mode & 0777;
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",
193 printf("directory creation failed\n");
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);
202 printf("file copy failed\n");
207 printf("Unhandled object type %d\n", stats.st_mode);
217 int is_all_ff(unsigned char *buffer, int n)
230 * Write the data to output, skipping over the spare bytes.
231 * Stop writing when we get to blank flash.
233 int generate_output_file(const char *working_file, const char *output_file)
235 unsigned char buffer[PAGE_SIZE];
242 inh = open(working_file, O_RDONLY);
243 outh = open(output_file, O_CREAT | O_TRUNC | O_RDWR, 0666);
245 while ((nread = read(inh, buffer, PAGE_SIZE)) > 0) {
246 if (nread != PAGE_SIZE) {
247 printf("working file not properly sized\n");
251 if(is_all_ff(buffer, PAGE_DATA_SIZE)) {
252 printf("End of data found\n");
256 nwritten = write(outh, buffer, PAGE_DATA_SIZE);
258 if (nwritten != PAGE_DATA_SIZE) {
259 printf("short write\n");
273 int main(int argc, char *argv[])
275 struct yaffs_dev * dev;
278 yaffs_trace_mask = 0;
280 parse_args(argc, argv);
282 if (!input_dir || !output_file || !working_file) {
283 printf("Need input directory , output file and working file\n");
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");
293 * Create the Yaffs working file using the simulator.
295 unlink(working_file);
296 dev = yaffs_nandsim_install_drv("yroot",
303 printf("Failed to create yaffs working file\n");
308 * Disable checkpointing to create an image without checkpoint data.
310 dev->param.skip_checkpt_rd = 1;
311 dev->param.skip_checkpt_wr = 1;
314 * Set up stored endian: 1 = little endian, 2 = big endian.
316 dev->param.stored_endian = (endian == 'l') ? 1 : 2;
318 ret = yaffs_mount("yroot");
320 printf("yaffs_mount returned %d\n", ret);
322 process_directory(input_dir, "yroot");
324 yaffs_unmount("yroot");
326 printf("Generating output file\n");
328 ret = generate_output_file(working_file, output_file);
330 printf("wrote %d bytes to output\n", ret);