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