yaffsfs.c: Fix NULL dereference in yaffs_unmount2_reldev()
[yaffs2.git] / direct / u-boot / fs / yaffs2 / yaffs_uboot_glue.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2018 Aleph One Ltd.
5  *
6  * Created by Charles Manning <charles@aleph1.co.uk>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 /*
14  * yaffscfg.c  The configuration for the "direct" use of yaffs.
15  *
16  * This is set up for u-boot.
17  *
18  * This version now uses the ydevconfig mechanism to set up partitions.
19  */
20
21 #include <common.h>
22
23 #include <config.h>
24 #include "nand.h"
25 #include "yaffscfg.h"
26 #include "yaffsfs.h"
27 #include "yaffs_packedtags2.h"
28 #include "yaffs_mtdif.h"
29 #include "yaffs_mtdif2.h"
30 #include "yaffs_uboot_glue.h"
31
32 #if 0
33 #include <errno.h>
34 #else
35 #include "malloc.h"
36 #endif
37
38 unsigned yaffs_trace_mask = 0x0; /* Disable logging */
39 static int yaffs_errno;
40
41
42 void yaffs_bug_fn(const char *fn, int n)
43 {
44         printf("yaffs bug at %s:%d\n", fn, n);
45 }
46
47 void *yaffsfs_malloc(size_t x)
48 {
49         return malloc(x);
50 }
51
52 void yaffsfs_free(void *x)
53 {
54         free(x);
55 }
56
57 void yaffsfs_SetError(int err)
58 {
59         yaffs_errno = err;
60 }
61
62 int yaffsfs_GetLastError(void)
63 {
64         return yaffs_errno;
65 }
66
67
68 int yaffsfs_GetError(void)
69 {
70         return yaffs_errno;
71 }
72
73 void yaffsfs_Lock(void)
74 {
75 }
76
77 void yaffsfs_Unlock(void)
78 {
79 }
80
81 __u32 yaffsfs_CurrentTime(void)
82 {
83         return 0;
84 }
85
86 void *yaffs_malloc(size_t size)
87 {
88         return malloc(size);
89 }
90
91 void yaffs_free(void *ptr)
92 {
93         free(ptr);
94 }
95
96 void yaffsfs_LocalInitialisation(void)
97 {
98         /* No locking used */
99 }
100
101
102 static const char *yaffs_file_type_str(struct yaffs_stat *stat)
103 {
104         switch (stat->st_mode & S_IFMT) {
105         case S_IFREG: return "regular file";
106         case S_IFDIR: return "directory";
107         case S_IFLNK: return "symlink";
108         default: return "unknown";
109         }
110 }
111
112 static const char *yaffs_error_str(void)
113 {
114         int error = yaffsfs_GetLastError();
115
116         if (error < 0)
117                 error = -error;
118
119         switch (error) {
120         case EBUSY: return "Busy";
121         case ENODEV: return "No such device";
122         case EINVAL: return "Invalid parameter";
123         case ENFILE: return "Too many open files";
124         case EBADF:  return "Bad handle";
125         case EACCES: return "Wrong permissions";
126         case EXDEV:  return "Not on same device";
127         case ENOENT: return "No such entry";
128         case ENOSPC: return "Device full";
129         case EROFS:  return "Read only file system";
130         case ERANGE: return "Range error";
131         case ENOTEMPTY: return "Not empty";
132         case ENAMETOOLONG: return "Name too long";
133         case ENOMEM: return "Out of memory";
134         case EFAULT: return "Fault";
135         case EEXIST: return "Name exists";
136         case ENOTDIR: return "Not a directory";
137         case EISDIR: return "Not permitted on a directory";
138         case ELOOP:  return "Symlink loop";
139         case 0: return "No error";
140         default: return "Unknown error";
141         }
142 }
143
144 extern nand_info_t nand_info[];
145
146 int cmd_yaffs_tracemask(unsigned set, unsigned mask)
147 {
148         if (set)
149                 yaffs_trace_mask = mask;
150
151         printf("yaffs trace mask: %08x\n", yaffs_trace_mask);
152         return 0;
153 }
154
155 static int yaffs_regions_overlap(int a, int b, int x, int y)
156 {
157         return  (a <= x && x <= b) ||
158                 (a <= y && y <= b) ||
159                 (x <= a && a <= y) ||
160                 (x <= b && b <= y);
161 }
162
163 int cmd_yaffs_devconfig(char *_mp, int flash_dev,
164                         int start_block, int end_block)
165 {
166         struct mtd_info *mtd = NULL;
167         struct yaffs_dev *dev = NULL;
168         struct yaffs_dev *chk;
169         char *mp = NULL;
170         struct nand_chip *chip;
171
172         dev = calloc(1, sizeof(*dev));
173         mp = strdup(_mp);
174
175         mtd = &nand_info[flash_dev];
176
177         if (!dev || !mp) {
178                 /* Alloc error */
179                 printf("Failed to allocate memory\n");
180                 goto err;
181         }
182
183         if (flash_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
184                 printf("Flash device invalid\n");
185                 goto err;
186         }
187
188         if (end_block == 0)
189                 end_block = mtd->size / mtd->erasesize - 1;
190
191         if (end_block < start_block) {
192                 printf("Bad start/end\n");
193                 goto err;
194         }
195
196         chip =  mtd->priv;
197
198         /* Check for any conflicts */
199         yaffs_dev_rewind();
200         while (1) {
201                 chk = yaffs_next_dev();
202                 if (!chk)
203                         break;
204                 if (strcmp(chk->param.name, mp) == 0) {
205                         printf("Mount point name already used\n");
206                         goto err;
207                 }
208                 if (chk->driver_context == mtd &&
209                         yaffs_regions_overlap(
210                                 chk->param.start_block, chk->param.end_block,
211                                 start_block, end_block)) {
212                         printf("Region overlaps with partition %s\n",
213                                 chk->param.name);
214                         goto err;
215                 }
216
217         }
218
219         /* Seems sane, so configure */
220         memset(dev, 0, sizeof(*dev));
221         dev->param.name = mp;
222         dev->driver_context = mtd;
223         dev->param.start_block = start_block;
224         dev->param.end_block = end_block;
225         dev->param.chunks_per_block = mtd->erasesize / mtd->writesize;
226         dev->param.total_bytes_per_chunk = mtd->writesize;
227         dev->param.is_yaffs2 = 1;
228         dev->param.use_nand_ecc = 1;
229         dev->param.n_reserved_blocks = 5;
230         if (chip->ecc.layout->oobavail < sizeof(struct yaffs_packed_tags2))
231                 dev->param.inband_tags = 1;
232         dev->param.n_caches = 10;
233         dev->param.write_chunk_tags_fn = nandmtd2_write_chunk_tags;
234         dev->param.read_chunk_tags_fn = nandmtd2_read_chunk_tags;
235         dev->param.erase_fn = nandmtd_EraseBlockInNAND;
236         dev->param.initialise_flash_fn = nandmtd_InitialiseNAND;
237         dev->param.bad_block_fn = nandmtd2_MarkNANDBlockBad;
238         dev->param.query_block_fn = nandmtd2_QueryNANDBlock;
239
240         yaffs_add_device(dev);
241
242         printf("Configures yaffs mount %s: dev %d start block %d, end block %d %s\n",
243                 mp, flash_dev, start_block, end_block,
244                 dev->param.inband_tags ? "using inband tags" : "");
245         return 0;
246
247 err:
248         free(dev);
249         free(mp);
250         return -1;
251 }
252
253 int cmd_yaffs_dev_ls(void)
254 {
255         struct yaffs_dev *dev;
256         int flash_dev;
257         int free_space;
258
259         yaffs_dev_rewind();
260
261         while (1) {
262                 dev = yaffs_next_dev();
263                 if (!dev)
264                         break;
265                 flash_dev =
266                         ((unsigned) dev->driver_context - (unsigned) nand_info)/
267                                 sizeof(nand_info[0]);
268                 printf("%-10s %5d 0x%05x 0x%05x %s",
269                         dev->param.name, flash_dev,
270                         dev->param.start_block, dev->param.end_block,
271                         dev->param.inband_tags ? "using inband tags, " : "");
272
273                 free_space = yaffs_freespace(dev->param.name);
274                 if (free_space < 0)
275                         printf("not mounted\n");
276                 else
277                         printf("free 0x%x\n", free_space);
278
279         }
280
281         return 0;
282 }
283
284 int make_a_file(char *yaffsName, char bval, int sizeOfFile)
285 {
286         int outh;
287         int i;
288         int written;
289         unsigned char buffer[100];
290
291         outh = yaffs_open(yaffsName,
292                                 O_CREAT | O_RDWR | O_TRUNC,
293                                 S_IREAD | S_IWRITE);
294         if (outh < 0) {
295                 printf("Error opening file: %d. %s\n", outh, yaffs_error_str());
296                 return -1;
297         }
298
299         memset(buffer, bval, 100);
300
301         written = 0;
302         while (written < sizeOfFile) {
303                 i = sizeOfFile - written;
304                 if (i > 100)
305                         i = 100;
306
307                 if (yaffs_write(outh, buffer, i) != i)
308                         break;
309                 written += i;
310         }
311
312         yaffs_close(outh);
313
314         return (written == sizeOfFile) ? 0 : -1;
315 }
316
317 int read_a_file(char *fn)
318 {
319         int h;
320         int i = 0;
321         unsigned char b;
322
323         h = yaffs_open(fn, O_RDWR, 0);
324         if (h < 0) {
325                 printf("File not found\n");
326                 return -1;
327         }
328
329         while (yaffs_read(h, &b, 1) > 0) {
330                 printf("%02x ", b);
331                 i++;
332                 if (i > 32) {
333                         printf("\n");
334                         i = 0;;
335                 }
336         }
337         printf("\n");
338         yaffs_close(h);
339
340         return 0;
341 }
342
343 int cmd_yaffs_mount(char *mp)
344 {
345         int retval = yaffs_mount(mp);
346         if (retval < 0)
347                 printf("Error mounting %s, return value: %d, %s\n", mp,
348                         yaffsfs_GetError(), yaffs_error_str());
349         return retval;
350 }
351
352
353 int cmd_yaffs_umount(char *mp)
354 {
355         int retval = yaffs_unmount(mp);
356
357         if (retval < 0)
358                 printf("Error umounting %s, return value: %d, %s\n", mp,
359                         yaffsfs_GetError(), yaffs_error_str());
360         return retval;
361 }
362
363 int cmd_yaffs_write_file(char *yaffsName, char bval, int sizeOfFile)
364 {
365         return make_a_file(yaffsName, bval, sizeOfFile);
366 }
367
368
369 int cmd_yaffs_read_file(char *fn)
370 {
371         return read_a_file(fn);
372 }
373
374
375 int cmd_yaffs_mread_file(char *fn, char *addr)
376 {
377         int h;
378         int retval = 0;
379         struct yaffs_stat s;
380         int read_size;
381         char buf[16];
382
383         yaffs_stat(fn, &s);
384
385         printf("Copy %s to 0x%p... ", fn, addr);
386         h = yaffs_open(fn, O_RDWR, 0);
387         if (h < 0) {
388                 printf("File not found\n");
389                 retval = -1;
390                 read_size = 0;
391         } else {
392                 read_size = (int) s.st_size;
393                 yaffs_read(h, addr, read_size);
394                 printf("\t[DONE]\n");
395
396                 yaffs_close(h);
397         }
398         sprintf(buf,"%x", read_size);
399         setenv("filesize", buf);
400
401         return retval;
402 }
403
404
405 int cmd_yaffs_mwrite_file(char *fn, char *addr, int size)
406 {
407         int outh;
408         int wrote;
409
410         outh = yaffs_open(fn, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE);
411         if (outh < 0) {
412                 printf("Error opening file: %d, %s\n", outh, yaffs_error_str());
413                 return -1;
414         }
415
416         wrote = yaffs_write(outh, addr, size);
417         yaffs_close(outh);
418
419         if(wrote != size) {
420                 printf("only wrote %d (0x%x) bytes\n", wrote, wrote);
421                 return -1;
422         }
423         return 0;
424
425
426 }
427
428
429 int cmd_yaffs_ls(const char *mountpt, int longlist)
430 {
431         int i;
432         yaffs_DIR *d;
433         struct yaffs_dirent *de;
434         struct yaffs_stat stat;
435         char tempstr[255];
436
437         d = yaffs_opendir(mountpt);
438
439         if (!d) {
440                 printf("opendir failed, %s\n", yaffs_error_str());
441                 return -1;
442         }
443
444         for (i = 0; (de = yaffs_readdir(d)) != NULL; i++) {
445                 if (longlist) {
446                         sprintf(tempstr, "%s/%s", mountpt, de->d_name);
447                         yaffs_lstat(tempstr, &stat);
448                         printf("%-25s\t%7ld",
449                                         de->d_name,
450                                         (long)stat.st_size);
451                         printf(" %5d %s\n",
452                                         stat.st_ino,
453                                         yaffs_file_type_str(&stat));
454                 } else {
455                         printf("%s\n", de->d_name);
456                 }
457         }
458
459         yaffs_closedir(d);
460
461         return 0;
462 }
463
464 int cmd_yaffs_check(const char *fname, const char *type)
465 {
466         int retval = 0;
467         int ret;
468         struct yaffs_stat stat;
469
470         ret = yaffs_stat(fname, &stat);
471         if (ret < 0) {
472                 printf("%s not found\n", fname);
473                 return -1;
474         }
475
476         printf("%s is a %s\n", fname, yaffs_file_type_str(&stat));
477
478         if (strcmp(type, "REG") == 0 &&
479             (stat.st_mode & S_IFMT) != S_IFREG)
480                 retval = -1;
481
482         if (strcmp(type, "DIR") == 0 &&
483             (stat.st_mode & S_IFMT) != S_IFDIR)
484                 retval = -1;
485
486         if (retval == 0)
487                 printf("check ok\n");
488         else
489                 printf("check failed\n");
490
491         return retval;
492 }
493
494
495 int cmd_yaffs_mkdir(const char *dir)
496 {
497         int retval = yaffs_mkdir(dir, 0);
498
499         if (retval < 0) {
500                 printf("yaffs_mkdir returning error: %d, %s\n",
501                         retval, yaffs_error_str());
502                 return -1;
503         }
504         return 0;
505 }
506
507 int cmd_yaffs_rmdir(const char *dir)
508 {
509         int retval = yaffs_rmdir(dir);
510
511         if (retval < 0) {
512                 printf("yaffs_rmdir returning error: %d, %s\n",
513                         retval, yaffs_error_str());
514                 return -1;
515         }
516         return 0;
517 }
518
519 int cmd_yaffs_rm(const char *path)
520 {
521         int retval = yaffs_unlink(path);
522
523         if (retval < 0) {
524                 printf("yaffs_unlink returning error: %d, %s\n",
525                         retval, yaffs_error_str());
526                 return -1;
527         }
528
529         return 0;
530 }
531
532 int cmd_yaffs_mv(const char *oldPath, const char *newPath)
533 {
534         int retval = yaffs_rename(newPath, oldPath);
535
536         if (retval < 0) {
537                 printf("yaffs_unlink returning error: %d, %s\n",
538                         retval, yaffs_error_str());
539                 return -1;
540         }
541
542         return 0;
543 }