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#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
  38unsigned yaffs_trace_mask = 0x0; /* Disable logging */
  39static int yaffs_errno;
  40
  41
  42void yaffs_bug_fn(const char *fn, int n)
  43{
  44        printf("yaffs bug at %s:%d\n", fn, n);
  45}
  46
  47void *yaffsfs_malloc(size_t x)
  48{
  49        return malloc(x);
  50}
  51
  52void yaffsfs_free(void *x)
  53{
  54        free(x);
  55}
  56
  57void yaffsfs_SetError(int err)
  58{
  59        yaffs_errno = err;
  60}
  61
  62int yaffsfs_GetLastError(void)
  63{
  64        return yaffs_errno;
  65}
  66
  67
  68int yaffsfs_GetError(void)
  69{
  70        return yaffs_errno;
  71}
  72
  73void yaffsfs_Lock(void)
  74{
  75}
  76
  77void yaffsfs_Unlock(void)
  78{
  79}
  80
  81__u32 yaffsfs_CurrentTime(void)
  82{
  83        return 0;
  84}
  85
  86void *yaffs_malloc(size_t size)
  87{
  88        return malloc(size);
  89}
  90
  91void yaffs_free(void *ptr)
  92{
  93        free(ptr);
  94}
  95
  96void yaffsfs_LocalInitialisation(void)
  97{
  98        /* No locking used */
  99}
 100
 101
 102static 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
 112static 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
 144void 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
 152static 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
 160void 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        mtd = get_nand_dev_by_index(flash_dev);
 170        if (!mtd) {
 171                pr_err("\nno NAND devices available\n");
 172                return;
 173        }
 174
 175        dev = calloc(1, sizeof(*dev));
 176        mp = strdup(_mp);
 177
 178        if (!dev || !mp) {
 179                /* Alloc error */
 180                printf("Failed to allocate memory\n");
 181                goto err;
 182        }
 183
 184        if (flash_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
 185                printf("Flash device invalid\n");
 186                goto err;
 187        }
 188
 189        if (end_block == 0)
 190                end_block = lldiv(mtd->size, mtd->erasesize - 1);
 191
 192        if (end_block < start_block) {
 193                printf("Bad start/end\n");
 194                goto err;
 195        }
 196
 197        chip =  mtd_to_nand(mtd);
 198
 199        /* Check for any conflicts */
 200        yaffs_dev_rewind();
 201        while (1) {
 202                chk = yaffs_next_dev();
 203                if (!chk)
 204                        break;
 205                if (strcmp(chk->param.name, mp) == 0) {
 206                        printf("Mount point name already used\n");
 207                        goto err;
 208                }
 209                if (chk->driver_context == mtd &&
 210                        yaffs_regions_overlap(
 211                                chk->param.start_block, chk->param.end_block,
 212                                start_block, end_block)) {
 213                        printf("Region overlaps with partition %s\n",
 214                                chk->param.name);
 215                        goto err;
 216                }
 217
 218        }
 219
 220        /* Seems sane, so configure */
 221        memset(dev, 0, sizeof(*dev));
 222        dev->param.name = mp;
 223        dev->driver_context = mtd;
 224        dev->param.start_block = start_block;
 225        dev->param.end_block = end_block;
 226        dev->param.chunks_per_block = mtd->erasesize / mtd->writesize;
 227        dev->param.total_bytes_per_chunk = mtd->writesize;
 228        dev->param.is_yaffs2 = 1;
 229        dev->param.use_nand_ecc = 1;
 230        dev->param.n_reserved_blocks = 5;
 231        if (chip->ecc.layout->oobavail < sizeof(struct yaffs_packed_tags2))
 232                dev->param.inband_tags = 1;
 233        dev->param.n_caches = 10;
 234        dev->param.write_chunk_tags_fn = nandmtd2_write_chunk_tags;
 235        dev->param.read_chunk_tags_fn = nandmtd2_read_chunk_tags;
 236        dev->param.erase_fn = nandmtd_EraseBlockInNAND;
 237        dev->param.initialise_flash_fn = nandmtd_InitialiseNAND;
 238        dev->param.bad_block_fn = nandmtd2_MarkNANDBlockBad;
 239        dev->param.query_block_fn = nandmtd2_QueryNANDBlock;
 240
 241        yaffs_add_device(dev);
 242
 243        printf("Configures yaffs mount %s: dev %d start block %d, end block %d %s\n",
 244                mp, flash_dev, start_block, end_block,
 245                dev->param.inband_tags ? "using inband tags" : "");
 246        return;
 247
 248err:
 249        free(dev);
 250        free(mp);
 251}
 252
 253void 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                        return;
 265                flash_dev = nand_mtd_to_devnum(dev->driver_context);
 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
 280void 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
 310void 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
 334void 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
 343void 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
 350void cmd_yaffs_write_file(char *yaffsName, char bval, int sizeOfFile)
 351{
 352        make_a_file(yaffsName, bval, sizeOfFile);
 353}
 354
 355
 356void cmd_yaffs_read_file(char *fn)
 357{
 358        read_a_file(fn);
 359}
 360
 361
 362void 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
 383void 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
 397void 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
 431void 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
 440void 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
 449void 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
 458void 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