最新消息:20190717 VPS服务器:Vultr新加坡,WordPress主题:大前端D8,统一介绍入口:关于

【代码】修改后的mkyaffs2image.c,使其生成的makeyaffs2image支持2k/4k/8k pagesize的nand flash

Yaffs2 crifan 1063浏览 0评论

下面是修改后的mkyaffs2image.c,使其生成的makeyaffs2image支持2k/4k/8k pagesize的nand flash:

———————————mkyaffs2image.c的源码———————————-

/*
 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2007 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 * Nick Bane modifications flagged NCB
 * Endian handling patches by James Ng.
 * mkyaffs2image hacks by NCB
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
  
  
/*
 * makeyaffs2image.c
 *
 * Makes a YAFFS2 file system image that can be used to load up a file system.
 * Uses default Linux MTD layout – change if you need something different.
 * Added support for 2k/4k/8k pagesize nand flash by green-waste@163.com
 */
  
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include "yaffs_ecc.h"
#include "yaffs_guts.h"
  
#include "yaffs_tagsvalidity.h"
#include "yaffs_packedtags2.h"
  
unsigned yaffs_traceMask = 0;
  
#define MAX_OBJECTS 10000
  
#define CHUNKSIZE_2K    2048
#define SPARESIZE_64    64
#define CHUNKSIZE_4K    4096
#define SPARESIZE_128   128
#define CHUNKSIZE_8K    8192
#define SPARESIZE_256   256
  
#define MAX_CHUNKSIZE   CHUNKSIZE_8K
#define MAX_SPARESIZE   SPARESIZE_256
  
#define ALL_0xFF_U32 (0xFFFFFFFF)
  
const char * mkyaffsimage_c_version = "$Id: mkyaffs2image.c,v 1.5 2010/01/11 21:43:18 charles Exp $";
  
  
typedef struct
{
    dev_t   dev;
    ino_t   ino;
    int obj;
} objItem;
  
static objItem  obj_list[MAX_OBJECTS];
static int  n_obj   = 0;
static int  obj_id  = YAFFS_NOBJECT_BUCKETS + 1;
  
static int nObjects, nDirectories, nPages;
  
static int outFile;
  
static int error;
  
static int  convert_endian  = 0;    /* default is little endian */
static int  ecc_on_tag  = 1;    /* default is do ECC on packed tags for yaffs2 */
  
static int  chunk_size  = CHUNKSIZE_2K;
static int  spare_size  = SPARESIZE_64;
  
  
/*
 * follow are current use oob(spare) layout in Linux Kernel MTD, nand_base.c:
 * static struct nand_ecclayout nand_oob_64 = {
 * ……
 * .oobfree = {
 * {.offset = 2,
 * .length = 30}}
 * };
 *
 * static struct nand_ecclayout nand_oob_128 = {
 * ……
 * .oobfree = {
 * {.offset = 2,
 * .length = 62}}
 * };
 *
 * that means the oob free for yaffs2 use is from 2~31 for 2K page nand or 2~61 for 4K page nand …
 * and yaffs2 tag is sizeof(yaffs_PackedTags2) = 25 or 16(no tag ecc)
 * is enough for yaffs2 use, and START OFFSET is 2.
 * here just to make sure is correpondding with Linux Kernel
 */
static int yaffs2_tag_start_position_in_spare = 2;
  
#define SWAP32( x ) ( ( ( (x) & 0x000000FF) << 24) |
( ( (x) & 0x0000FF00) << 8) |
( ( (x) & 0x00FF0000) >> 8) |
( ( (x) & 0xFF000000) >> 24) )
  
#define SWAP16( x ) ( ( ( (x) & 0x00FF) << 8) |
( ( (x) & 0xFF00) >> 8) )
  
static int obj_compare( const void *a, const void * b )
{
    objItem *oa, *ob;
  
    oa  = (objItem *) a;
    ob  = (objItem *) b;
  
    if ( oa->dev < ob->dev )
        return(-1);
    if ( oa->dev > ob->dev )
        return(1);
    if ( oa->ino < ob->ino )
        return(-1);
    if ( oa->ino > ob->ino )
        return(1);
  
    return(0);
}
  
  
static void add_obj_to_list( dev_t dev, ino_t ino, int obj )
{
    if ( n_obj < MAX_OBJECTS )
    {
        obj_list[n_obj].dev = dev;
        obj_list[n_obj].ino = ino;
        obj_list[n_obj].obj = obj;
        n_obj++;
        qsort( obj_list, n_obj, sizeof(objItem), obj_compare );
    }else  {
/* oops! not enough space in the object array */
        fprintf( stderr, "Not enough space in object arrayn" );
        exit( 2 );
    }
}
  
  
static int find_obj_in_list( dev_t dev, ino_t ino )
{
    objItem *i = NULL;
    objItem test;
  
    test.dev    = dev;
    test.ino    = ino;
  
    if ( n_obj > 0 )
    {
        i = bsearch( &test, obj_list, n_obj, sizeof(objItem), obj_compare );
    }
  
    if ( i )
    {
        return(i->obj);
    }
    return(-1);
}
  
  
/* This little function converts a little endian tag to a big endian tag.*/
static void little_to_big_endian_yaffs2PackedTagTagsPart( yaffs_PackedTags2TagsPart *tagsPtr )
{
    tagsPtr->sequenceNumber = SWAP32( tagsPtr->sequenceNumber );
    tagsPtr->objectId    = SWAP32( tagsPtr->objectId );
    tagsPtr->chunkId = SWAP32( tagsPtr->chunkId );
    tagsPtr->byteCount   = SWAP32( tagsPtr->byteCount );
}
  
  
static void little_to_big_endian_yaffs2PackedTagECCPart( yaffs_ECCOther *eccPtr )
{
/* colParity is unsigned char, not need swap */
    eccPtr->lineParity   = SWAP32( eccPtr->lineParity );
    eccPtr->lineParityPrime = SWAP32( eccPtr->lineParityPrime );
}
  
  
#if 0
static void yaffs_PackTags2_auto_endian( yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t, int tagsECC, int big_endian )
{
    yaffs_PackTags2TagsPart( &pt->t, t );
  
/*
 * if (big_endian)
 * {
 * little_to_big_endian_yaffs2PackedTagTagsPart(&pt->t);
 * }
 */
  
    if ( tagsECC )
    {
        yaffs_ECCCalculateOther( (unsigned char *) &pt->t,
                     sizeof(yaffs_PackedTags2TagsPart),
                     &pt->ecc );
  
        if ( big_endian )
        {
            little_to_big_endian_yaffs2PackedTagECCPart( &pt->ecc );
        }
    }
}
  
  
#endif
  
static int write_chunk( __u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes )
{
    yaffs_ExtendedTags  t;
    yaffs_PackedTags2   pt;
    int         tag_size = ecc_on_tag ? sizeof(yaffs_PackedTags2) : sizeof(yaffs_PackedTags2TagsPart);
    __u8            spare_buf[MAX_SPARESIZE]; /* max enough */
  
    error = write( outFile, data, chunk_size );
    if ( error < 0 )
        return(error);
  
    yaffs_InitialiseTags( &t );
  
    t.chunkId = chunkId;
/* t.serialNumber = 0; */
  
  
/*CRL: seems not need this,
 * for yaffs2, in yaffs_UnpackTags2TagsPart() will do "t->serialNumber = 0;"
 * and this field is not used for yaffs2 */
/* t.serialNumber = 1; // **CHECK** */
    t.byteCount = nBytes;
    t.objectId  = objId;
  
    t.sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
  
/* added NCB **CHECK** */
  
  
/* CRL: seems that not need this, for in yaffs_UnpackTags2TagsPart(),
 * when found (ptt->sequenceNumber != 0xFFFFFFFF), here has set to YAFFS_LOWEST_SEQUENCE_NUMBER,
 * then will do "t->chunkUsed = 1;" */
/* t.chunkUsed = 1; */
  
    nPages++;
  
/* CRL: add little to big endian if need */
    yaffs_PackTags2( &pt, &t, ecc_on_tag );
    if ( convert_endian )
    {
        little_to_big_endian_yaffs2PackedTagTagsPart( &pt.t );
  
        if ( ecc_on_tag )
        {
            little_to_big_endian_yaffs2PackedTagECCPart( &pt.ecc );
        }
    }
  
/* prepare spare buffer */
    memset( spare_buf, 0xFF, spare_size );
/* copy yaffs2 tag into spare */
    memcpy( spare_buf + yaffs2_tag_start_position_in_spare, &pt, tag_size );
  
    return(write( outFile, spare_buf, spare_size ) );
}
  
  
/* This one is easier, since the types are more standard. No funky shifts here. */
static void yaffs2_object_header_little_to_big_endian( yaffs_ObjectHeader* oh )
{
    oh->type     = SWAP32( oh->type );                   /* GCC makes enums 32 bits. */
    oh->parentObjectId   = SWAP32( oh->parentObjectId );         /* int */
    oh->sum__NoLongerUsed    = SWAP16( oh->sum__NoLongerUsed );      /* __u16 – Not used, but done for completeness. */
/* name = skip. Char array. Not swapped. */
    oh->yst_mode = SWAP32( oh->yst_mode );
#ifdef CONFIG_YAFFS_WINCE                                               /* WinCE doesn’t implement this, but we need to just in case. */
/* In fact, WinCE would be *THE* place where this would be an issue! */
    oh->notForWinCE[0]   = SWAP32( oh->notForWinCE[0] );
    oh->notForWinCE[1]   = SWAP32( oh->notForWinCE[1] );
    oh->notForWinCE[2]   = SWAP32( oh->notForWinCE[2] );
    oh->notForWinCE[3]   = SWAP32( oh->notForWinCE[3] );
    oh->notForWinCE[4]   = SWAP32( oh->notForWinCE[4] );
#else
/* Regular POSIX. */
    oh->yst_uid  = SWAP32( oh->yst_uid );
    oh->yst_gid  = SWAP32( oh->yst_gid );
    oh->yst_atime    = SWAP32( oh->yst_atime );
    oh->yst_mtime    = SWAP32( oh->yst_mtime );
    oh->yst_ctime    = SWAP32( oh->yst_ctime );
#endif
  
    oh->fileSize     = SWAP32( oh->fileSize ); /* Aiee. An int… signed, at that! */
    oh->equivalentObjectId   = SWAP32( oh->equivalentObjectId );
/* alias – char array. */
    oh->yst_rdev = SWAP32( oh->yst_rdev );
  
#ifdef CONFIG_YAFFS_WINCE
    oh->win_ctime[0] = SWAP32( oh->win_ctime[0] );
    oh->win_ctime[1] = SWAP32( oh->win_ctime[1] );
    oh->win_atime[0] = SWAP32( oh->win_atime[0] );
    oh->win_atime[1] = SWAP32( oh->win_atime[1] );
    oh->win_mtime[0] = SWAP32( oh->win_mtime[0] );
    oh->win_mtime[1] = SWAP32( oh->win_mtime[1] );
  
#else   /* no def CONFIG_YAFFS_WINCE */
    oh->roomToGrow[0]    = SWAP32( oh->roomToGrow[0] );
    oh->roomToGrow[1]    = SWAP32( oh->roomToGrow[1] );
    oh->roomToGrow[2]    = SWAP32( oh->roomToGrow[2] );
    oh->roomToGrow[3]    = SWAP32( oh->roomToGrow[3] );
    oh->roomToGrow[4]    = SWAP32( oh->roomToGrow[4] );
    oh->roomToGrow[5]    = SWAP32( oh->roomToGrow[5] );
  
#endif
  
/* CRL: update accord with yaffs_ObjectHeader */
    oh->inbandShadowsObject = SWAP32( oh->inbandShadowsObject );
    oh->inbandIsShrink   = SWAP32( oh->inbandIsShrink );
    oh->reservedSpace[0] = SWAP32( oh->reservedSpace[0] );
    oh->reservedSpace[1] = SWAP32( oh->reservedSpace[1] );
    oh->shadowsObject    = SWAP32( oh->shadowsObject );
    oh->isShrink     = SWAP32( oh->isShrink );
}
  
  
static int write_object_header( int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias )
{
    __u8 bytes[MAX_CHUNKSIZE];
  
    yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *) bytes;
  
    memset( bytes, 0xFF, chunk_size );
  
    oh->type = t;
  
    oh->parentObjectId = parent;
  
    strncpy( oh->name, name, YAFFS_MAX_NAME_LENGTH );
  
    if ( t != YAFFS_OBJECT_TYPE_HARDLINK )
    {
        oh->yst_mode = s->st_mode;
        oh->yst_uid  = s->st_uid;
/* NCB 12/9/02   oh->yst_gid = s->yst_uid; */
        oh->yst_gid  = s->st_gid;
        oh->yst_atime    = s->st_atime;
        oh->yst_mtime    = s->st_mtime;
        oh->yst_ctime    = s->st_ctime;
        oh->yst_rdev = s->st_rdev;
    }
  
    if ( t == YAFFS_OBJECT_TYPE_FILE )
    {
        oh->fileSize = s->st_size;
    }
  
    if ( t == YAFFS_OBJECT_TYPE_HARDLINK )
    {
        oh->equivalentObjectId = equivalentObj;
    }
  
    if ( t == YAFFS_OBJECT_TYPE_SYMLINK )
    {
        strncpy( oh->alias, alias, YAFFS_MAX_ALIAS_LENGTH );
    }
  
    if ( convert_endian )
    {
        yaffs2_object_header_little_to_big_endian( oh );
    }
  
  
/* CRL:
 * chunkid==0 means chunk is object header, not data chunk
 * nBytes==0 here, for byteCount Only valid for data chunks */
    return(write_chunk( bytes, objId, 0, 0 ) );
}
  
  
static int process_directory( int parent, const char *path )
{
    DIR     *dir;
    struct dirent   *entry;
  
    nDirectories++;
  
    dir = opendir( path );
  
    if ( dir )
    {
        while ( (entry = readdir( dir ) ) != NULL )
        {
/* Ignore . and .. */
            if ( strcmp( entry->d_name, "." ) &&
                 strcmp( entry->d_name, ".." ) )
            {
                char        full_name[500];
                struct stat stats;
                int     equivalentObj;
                int     newObj;
  
                sprintf( full_name, "%s/%s", path, entry->d_name );
  
                lstat( full_name, &stats );
  
                if ( S_ISLNK( stats.st_mode ) ||
                     S_ISREG( stats.st_mode ) ||
                     S_ISDIR( stats.st_mode ) ||
                     S_ISFIFO( stats.st_mode ) ||
                     S_ISBLK( stats.st_mode ) ||
                     S_ISCHR( stats.st_mode ) ||
                     S_ISSOCK( stats.st_mode ) )
                {
                    newObj = obj_id++;
                    nObjects++;
  
                    printf( "Object %d, %s is a ", newObj, full_name );
  
/* We’re going to create an object for it */
                    if ( (equivalentObj = find_obj_in_list( stats.st_dev, stats.st_ino ) ) > 0 )
                    {
/* we need to make a hard link */
                        printf( "hard link to object %dn", equivalentObj );
                        error = write_object_header( newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL );
                    }else  {
                        add_obj_to_list( stats.st_dev, stats.st_ino, newObj );
  
                        if ( S_ISLNK( stats.st_mode ) )
                        {
                            char symname[500];
  
                            memset( symname, 0, sizeof(symname) );
  
                            readlink( full_name, symname, sizeof(symname) - 1 );
  
                            printf( "symlink to " % s "n", symname );
                            error = write_object_header( newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname );
                        }else if ( S_ISREG( stats.st_mode ) )
                        {
                            printf( "file, " );
                            error = write_object_header( newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL );
  
                            if ( error >= 0 )
                            {
                                int h;
                                __u8    bytes[MAX_CHUNKSIZE];
                                int nBytes;
                                int chunk = 0;
  
                                h = open( full_name, O_RDONLY );
                                if ( h >= 0 )
                                {
                                    memset( bytes, 0xff, chunk_size );
                                    while ( (nBytes = read( h, bytes, chunk_size ) ) > 0 )
                                    {
                                        chunk++;
                                        write_chunk( bytes, newObj, chunk, nBytes );
                                        memset( bytes, 0xFF, chunk_size );
                                    }
                                    if ( nBytes < 0 )
                                        error = nBytes;
  
                                    printf( "%d data chunks writtenn", chunk );
                                }else  {
                                    perror( "Error opening file.n" );
                                }
                                close( h );
                            }
                        }else if ( S_ISSOCK( stats.st_mode ) )
                        {
                            printf( "socketn" );
                            error = write_object_header( newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL );
                        }else if ( S_ISFIFO( stats.st_mode ) )
                        {
                            printf( "fifon" );
                            error = write_object_header( newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL );
                        }else if ( S_ISCHR( stats.st_mode ) )
                        {
                            printf( "character devicen" );
                            error = write_object_header( newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL );
                        }else if ( S_ISBLK( stats.st_mode ) )
                        {
                            printf( "block devicen" );
                            error = write_object_header( newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL );
                        }else if ( S_ISDIR( stats.st_mode ) )
                        {
                            printf( "directoryn" );
                            error = write_object_header( newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL );
/* NCB modified 10/9/2001     process_directory(1,full_name); */
                            process_directory( newObj, full_name );
                        }
                    }
                }else  {
                    printf( " we don’t handle this typen" );
                }
            }
        }
    }
  
    return(0);
}
  
  
#define STRN_SAME( dst, src )   (0 == strncmp( dst, src, strlen( src ) ) )
#define STR_SAME( dst, src )    (0 == strcmp( dst, src ) )
  
int main( int argc, char *argv[] )
{
    struct stat stats;
  
    printf( "mkyaffs2image: image building tool for YAFFS2 built "__DATE__ " "__TIME__ "n" );
  
    if ( argc < 4 )
    {
        printf( "usage: mkyaffs2image dir image_file chunk_size [notagecc] [convert]n" );
        printf( "           dir        the directory tree to be convertedn" );
        printf( "           image_file the output file to hold the imagen" );
        printf( "           ’2k’ or ’4k’ or ’8k’ (’2048′ or ’4096′ or ’8192′) the chunk(page) sizen" );
        printf( "           ‘notagecc’ disable ecc on tagn" );
        printf( "           ‘convert’ produce a big-endian image from a little-endian machinen" );
        exit( 1 );
    }
  
/* parse chunk (page) and spare size */
    if ( STRN_SAME( argv[3], "2k" ) || STRN_SAME( argv[3], "2048" ) )
    {
        chunk_size  = CHUNKSIZE_2K;
        spare_size  = SPARESIZE_64;
    }else
    if ( STRN_SAME( argv[3], "4k" ) || STRN_SAME( argv[3], "4096" ) )
    {
        chunk_size  = CHUNKSIZE_4K;
        spare_size  = SPARESIZE_128;
    }else
    if ( STRN_SAME( argv[3], "8k" ) || STRN_SAME( argv[3], "8192" ) )
    {
        chunk_size  = CHUNKSIZE_8K;
        spare_size  = SPARESIZE_256;
    }else  {
        printf( "Unrecognized chunk(page) size: %sn", argv[3] );
        exit( 1 );
    }
  
/* parse optitional parameter */
    if ( argc == 5 )
    {
        if ( STRN_SAME( argv[4], "convert" ) )
        {
            convert_endian = 1;
        }else
        if ( STRN_SAME( argv[4], "notagecc" ) )
        {
            ecc_on_tag = 0;
        }else  {
            printf( "Unrecognized parameter: %sn", argv[4] );
            exit( 1 );
        }
    }else
    if ( argc == 6 )
    {
        if ( STRN_SAME( argv[4], "convert" ) )
        {
            convert_endian = 1;
  
            if ( STRN_SAME( argv[5], "notagecc" ) )
            {
                ecc_on_tag = 0;
            }else  {
                printf( "Unrecognized parameter: %sn", argv[5] );
                exit( 1 );
            }
        }else
        if ( STRN_SAME( argv[4], "notagecc" ) )
        {
            ecc_on_tag = 0;
  
            if ( STRN_SAME( argv[5], "convert" ) )
            {
                convert_endian = 1;
            }else  {
                printf( "Unrecognized parameter: %sn", argv[5] );
                exit( 1 );
            }
        }else  {
            printf( "Unrecognized parameter: %sn", argv[4] );
            exit( 1 );
        }
    }
  
    if ( stat( argv[1], &stats ) < 0 )
    {
        printf( "Could not stat %sn", argv[1] );
        exit( 1 );
    }
  
    if ( !S_ISDIR( stats.st_mode ) )
    {
        printf( " %s is not a directoryn", argv[1] );
        exit( 1 );
    }
  
    outFile = open( argv[2], O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE );
  
    if ( outFile < 0 )
    {
        printf( "Could not open output file %sn", argv[2] );
        exit( 1 );
    }
  
    printf( "Processing directory %s into image file %sn", argv[1], argv[2] );
    error = write_object_header( YAFFS_OBJECTID_ROOT, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1, "", -1, NULL );
    if ( error )
        error = process_directory( YAFFS_OBJECTID_ROOT, argv[1] );
  
    close( outFile );
  
    if ( error < 0 )
    {
        perror( "operation incomplete !" );
        exit( 1 );
    }else  {
        printf( "Operation complete.n"
            "%d objects in %d directoriesn"
            "%d NAND pagesn"
            "total chunk size: 0x%xn"
            "total image file size: 0x%xn", nObjects, nDirectories, nPages, chunk_size * nPages, (chunk_size + spare_size) * nPages );
    }
  
    close( outFile );
  
    exit( 0 );
}

转载请注明:在路上 » 【代码】修改后的mkyaffs2image.c,使其生成的makeyaffs2image支持2k/4k/8k pagesize的nand flash

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
63 queries in 0.115 seconds, using 18.65MB memory