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