uboot/fs/yaffs2/yaffs_uboot_glue.c
<<
>>
Prefs
   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
  37unsigned yaffs_trace_mask = 0x0; /* Disable logging */
  38static int yaffs_errno;
  39
  40
  41void yaffs_bug_fn(const char *fn, int n)
  42{
  43        printf("yaffs bug at %s:%d\n", fn, n);
  44}
  45
  46void *yaffsfs_malloc(size_t x)
  47{
  48        return malloc(x);
  49}
  50
  51void yaffsfs_free(void *x)
  52{
  53        free(x);
  54}
  55
  56void yaffsfs_SetError(int err)
  57{
  58        yaffs_errno = err;
  59}
  60
  61int yaffsfs_GetLastError(void)
  62{
  63        return yaffs_errno;
  64}
  65
  66
  67int yaffsfs_GetError(void)
  68{
  69        return yaffs_errno;
  70}
  71
  72void yaffsfs_Lock(void)
  73{
  74}
  75
  76void yaffsfs_Unlock(void)
  77{
  78}
  79
  80__u32 yaffsfs_CurrentTime(void)
  81{
  82        return 0;
  83}
  84
  85void *yaffs_malloc(size_t size)
  86{
  87        return malloc(size);
  88}
  89
  90void yaffs_free(void *ptr)
  91{
  92        free(ptr);
  93}
  94
  95void yaffsfs_LocalInitialisation(void)
  96{
  97        /* No locking used */
  98}
  99
 100
 101static 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
 111static 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
 143extern nand_info_t nand_info[];
 144
 145void 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
 153static 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
 161void 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
 245err:
 246        free(dev);
 247        free(mp);
 248}
 249
 250void 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
 279void 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
 309void 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
 333void 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
 342void 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
 349void cmd_yaffs_write_file(char *yaffsName, char bval, int sizeOfFile)
 350{
 351        make_a_file(yaffsName, bval, sizeOfFile);
 352}
 353
 354
 355void cmd_yaffs_read_file(char *fn)
 356{
 357        read_a_file(fn);
 358}
 359
 360
 361void 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
 382void 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
 396void 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
 430void 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
 439void 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
 448void 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
 457void 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