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