下面是修改后的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 <[email protected]> * 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 [email protected] */ #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