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 #include <div64.h> 24 25 #include <config.h> 26 #include "nand.h" 27 #include "yaffscfg.h" 28 #include "yaffsfs.h" 29 #include "yaffs_packedtags2.h" 30 #include "yaffs_mtdif.h" 31 #include "yaffs_mtdif2.h" 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 void 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 } 153 154 static int yaffs_regions_overlap(int a, int b, int x, int y) 155 { 156 return (a <= x && x <= b) || 157 (a <= y && y <= b) || 158 (x <= a && a <= y) || 159 (x <= b && b <= y); 160 } 161 162 void cmd_yaffs_devconfig(char *_mp, int flash_dev, 163 int start_block, int end_block) 164 { 165 struct mtd_info *mtd = NULL; 166 struct yaffs_dev *dev = NULL; 167 struct yaffs_dev *chk; 168 char *mp = NULL; 169 struct nand_chip *chip; 170 171 dev = calloc(1, sizeof(*dev)); 172 mp = strdup(_mp); 173 174 mtd = &nand_info[flash_dev]; 175 176 if (!dev || !mp) { 177 /* Alloc error */ 178 printf("Failed to allocate memory\n"); 179 goto err; 180 } 181 182 if (flash_dev >= CONFIG_SYS_MAX_NAND_DEVICE) { 183 printf("Flash device invalid\n"); 184 goto err; 185 } 186 187 if (end_block == 0) 188 end_block = lldiv(mtd->size, mtd->erasesize - 1); 189 190 if (end_block < start_block) { 191 printf("Bad start/end\n"); 192 goto err; 193 } 194 195 chip = mtd->priv; 196 197 /* Check for any conflicts */ 198 yaffs_dev_rewind(); 199 while (1) { 200 chk = yaffs_next_dev(); 201 if (!chk) 202 break; 203 if (strcmp(chk->param.name, mp) == 0) { 204 printf("Mount point name already used\n"); 205 goto err; 206 } 207 if (chk->driver_context == mtd && 208 yaffs_regions_overlap( 209 chk->param.start_block, chk->param.end_block, 210 start_block, end_block)) { 211 printf("Region overlaps with partition %s\n", 212 chk->param.name); 213 goto err; 214 } 215 216 } 217 218 /* Seems sane, so configure */ 219 memset(dev, 0, sizeof(*dev)); 220 dev->param.name = mp; 221 dev->driver_context = mtd; 222 dev->param.start_block = start_block; 223 dev->param.end_block = end_block; 224 dev->param.chunks_per_block = mtd->erasesize / mtd->writesize; 225 dev->param.total_bytes_per_chunk = mtd->writesize; 226 dev->param.is_yaffs2 = 1; 227 dev->param.use_nand_ecc = 1; 228 dev->param.n_reserved_blocks = 5; 229 if (chip->ecc.layout->oobavail < sizeof(struct yaffs_packed_tags2)) 230 dev->param.inband_tags = 1; 231 dev->param.n_caches = 10; 232 dev->param.write_chunk_tags_fn = nandmtd2_write_chunk_tags; 233 dev->param.read_chunk_tags_fn = nandmtd2_read_chunk_tags; 234 dev->param.erase_fn = nandmtd_EraseBlockInNAND; 235 dev->param.initialise_flash_fn = nandmtd_InitialiseNAND; 236 dev->param.bad_block_fn = nandmtd2_MarkNANDBlockBad; 237 dev->param.query_block_fn = nandmtd2_QueryNANDBlock; 238 239 yaffs_add_device(dev); 240 241 printf("Configures yaffs mount %s: dev %d start block %d, end block %d %s\n", 242 mp, flash_dev, start_block, end_block, 243 dev->param.inband_tags ? "using inband tags" : ""); 244 return; 245 246 err: 247 free(dev); 248 free(mp); 249 } 250 251 void cmd_yaffs_dev_ls(void) 252 { 253 struct yaffs_dev *dev; 254 int flash_dev; 255 int free_space; 256 257 yaffs_dev_rewind(); 258 259 while (1) { 260 dev = yaffs_next_dev(); 261 if (!dev) 262 return; 263 flash_dev = 264 ((unsigned) dev->driver_context - (unsigned) nand_info)/ 265 sizeof(nand_info[0]); 266 printf("%-10s %5d 0x%05x 0x%05x %s", 267 dev->param.name, flash_dev, 268 dev->param.start_block, dev->param.end_block, 269 dev->param.inband_tags ? "using inband tags, " : ""); 270 271 free_space = yaffs_freespace(dev->param.name); 272 if (free_space < 0) 273 printf("not mounted\n"); 274 else 275 printf("free 0x%x\n", free_space); 276 277 } 278 } 279 280 void make_a_file(char *yaffsName, char bval, int sizeOfFile) 281 { 282 int outh; 283 int i; 284 unsigned char buffer[100]; 285 286 outh = yaffs_open(yaffsName, 287 O_CREAT | O_RDWR | O_TRUNC, 288 S_IREAD | S_IWRITE); 289 if (outh < 0) { 290 printf("Error opening file: %d. %s\n", outh, yaffs_error_str()); 291 return; 292 } 293 294 memset(buffer, bval, 100); 295 296 do { 297 i = sizeOfFile; 298 if (i > 100) 299 i = 100; 300 sizeOfFile -= i; 301 302 yaffs_write(outh, buffer, i); 303 304 } while (sizeOfFile > 0); 305 306 307 yaffs_close(outh); 308 } 309 310 void read_a_file(char *fn) 311 { 312 int h; 313 int i = 0; 314 unsigned char b; 315 316 h = yaffs_open(fn, O_RDWR, 0); 317 if (h < 0) { 318 printf("File not found\n"); 319 return; 320 } 321 322 while (yaffs_read(h, &b, 1) > 0) { 323 printf("%02x ", b); 324 i++; 325 if (i > 32) { 326 printf("\n"); 327 i = 0;; 328 } 329 } 330 printf("\n"); 331 yaffs_close(h); 332 } 333 334 void cmd_yaffs_mount(char *mp) 335 { 336 int retval = yaffs_mount(mp); 337 if (retval < 0) 338 printf("Error mounting %s, return value: %d, %s\n", mp, 339 yaffsfs_GetError(), yaffs_error_str()); 340 } 341 342 343 void cmd_yaffs_umount(char *mp) 344 { 345 if (yaffs_unmount(mp) == -1) 346 printf("Error umounting %s, return value: %d, %s\n", mp, 347 yaffsfs_GetError(), yaffs_error_str()); 348 } 349 350 void cmd_yaffs_write_file(char *yaffsName, char bval, int sizeOfFile) 351 { 352 make_a_file(yaffsName, bval, sizeOfFile); 353 } 354 355 356 void cmd_yaffs_read_file(char *fn) 357 { 358 read_a_file(fn); 359 } 360 361 362 void cmd_yaffs_mread_file(char *fn, char *addr) 363 { 364 int h; 365 struct yaffs_stat s; 366 367 yaffs_stat(fn, &s); 368 369 printf("Copy %s to 0x%p... ", fn, addr); 370 h = yaffs_open(fn, O_RDWR, 0); 371 if (h < 0) { 372 printf("File not found\n"); 373 return; 374 } 375 376 yaffs_read(h, addr, (int)s.st_size); 377 printf("\t[DONE]\n"); 378 379 yaffs_close(h); 380 } 381 382 383 void cmd_yaffs_mwrite_file(char *fn, char *addr, int size) 384 { 385 int outh; 386 387 outh = yaffs_open(fn, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE); 388 if (outh < 0) 389 printf("Error opening file: %d, %s\n", outh, yaffs_error_str()); 390 391 yaffs_write(outh, addr, size); 392 393 yaffs_close(outh); 394 } 395 396 397 void cmd_yaffs_ls(const char *mountpt, int longlist) 398 { 399 int i; 400 yaffs_DIR *d; 401 struct yaffs_dirent *de; 402 struct yaffs_stat stat; 403 char tempstr[255]; 404 405 d = yaffs_opendir(mountpt); 406 407 if (!d) { 408 printf("opendir failed, %s\n", yaffs_error_str()); 409 return; 410 } 411 412 for (i = 0; (de = yaffs_readdir(d)) != NULL; i++) { 413 if (longlist) { 414 sprintf(tempstr, "%s/%s", mountpt, de->d_name); 415 yaffs_lstat(tempstr, &stat); 416 printf("%-25s\t%7ld", 417 de->d_name, 418 (long)stat.st_size); 419 printf(" %5d %s\n", 420 stat.st_ino, 421 yaffs_file_type_str(&stat)); 422 } else { 423 printf("%s\n", de->d_name); 424 } 425 } 426 427 yaffs_closedir(d); 428 } 429 430 431 void cmd_yaffs_mkdir(const char *dir) 432 { 433 int retval = yaffs_mkdir(dir, 0); 434 435 if (retval < 0) 436 printf("yaffs_mkdir returning error: %d, %s\n", 437 retval, yaffs_error_str()); 438 } 439 440 void cmd_yaffs_rmdir(const char *dir) 441 { 442 int retval = yaffs_rmdir(dir); 443 444 if (retval < 0) 445 printf("yaffs_rmdir returning error: %d, %s\n", 446 retval, yaffs_error_str()); 447 } 448 449 void cmd_yaffs_rm(const char *path) 450 { 451 int retval = yaffs_unlink(path); 452 453 if (retval < 0) 454 printf("yaffs_unlink returning error: %d, %s\n", 455 retval, yaffs_error_str()); 456 } 457 458 void cmd_yaffs_mv(const char *oldPath, const char *newPath) 459 { 460 int retval = yaffs_rename(newPath, oldPath); 461 462 if (retval < 0) 463 printf("yaffs_unlink returning error: %d, %s\n", 464 retval, yaffs_error_str()); 465 } 466