write yaffs2 image to nand for dm365

我们知道, dm365的rbl 对 nand flash的支持比较特别,和uboot以及内核的不相同,需要打补丁,因此导致写oob的fs需要特别的操作,

特别是针对硬件开启ecc的内核和uboot(本人就是)

起初,不管怎么改nandwrite 和mkyaffs2image(这个东东很难下载到!!本人实在是无奈,从官网下载到了,和邮件列表上回复的时间一致的版本,方便打补丁嘛微笑

分析oob

通过挂载yaffs2,拷贝写文件:

/home/workspace/mtd-utils # ./nanddump -p -c /dev/mtd6 -o -l 0x4000 | grep OOB
ECC failed: 2
ECC corrected: 0
Number of bad blocks: 0
Number of bbt blocks: 0
Block size 131072, page size 2048, OOB size 64
Dumping data starting at 0x00000000 and ending at 0x00004000...
  OOB Data: ff ff 01 10 00 00 00 d6 ff b8 a5 4f 55 4a 79 c6  |...........OUJy.|
  OOB Data: 01 01 00 10 01 00 3f 27 56 f5 29 d8 61 d9 9d 14  |......?'V.).a...|
  OOB Data: 00 80 00 00 00 00 3f 27 56 f5 29 d8 61 d9 9d 14  |......?'V.).a...|
  OOB Data: ff ff ff ff ff ff 3f 27 56 f5 29 d8 61 d9 9d 14  |......?'V.).a...|
 
  OOB Data: ff ff 01 10 00 00 e3 be ad b3 1f b8 df de b5 d4  |................|
  OOB Data: 01 01 00 00 01 00 63 58 90 20 16 23 79 d2 b2 a5  |......cX. .#y...|
  OOB Data: 00 00 00 08 00 00 e7 be fd cd 34 fd e6 6a 5f 55  |..........4..j_U|
  OOB Data: ff ff ff ff ff ff 6d 5a a2 64 2c b8 b8 6c 50 81  |......mZ.d,..lP.|
 
  OOB Data: ff ff 01 10 00 00 7c 98 83 d7 69 ed f0 d8 25 3e  |......|...i...%>|
  OOB Data: 01 01 00 00 02 00 cb 2e c2 1a 8c 39 a8 b3 93 3c  |...........9...<|
  OOB Data: 00 00 00 08 00 00 04 84 5e 96 5b a9 c0 af a0 78  |........^.[....x|
  OOB Data: ff ff ff ff ff ff 1a 16 4f ca c1 36 49 a4 d5 50  |........O..6I..P|
 
  OOB Data: ff ff 01 10 00 00 45 b1 36 ab f9 83 fe 3d 0f 8e  |......E.6....=..|
  OOB Data: 01 01 00 00 03 00 b8 40 34 87 ff 54 7b ce 45 0c  |.......@4..T{.E.|
  OOB Data: 00 00 00 08 00 00 30 87 c4 0b 5c 41 ef d4 21 3b  |......0...\A..!;|
  OOB Data: ff ff ff ff ff ff 4e 5e f8 75 1b 2a 29 60 a5 89  |......N^.u.*)`..|
 
  OOB Data: ff ff 01 10 00 00 ff 4d 0a 6a fe 20 12 00 85 04  |.......M.j. ....|
  OOB Data: 01 01 00 00 04 00 f5 5a 55 3a b7 86 a6 e7 b3 46  |.......ZU:.....F|
  OOB Data: 00 00 00 08 00 00 77 03 0a 74 4b 3f 81 93 d7 54  |......w..tK?...T|
  OOB Data: ff ff ff ff ff ff 98 ae cb e4 67 fd 4d b9 da dc  |..........g.M...|
 
  OOB Data: ff ff 01 10 00 00 1c 19 b8 03 e7 c9 51 68 bb 52  |............Qh.R|
  OOB Data: 01 01 00 00 05 00 60 59 3f 05 08 eb 91 17 5f 28  |......`Y?....._(|
  OOB Data: 00 00 00 08 00 00 ad e8 f7 68 31 66 4b 7a 7e 5f  |.........h1fKz~_|
  OOB Data: ff ff ff ff ff ff 74 98 c2 25 c0 75 e8 87 35 e2  |......t..%.u..5.|
 
  OOB Data: ff ff 01 10 00 00 2e 18 22 c4 cb c7 a9 3c 83 58  |........"....<.X|
  OOB Data: 01 01 00 00 06 00 50 b3 cc 30 1b fb b2 6a d6 97  |......P..0...j..|
  OOB Data: 00 00 00 08 00 00 cc 80 ad 26 be d7 db dc cd ad  |.........&......|
  OOB Data: ff ff ff ff ff ff 9c 3e 19 bb 2c 73 98 5b d0 ad  |.......>..,s.[..|
 
  OOB Data: ff ff 01 10 00 00 19 66 ef 08 ec 46 8b f5 ed 83  |.......f...F....|
  OOB Data: 01 01 00 00 07 00 37 4c 4b 20 4d b3 6d f2 72 07  |......7LK M.m.r.|
  OOB Data: 00 00 00 08 00 00 84 06 52 e5 68 22 56 07 7f aa  |........R.h"V...|
  OOB Data: ff ff ff ff ff ff 33 7e 50 33 d4 1f 73 f0 3a 9f  |......3~P3..s.:.|
 
 
 对比分析:OOB 0-1 未使用(为FF)
           OOB
           OOB     
           OOB 0-5 未使用(为FF)
 OOB 中未使用部分 2+6 = 8bytes,使用部分 24 - 8 = 16 bytes
 
 (参见dm365 中ecc的部分分析)
 

分析工具mkyaffs2image:

mkyaffs2image.c中写oob部分:
 
typedef struct {
 yaffs_PackedTags2TagsPart t;
 yaffs_ECCOther ecc;
}yaffs_PackedTags2;

typedef struct {
 unsigned sequenceNumber;
 unsigned objectId;
 unsigned chunkId;
 unsigned byteCount;
} yaffs_PackedTags2TagsPart;

yaffs_PackedTags2TagsPart 大小为 4×4=16 bytes
yaffs_ECCOther 不需要写入,因为内核自己做 hw ecc(硬件ECC).

和上面一致.修改部分:下载,打补丁用法

 

(注意http://www.aleph1.co.uk/gitweb?p=yaffs2.git;a=shortlog;pg=5这里的shortlog 需要接近于补丁的时间:

Author:  Vu Tran
Date:  2007-09-12 22:00   +800
To:  yaffs
Subject: [Yaffs] Fix for mkyaffs2image utility

此处,选中,某个时间段,点击snapshot即可。由于我们只只适用里面的utils,因此版本估计影响不大)

 

打过补丁后,另外需要修改(应该不修改也没关系?)

memcpy(&(oobData[oob_tags_pos]),&pt,sizeof(yaffs_PackedTags2));

memcpy(&(oobData[oob_tags_pos]),&pt, 16);//注意我们只写16字节。

 

注意此补丁的作者(见patch  address url) 建议使用下面的参数 来烧写img

./nandwrite -a -o -q /dev/mtd6  img/config.img

 

编译mtd-utils

此工具真的很难整。。

 

下载需要的依赖 

zlib-1.2.5.tar.gz lzo-2.03.tar.gz  uuid-1.6.2.tar.gz 

解压

cd /opt/utils/uuid-1.6.2
./configure --host=arm-linux prefix=/opt/utils/uuid-1.6.2/build CC=arm-none-linux-gnueabi-gcc ac_cv_va_copy=no
make && make install


cd  /opt/utils/lzo-2.03
CC=arm-none-linux-gnueabi-gcc ./configure --host=arm-linux --prefix=/opt/utils/lzo-2.03/build
make && make install

 

cd zlib-1.2.5

 prefix=./build CC=arm-none-linux-gnueabi-gcc ./configure  

 make && make install

 

注解 makefile中的 BINS += mkfs.ubifs/mkfs.ubifs ,不然这个工具编译报错(主要是有2个函数调用链接报错)。。如果有人知道怎么修改。。请告知。

修改Makefile ,在 VERSION = 1.4.5下面(开头)添加

#################
#mike add for ti 3515

CROSS := arm-none-linux-gnueabi-
#bug !
BUILDDIR := $(CURDIR)

ZLIB_DIR := /opt/utils/zlib-1.2.5/build
LZO_DIR := /opt/utils/lzo-2.03/build
UUID_DIR := /opt/utils/uuid-1.6.2/build

DESTDIR := /opt/utils/mtd-utils/build

#addend

修改

LDLIBS += -L$(ZLIB_DIR)/lib -L$(LZO_DIR)/lib -L$(UUID_DIR)/lib

添加库路径

然后编译

cd /opt/utils/mtd-utils
make WITHOUT_XATTR=1

如出错,请修改Makefile以链接进正确的库

最后拷贝nandwrite nanddump mtd_debug 和

libuuid.so          libuuid.so.16       libuuid.so.16.0.22

到目标板,添加库路径

export LD_LIBRARY_PATH=/home/workspace/mtd-utils/lib:$LD_LIBRARY_PATH

即可运行这些工具。

 

针对DM365的补丁

 

继续修改(上述补丁只适合于未打补丁的内核,不针对打过补丁的内核(使用于dm365)):
 

 注解关于 MEMSETOOBSEL 、 MEMGETOOBSEL 的ioctl 调用

(不适用于新版本内核。或者说在本人系统上会报错抓狂 。。。本人内核版本2.6.32.17)

修改写OOB部分的代码:注解部分

   if (!noecc) {
    int i, start, len;
    int tags_pos = 0;
    /*
     * We use autoplacement and have the oobinfo with the autoplacement
     * information from the kernel available
     *
     * Modified to support out of order oobfree segments,
     * such as the layout used by diskonchip.c
     */
//     if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) {
//      for (i = 0; old_oobinfo.oobfree[i][1]; i++) {
//       /* Set the reserved bytes to 0xff */
//       start = old_oobinfo.oobfree[i][0];
//       len = old_oobinfo.oobfree[i][1];
//       if (rawoob)
//        memcpy(oobbuf + start,
//          oobreadbuf + start, len);
//       else
//        memcpy(oobbuf + start,
//          oobreadbuf + tags_pos, len);
//       tags_pos += len;
//      }
//     } else {
//      /* Set at least the ecc byte positions to 0xff */
//      start = old_oobinfo.eccbytes;
//      len = mtd.oob_size - start;
//      memcpy(oobbuf + start,
//        oobreadbuf + start,
//        len);
//     }

///新添加部分,见前面的分析

    memcpy(oobbuf + 2, oobreadbuf, 4);
    memcpy(oobbuf + 16, oobreadbuf+4, 6);
    memcpy(oobbuf + 32, oobreadbuf+10, 6); 
   }

yaffs oob 也要修改

static struct nand_oobinfo yaffs_oobinfo = {
 .useecc = MTD_NANDECC_PLACE,
// .eccbytes = 6,
// .eccpos = { 8, 9, 10, 13, 14, 15}

  .eccbytes = 40,
    .eccpos = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
               22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
               38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
               54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
   },
};

 

main 函数的oob也要修改

int main(int argc, char * const argv[])
{

//...

 struct nand_oobinfo old_oobinfo =
 {
  .oobfree = {{2, 4}, {16, 6}, {32, 6}, {48, 6}},
 };

 

 

修改后的

utils\mtd-utils\nandwrite.c

[code=cpp]
/*
 *  nandwrite.c
 *
 *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
 *		  2003 Thomas Gleixner (tglx@linutronix.de)
 *
 * 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.
 *
 * Overview:
 *   This utility writes a binary image directly to a NAND flash
 *   chip or NAND chips contained in DoC devices. This is the
 *   "inverse operation" of nanddump.
 *
 * tglx: Major rewrite to handle bad blocks, write data with or without ECC
 *	 write oob data only on request
 *
 * Bug/ToDo:
 */

#define PROGRAM_NAME "nandwrite"

#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <getopt.h>

#include <asm/types.h>
#include "mtd/mtd-user.h"
#include "common.h"
#include <libmtd.h>

#if 0
// oob layouts to pass into the kernel as default
static struct nand_oobinfo none_oobinfo = {
	.useecc = MTD_NANDECC_OFF,
};

static struct nand_oobinfo jffs2_oobinfo = {
	.useecc = MTD_NANDECC_PLACE,
	.eccbytes = 6,
	.eccpos = { 0, 1, 2, 3, 6, 7 }
};

static struct nand_oobinfo yaffs_oobinfo = {
	.useecc = MTD_NANDECC_PLACE,
//	.eccbytes = 6,
//	.eccpos = { 8, 9, 10, 13, 14, 15}

 	.eccbytes = 40,
    .eccpos = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
               22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
               38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
               54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
			},
};

static struct nand_oobinfo autoplace_oobinfo = {
	.useecc = MTD_NANDECC_AUTOPLACE
};
#endif

static void display_help(void)
{
	printf(
"Usage: nandwrite [OPTION] MTD_DEVICE [INPUTFILE|-]\n"
"Writes to the specified MTD device.\n"
"\n"
//"  -a, --autoplace         Use auto oob layout\n"
//"  -j, --jffs2             Force jffs2 oob layout (legacy support)\n"
//"  -y, --yaffs             Force yaffs oob layout (legacy support)\n"
"  -f, --forcelegacy       Force legacy support on autoplacement-enabled mtd\n"
"                          device\n"
"  -m, --markbad           Mark blocks bad if write fails\n"
//"  -n, --noecc             Write without ecc\n"
"  -N, --noskipbad         Write without bad block skipping\n"
"  -o, --oob               Image contains oob data\n"
"  -O, --onlyoob           Image contains oob data and only write the oob part\n"
"  -r, --raw               Image contains the raw oob data dumped by nanddump\n"
"  -s addr, --start=addr   Set start address (default is 0)\n"
"  -p, --pad               Pad to page size\n"
"  -b, --blockalign=1|2|4  Set multiple of eraseblocks to align to\n"
"  -v, --verbose           Display progress messages\n"
"      --help              Display this help and exit\n"
"      --version           Output version information and exit\n"
	);
	exit(EXIT_SUCCESS);
}

static void display_version(void)
{
	fprintf(stderr, "writing YAFFS2 image specially for dm365,version :"__DATE__"\n");	
	printf("%1$s " VERSION "\n"
			"\n"
			"Copyright (C) 2003 Thomas Gleixner \n"
			"\n"
			"%1$s comes with NO WARRANTY\n"
			"to the extent permitted by law.\n"
			"\n"
			"You may redistribute copies of %1$s\n"
			"under the terms of the GNU General Public Licence.\n"
			"See the file `COPYING' for more information.\n",
			PROGRAM_NAME);
	exit(EXIT_SUCCESS);
}

static const char	*standard_input = "-";
static const char	*mtd_device, *img;
static long long	mtdoffset = 0;
static bool		quiet = true;
static bool		writeoob = false;
static bool		rawoob = false;
static bool		onlyoob = false;
//static bool		autoplace = false;
static bool		markbad = false;
//static bool		forcejffs2 = false;
//static bool		forceyaffs = false;
static bool		forcelegacy = false;
//static bool		noecc = false;
static bool		noskipbad = false;
static bool		pad = false;
static int		blockalign = 1; /* default to using actual block size */

static void process_options(int argc, char * const argv[])
{
	int error = 0;

	for (;;) {
		int option_index = 0;
		static const char *short_options = "ab:fjmnNoOpqrs:y";
		static const struct option long_options[] = {
			{"help", no_argument, 0, 0},
			{"version", no_argument, 0, 0},
//			{"autoplace", no_argument, 0, 'a'},
			{"blockalign", required_argument, 0, 'b'},
			{"forcelegacy", no_argument, 0, 'f'},
//			{"jffs2", no_argument, 0, 'j'},
			{"markbad", no_argument, 0, 'm'},
//			{"noecc", no_argument, 0, 'n'},
			{"noskipbad", no_argument, 0, 'N'},
			{"oob", no_argument, 0, 'o'},
			{"onlyoob", no_argument, 0, 'O'},
			{"pad", no_argument, 0, 'p'},
			{"verbose", no_argument, 0, 'v'},
			{"raw", no_argument, 0, 'r'},
			{"start", required_argument, 0, 's'},
//			{"yaffs", no_argument, 0, 'y'},
			{0, 0, 0, 0},
		};

		int c = getopt_long(argc, argv, short_options,
				long_options, &option_index);
		if (c == EOF) {
			break;
		}

		switch (c) {
			case 0:
				switch (option_index) {
					case 0:
						display_help();
						break;
					case 1:
						display_version();
						break;
				}
				break;
			case 'v':
				quiet = false;
				break;
//			case 'a':
//				autoplace = true;
//				break;
//			case 'j':
//				forcejffs2 = true;
//				break;
//			case 'y':
//				forceyaffs = true;
//				break;
			case 'f':
				forcelegacy = true;
				break;
//			case 'n':
//				noecc = true;
//				break;
			case 'N':
				noskipbad = true;
				break;
			case 'm':
				markbad = true;
				break;
			case 'o':
				writeoob = true;
				break;
			case 'O':
				writeoob = true;
				onlyoob = true;
				break;
			case 'p':
				pad = true;
				break;
			case 'r':
				rawoob = true;
				writeoob = true;
				break;
			case 's':
				mtdoffset = simple_strtoll(optarg, &error);
				break;
			case 'b':
				blockalign = atoi(optarg);
				break;
			case '?':
				error++;
				break;
		}
	}

	if (mtdoffset < 0)
		errmsg_die("Can't specify negative device offset with option"
				" -s: %lld", mtdoffset);

	if (blockalign < 0)
		errmsg_die("Can't specify negative blockalign with option -b:"
				" %d", blockalign);

	argc -= optind;
	argv += optind;

	/*
	 * There must be at least the MTD device node positional
	 * argument remaining and, optionally, the input file.
	 */

	if (argc < 1 || argc > 2 || error)
		display_help();

	mtd_device = argv[0];

	/*
	 * Standard input may be specified either explictly as "-" or
	 * implicity by simply omitting the second of the two
	 * positional arguments.
	 */

	img = ((argc == 2) ? argv[1] : standard_input);
}

static void erase_buffer(void *buffer, size_t size)
{
	const uint8_t kEraseByte = 0xff;

	if (buffer != NULL && size > 0) {
		memset(buffer, kEraseByte, size);
	}
}

/*
 * Main program
 */
int main(int argc, char * const argv[])
{
	int cnt = 0;
	int fd = -1;
	int ifd = -1;
	int imglen = 0, pagelen;
	bool baderaseblock = false;
	long long blockstart = -1;
	struct mtd_dev_info mtd;
	long long offs;
	int ret;
	int oobinfochanged = 0;
	struct nand_oobinfo old_oobinfo = 
	{
		.oobfree = {{2, 4}, {16, 6}, {32, 6}, {48, 6}},
	};
	bool failed = true;
	// contains all the data read from the file so far for the current eraseblock
	unsigned char *filebuf = NULL;
	size_t filebuf_max = 0;
	size_t filebuf_len = 0;
	// points to the current page inside filebuf
	unsigned char *writebuf = NULL;
	// points to the OOB for the current page in filebuf
	unsigned char *oobreadbuf = NULL;
	unsigned char *oobbuf = NULL;
	libmtd_t mtd_desc;
	int ebsize_aligned;

	process_options(argc, argv);

	if (!onlyoob && (pad && writeoob)) {
		fprintf(stderr, "Can't pad when oob data is present.\n");
		exit(EXIT_FAILURE);
	}

	/* Open the device */
	if ((fd = open(mtd_device, O_RDWR)) == -1) {
		perror(mtd_device);
		exit(EXIT_FAILURE);
	}

	mtd_desc = libmtd_open();
	if (!mtd_desc)
		return errmsg("can't initialize libmtd");
	/* Fill in MTD device capability structure */
	if (mtd_get_dev_info(mtd_desc, mtd_device, &mtd) < 0)
		return errmsg("mtd_get_dev_info failed");

	/*
	 * Pretend erasesize is specified number of blocks - to match jffs2
	 *   (virtual) block size
	 * Use this value throughout unless otherwise necessary
	 */
	ebsize_aligned = mtd.eb_size * blockalign;

	if (mtdoffset & (mtd.min_io_size - 1)) {
		fprintf(stderr, "The start address is not page-aligned !\n"
				"The pagesize of this NAND Flash is 0x%x.\n",
				mtd.min_io_size);
		close(fd);
		exit(EXIT_FAILURE);
	}

	//if (autoplace) {
		/* Read the current oob info */
		//if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
		//	perror("MEMGETOOBSEL");
		//	close(fd);
		//	exit(EXIT_FAILURE);
		//}

		// autoplace ECC ?
		if (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE) {
			//mike
		//	if (ioctl(fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
		//		perror("MEMSETOOBSEL");
		//		close(fd);
		//		exit(EXIT_FAILURE);
		//	}
		
			oobinfochanged = 1;
		}
	//}

#if 0
	if (noecc)  {
		ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW);
		if (ret == 0) {
			oobinfochanged = 2;
		} else {
			switch (errno) {
			case ENOTTY:
					//if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
					//perror("MEMGETOOBSEL");
					//close(fd);
					//exit(EXIT_FAILURE);
					//}
				//mike
			//	if (ioctl(fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
			//		perror("MEMSETOOBSEL");
			//		close(fd);
			//		exit(EXIT_FAILURE);
			//	}
				oobinfochanged = 1;
				break;
			default:
				perror("MTDFILEMODE");
				close(fd);
				exit(EXIT_FAILURE);
			}
		}
	}
#endif

	/*
	 * force oob layout for jffs2 or yaffs ?
	 * Legacy support
	 */
#if 0
	if (forcejffs2 || forceyaffs) {
		struct nand_oobinfo *oobsel = forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;

//		if (autoplace) {
			fprintf(stderr, "Autoplacement is not possible for legacy -j/-y options\n");
			goto restoreoob;
//		}
		if ((old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) && !forcelegacy) {
			fprintf(stderr, "Use -f option to enforce legacy placement on autoplacement enabled mtd device\n");
			goto restoreoob;
		}
		if (mtd.oob_size == 8) {
			if (forceyaffs) {
				fprintf(stderr, "YAFSS cannot operate on 256 Byte page size");
				goto restoreoob;
			}
			/* Adjust number of ecc bytes */
			jffs2_oobinfo.eccbytes = 3;
		}
	//mike
	//	if (ioctl(fd, MEMSETOOBSEL, oobsel) != 0) {
	//		perror("MEMSETOOBSEL");
	//		goto restoreoob;
	//	}
	}
#endif

	/* Determine if we are reading from standard input or from a file. */
	if (strcmp(img, standard_input) == 0) {
		ifd = STDIN_FILENO;
	} else {
		ifd = open(img, O_RDONLY);
	}

	if (ifd == -1) {
		perror(img);
		goto restoreoob;
	}

	pagelen = mtd.min_io_size + ((writeoob) ? mtd.oob_size : 0);


	/*
	 * For the standard input case, the input size is merely an
	 * invariant placeholder and is set to the write page
	 * size. Otherwise, just use the input file size.
	 *
	 * TODO: Add support for the -l,--length=length option (see
	 * previous discussion by Tommi Airikka <tommi.airikka@ericsson.com> at
	 * <http://lists.infradead.org/pipermail/linux-mtd/2008-September/
	 * 022913.html>
	 */

	if (ifd == STDIN_FILENO) {
	    imglen = pagelen;
	} else {
	    imglen = lseek(ifd, 0, SEEK_END);
	    lseek(ifd, 0, SEEK_SET);
	}

	// Check, if file is page-aligned
	if ((!pad) && ((imglen % pagelen) != 0)) {
		fprintf(stderr, "Input file is not page-aligned. Use the padding "
				 "option.\n");
		fprintf(stderr, "imglen=%d,pagelen=%d\n",imglen, pagelen);
		goto closeall;
	}

	// Check, if length fits into device
	if (((imglen / pagelen) * mtd.min_io_size) > (mtd.size - mtdoffset)) {
		fprintf(stderr, "Image %d bytes, NAND page %d bytes, OOB area %d"
				" bytes, device size %lld bytes\n",
				imglen, pagelen, mtd.oob_size, mtd.size);
		perror("Input file does not fit into device");
		goto closeall;
	}

	/*
	 * Allocate a buffer big enough to contain all the data (OOB included)
	 * for one eraseblock. The order of operations here matters; if ebsize
	 * and pagelen are large enough, then "ebsize_aligned * pagelen" could
	 * overflow a 32-bit data type.
	 */
	filebuf_max = ebsize_aligned / mtd.min_io_size * pagelen;
	filebuf = xmalloc(filebuf_max);
	erase_buffer(filebuf, filebuf_max);

	oobbuf = xmalloc(mtd.oob_size);
	erase_buffer(oobbuf, mtd.oob_size);

	/*
	 * Get data from input and write to the device while there is
	 * still input to read and we are still within the device
	 * bounds. Note that in the case of standard input, the input
	 * length is simply a quasi-boolean flag whose values are page
	 * length or zero.
	 */
	while (((imglen > 0) || (writebuf < (filebuf + filebuf_len)))
		&& (mtdoffset < mtd.size)) {
		/*
		 * New eraseblock, check for bad block(s)
		 * Stay in the loop to be sure that, if mtdoffset changes because
		 * of a bad block, the next block that will be written to
		 * is also checked. Thus, we avoid errors if the block(s) after the
		 * skipped block(s) is also bad (number of blocks depending on
		 * the blockalign).
		 */
		while (blockstart != (mtdoffset & (~ebsize_aligned + 1))) {
			blockstart = mtdoffset & (~ebsize_aligned + 1);
			offs = blockstart;

			// if writebuf == filebuf, we are rewinding so we must not
			// reset the buffer but just replay it
			if (writebuf != filebuf) {
				erase_buffer(filebuf, filebuf_len);
				filebuf_len = 0;
				writebuf = filebuf;
			}

			baderaseblock = false;
			if (!quiet)
				fprintf(stdout, "Writing data to block %lld at offset 0x%llx\n",
						 blockstart / ebsize_aligned, blockstart);

			/* Check all the blocks in an erase block for bad blocks */
			if (noskipbad)
				continue;
			do {
				if ((ret = mtd_is_bad(&mtd, fd, offs / ebsize_aligned)) < 0) {
					sys_errmsg("%s: MTD get bad block failed", mtd_device);
					goto closeall;
				} else if (ret == 1) {
					baderaseblock = true;
					if (!quiet)
						fprintf(stderr, "Bad block at %llx, %u block(s) "
								"from %llx will be skipped\n",
								offs, blockalign, blockstart);
				}

				if (baderaseblock) {
					mtdoffset = blockstart + ebsize_aligned;
				}
				offs +=  ebsize_aligned / blockalign;
			} while (offs < blockstart + ebsize_aligned);

		}

		// Read more data from the input if there isn't enough in the buffer
		if ((writebuf + mtd.min_io_size) > (filebuf + filebuf_len)) {
			int readlen = mtd.min_io_size;

			int alreadyread = (filebuf + filebuf_len) - writebuf;
			int tinycnt = alreadyread;

			while (tinycnt < readlen) {
				cnt = read(ifd, writebuf + tinycnt, readlen - tinycnt);
				if (cnt == 0) { // EOF
					break;
				} else if (cnt < 0) {
					perror("File I/O error on input");
					goto closeall;
				}
				tinycnt += cnt;
			}

			/* No padding needed - we are done */
			if (tinycnt == 0) {
				/*
				 * For standard input, set imglen to 0 to signal
				 * the end of the "file". For nonstandard input,
				 * leave it as-is to detect an early EOF.
				 */
				if (ifd == STDIN_FILENO) {
					imglen = 0;
				}
				break;
			}

			/* Padding */
			if (tinycnt < readlen) {
				if (!pad) {
					fprintf(stderr, "Unexpected EOF. Expecting at least "
							"%d more bytes. Use the padding option.\n",
							readlen - tinycnt);
					goto closeall;
				}
				erase_buffer(writebuf + tinycnt, readlen - tinycnt);
			}

			filebuf_len += readlen - alreadyread;
			if (ifd != STDIN_FILENO) {
				imglen -= tinycnt - alreadyread;
			}
			else if (cnt == 0) {
				/* No more bytes - we are done after writing the remaining bytes */
				imglen = 0;
			}
		}

		if (writeoob) {
			oobreadbuf = writebuf + mtd.min_io_size;

			// Read more data for the OOB from the input if there isn't enough in the buffer
			if ((oobreadbuf + mtd.oob_size) > (filebuf + filebuf_len)) {
				int readlen = mtd.oob_size;
				int alreadyread = (filebuf + filebuf_len) - oobreadbuf;
				int tinycnt = alreadyread;

				while (tinycnt < readlen) {
					cnt = read(ifd, oobreadbuf + tinycnt, readlen - tinycnt);
					if (cnt == 0) { // EOF
						break;
					} else if (cnt < 0) {
						perror("File I/O error on input");
						goto closeall;
					}
					tinycnt += cnt;
				}

				if (tinycnt < readlen) {
					fprintf(stderr, "Unexpected EOF. Expecting at least "
							"%d more bytes for OOB\n", readlen - tinycnt);
					goto closeall;
				}

				filebuf_len += readlen - alreadyread;
				if (ifd != STDIN_FILENO) {
					imglen -= tinycnt - alreadyread;
				}
				else if (cnt == 0) {
					/* No more bytes - we are done after writing the remaining bytes */
					imglen = 0;
				}
			}

//			if (!noecc) 			{

//				int i, start, len;
//				int tags_pos = 0;
				/*
				 * We use autoplacement and have the oobinfo with the autoplacement
				 * information from the kernel available
				 *
				 * Modified to support out of order oobfree segments,
				 * such as the layout used by diskonchip.c
				 */
//					if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) {
//						for (i = 0; old_oobinfo.oobfree[i][1]; i++) {
//							/* Set the reserved bytes to 0xff */
//							start = old_oobinfo.oobfree[i][0];
//							len = old_oobinfo.oobfree[i][1];
//							if (rawoob)
//								memcpy(oobbuf + start,
//										oobreadbuf + start, len);
//							else
//								memcpy(oobbuf + start,
//										oobreadbuf + tags_pos, len);
//							tags_pos += len;
//						}
//					} else {
//						/* Set at least the ecc byte positions to 0xff */
//						start = old_oobinfo.eccbytes;
//						len = mtd.oob_size - start;
//						memcpy(oobbuf + start,
//								oobreadbuf + start,
//								len);
//					}

				memcpy(oobbuf + 2, oobreadbuf, 4);
				memcpy(oobbuf + 16, oobreadbuf+4, 6);
				memcpy(oobbuf + 32, oobreadbuf+10, 6);			
//			}

			/* Write OOB data first, as ecc will be placed in there */
			if (mtd_write_oob(mtd_desc, &mtd, fd, mtdoffset,
						mtd.oob_size,
						//noecc ? oobreadbuf : oobbuf)) {
						oobbuf)) {
				sys_errmsg("%s: MTD writeoob failure", mtd_device);
				goto closeall;
			}
		}

		/* Write out the Page data */
		if (!onlyoob && mtd_write(&mtd, fd, mtdoffset / mtd.eb_size, mtdoffset % mtd.eb_size,
					writebuf, mtd.min_io_size)) {
			int i;
			if (errno != EIO) {
				sys_errmsg("%s: MTD write failure", mtd_device);
				goto closeall;
			}

			/* Must rewind to blockstart if we can */
			writebuf = filebuf;

			fprintf(stderr, "Erasing failed write from %#08llx to %#08llx\n",
				blockstart, blockstart + ebsize_aligned - 1);
			for (i = blockstart; i < blockstart + ebsize_aligned; i += mtd.eb_size) {
				if (mtd_erase(mtd_desc, &mtd, fd, mtd.eb_size)) {
					int errno_tmp = errno;
					sys_errmsg("%s: MTD Erase failure", mtd_device);
					if (errno_tmp != EIO) {
						goto closeall;
					}
				}
			}

			if (markbad) {
				fprintf(stderr, "Marking block at %08llx bad\n",
						mtdoffset & (~mtd.eb_size + 1));
				if (mtd_mark_bad(&mtd, fd, mtdoffset / mtd.eb_size)) {
					sys_errmsg("%s: MTD Mark bad block failure", mtd_device);
					goto closeall;
				}
			}
			mtdoffset = blockstart + ebsize_aligned;

			continue;
		}
		mtdoffset += mtd.min_io_size;
		writebuf += pagelen;
	}

	failed = false;

closeall:
	close(ifd);

restoreoob:
	libmtd_close(mtd_desc);
	free(filebuf);
	free(oobbuf);
	//mike
	//if (oobinfochanged == 1) {
	//	if (ioctl(fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
	//		perror("MEMSETOOBSEL");
	//		close(fd);
	//		exit(EXIT_FAILURE);
	//	}
	//}

	close(fd);

	if (failed
		|| ((ifd != STDIN_FILENO) && (imglen > 0))
		|| (writebuf < (filebuf + filebuf_len))) {
		perror("Data was only partially written due to error\n");
		exit(EXIT_FAILURE);
	}

	/* Return happy */
	return EXIT_SUCCESS;
}

[/code]

 

utils\mtd-utils\Mikefile为

# -*- sh -*-

VERSION = 1.4.5

#################
#mike add for ti 3515

CROSS := arm-none-linux-gnueabi-
#bug !
BUILDDIR := $(CURDIR)

ZLIB_DIR := /opt/utils/zlib-1.2.5/build
LZO_DIR := /opt/utils/lzo-2.03/build
UUID_DIR := /opt/utils/uuid-1.6.2/build

DESTDIR := /opt/utils/mtd-utils/build

#addend

CPPFLAGS += -I./include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) -I$(ZLIB_DIR)/include -I$(LZO_DIR)/include -I$(UUID_DIR)/include 
LDLIBS += $(ZLIB_DIR)/lib/libz.a  $(UUID_DIR)/lib/libuuid.a

#ifeq ($(WITHOUT_XATTR), 1)
  CPPFLAGS += -DWITHOUT_XATTR
#endif

ifeq ($(WITHOUT_LZO), 1)
  CPPFLAGS += -DWITHOUT_LZO
else
  LZOLDLIBS = $(LZO_DIR)/lib/liblzo2.a
endif

TESTS = tests

MTD_BINS = \
	ftl_format flash_erase nanddump doc_loadbios \
	ftl_check mkfs.jffs2 flash_lock flash_unlock \
	flash_otp_info flash_otp_dump mtd_debug flashcp nandwrite nandtest \
	jffs2dump \
	nftldump nftl_format docfdisk \
	rfddump rfdformat \
	serve_image recv_image \
	sumtool #jffs2reader
UBI_BINS = \
	ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
	ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol

BINS = $(MTD_BINS)
#BINS += mkfs.ubifs/mkfs.ubifs
BINS += $(addprefix ubi-utils/,$(UBI_BINS))
SCRIPTS = flash_eraseall

TARGETS = $(BINS)
TARGETS += lib/libmtd.a
TARGETS += ubi-utils/libubi.a

OBJDEPS = $(BUILDDIR)/include/version.h

include common.mk

clean::
ifneq ($(BUILDDIR)/.git,)
ifneq ($(BUILDDIR),.)
ifneq ($(BUILDDIR),$(CURDIR))
	rm -rf $(BUILDDIR)
endif
endif
endif
	find $(BUILDDIR)/ -xdev \
		'(' -name '*.[ao]' -o -name '.*.c.dep' ')' \
		-exec rm -f {} +
	rm -f $(BUILDDIR)/include/version.h
	$(MAKE) -C $(TESTS) clean

install:: ${BINS} ${SCRIPTS}
	mkdir -p ${DESTDIR}/${SBINDIR}
	install -m 0755 ${BINS} ${SCRIPTS} ${DESTDIR}/${SBINDIR}/
	mkdir -p ${DESTDIR}/${MANDIR}/man1
	gzip -9c mkfs.jffs2.1 > ${DESTDIR}/${MANDIR}/man1/mkfs.jffs2.1.gz

tests::
	$(MAKE) -C $(TESTS)

cscope:
	cscope -bR

$(BUILDDIR)/include/version.h: $(BUILDDIR)/include/version.h.tmp
	$(Q)cmp -s $@ $@.tmp && rm -f $@.tmp || mv $@.tmp $@
$(BUILDDIR)/include/version.h.tmp:
	$(Q)echo '#define VERSION "$(VERSION)"' > $@

#
# Utils in top level
#
obj-mkfs.jffs2 = compr_rtime.o compr_zlib.o compr_lzo.o compr.o rbtree.o
LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
LDLIBS_mkfs.jffs2  =  $(LZOLDLIBS)

LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
LDLIBS_jffs2reader  = $(LZOLDLIBS)

$(foreach v,$(MTD_BINS),$(eval $(call mkdep,,$(v))))

#
# Common libmtd
#
obj-libmtd.a = libmtd.o libmtd_legacy.o libcrc32.o libfec.o
$(call _mkdep,lib/,libmtd.a)

#
# Utils in mkfs.ubifs subdir
#
obj-mkfs.ubifs = crc16.o lpt.o compr.o devtable.o \
	hashtable/hashtable.o hashtable/hashtable_itr.o
#LDLIBS_mkfs.ubifs = -lz -llzo2 -lm -luuid
$(call mkdep,mkfs.ubifs/,mkfs.ubifs,,ubi-utils/libubi.a)

#
# Utils in ubi-utils/ subdir
#
obj-libiniparser.a = libiniparser.o dictionary.o
obj-libscan.a      = libscan.o
obj-libubi.a       = libubi.o
obj-libubigen.a    = libubigen.o

obj-mtdinfo   = libubigen.a
obj-ubinize   = libubigen.a libiniparser.a
obj-ubiformat = libubigen.a libscan.a

$(foreach v,libubi.a libubigen.a libiniparser.a libscan.a,$(eval $(call _mkdep,ubi-utils/,$(v))))
$(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-common.o)))


utils\mtd-utils\common.mk为

CC := $(CROSS)gcc
AR := $(CROSS)ar
RANLIB := $(CROSS)ranlib

# Stolen from Linux build system
comma = ,
try-run = $(shell set -e; ($(1)) >/dev/null 2>&1 && echo "$(2)" || echo "$(3)")
cc-option = $(call try-run, $(CC) $(1) -c -xc /dev/null -o /dev/null,$(1),$(2))

CFLAGS ?= -O2 -g
WFLAGS := -Wall \
	$(call cc-option,-Wextra) \
	$(call cc-option,-Wwrite-strings) \
	$(call cc-option,-Wno-sign-compare)
CFLAGS += $(WFLAGS)
SECTION_CFLAGS := $(call cc-option,-ffunction-sections -fdata-sections -Wl$(comma)--gc-sections)
CFLAGS += $(SECTION_CFLAGS)

ifneq ($(WITHOUT_LARGEFILE), 1)
  CPPFLAGS += -D_FILE_OFFSET_BITS=64
endif

DESTDIR?=
PREFIX=/usr
EXEC_PREFIX=$(PREFIX)
SBINDIR=$(EXEC_PREFIX)/sbin
MANDIR=$(PREFIX)/share/man
INCLUDEDIR=$(PREFIX)/include

ifndef BUILDDIR
ifeq ($(origin CROSS),undefined)
  BUILDDIR := $(CURDIR)
else
# Remove the trailing slash to make the directory name
  BUILDDIR := $(CURDIR)/$(CROSS:-=)
endif
endif
override BUILDDIR := $(patsubst %/,%,$(BUILDDIR))

override TARGETS := $(addprefix $(BUILDDIR)/,$(TARGETS))

ifeq ($(V),1)
XECHO = @:
XPRINTF = @:
Q =
else
XECHO = @echo
XPRINTF = @printf
Q = @
endif
define BECHO
$(XPRINTF) '  %-7s %s\n' "$1" "$(subst $(BUILDDIR)/,,$@)"
endef

all:: $(TARGETS)

clean::
	rm -f $(BUILDDIR)/*.o $(TARGETS) $(BUILDDIR)/.*.c.dep

install:: $(TARGETS)

define _mkdep
$(BUILDDIR)/$1$2: $(addprefix $(BUILDDIR)/$1,$(obj-$2) $3) $(addprefix $(BUILDDIR)/,$4)
endef
define mkdep
$(call _mkdep,$1,$2,$3 $2.o,$4 lib/libmtd.a)
endef

%: %.o $(LDDEPS)
	$(call BECHO,LD)
	$(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_$(notdir $@)) -g -o $@ $^ $(LDLIBS) $(LDLIBS_$(notdir $@))

$(BUILDDIR)/%.a:
	$(call BECHO,AR)
	$(Q)$(AR) cr $@ $^
	$(Q)$(RANLIB) $@

$(BUILDDIR)/%.o: %.c $(OBJDEPS)
ifneq ($(BUILDDIR),$(CURDIR))
	$(Q)mkdir -p $(dir $@)
endif
	$(call BECHO,CC)
	$(Q)$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ {1}lt; -g -Wp,-MD,$(BUILDDIR)/.$(<F).dep

.SUFFIXES:

IGNORE=${wildcard $(BUILDDIR)/.*.c.dep}
-include ${IGNORE}

PHONY += all clean install
.PHONY: $(PHONY)


yaffs2-git\utils\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.
 * Mike : guide 
 * get form http://www.aleph1.co.uk/gitweb?p=yaffs2.git;a=blob_plain;f=utils/mkyaffs2image.c;hb=e1ac494e05a5dc7ab61d799af815d103a11d318c
 * patch address : http://www.aleph1.co.uk/lurker/message/20070912.140012.12f2d093.en.html
 * usage : http://www.yaffs.net/lurker/message/20090818.064412.ade6284d.en.html#yaffs
 */
 
#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 2048
#define spareSize 64

const char * mkyaffsimage_c_version = "$Id: mkyaffs2image.c,v 1.4 2007-02-14 01:09:06 wookey Exp {1}quot;;


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;
//mike added
#define OOB_TAGS_POSITION_DEFAULT 0;
static int oob_tags_pos = OOB_TAGS_POSITION_DEFAULT;


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 array\n");
		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.
 * NOTE: The tag is not usable after this other than calculating the CRC
 * with.
 */
static void little_to_big_endian(yaffs_Tags *tagsPtr)
{
#if 0 // FIXME NCB
    yaffs_TagsUnion * tags = (yaffs_TagsUnion* )tagsPtr; // Work in bytes.
    yaffs_TagsUnion   temp;

    memset(&temp, 0, sizeof(temp));
    // Ick, I hate magic numbers.
    temp.asBytes[0] = ((tags->asBytes[2] & 0x0F) << 4) | ((tags->asBytes[1] & 0xF0) >> 4);
    temp.asBytes[1] = ((tags->asBytes[1] & 0x0F) << 4) | ((tags->asBytes[0] & 0xF0) >> 4);
    temp.asBytes[2] = ((tags->asBytes[0] & 0x0F) << 4) | ((tags->asBytes[2] & 0x30) >> 2) | ((tags->asBytes[3] & 0xC0) >> 6);
    temp.asBytes[3] = ((tags->asBytes[3] & 0x3F) << 2) | ((tags->asBytes[2] & 0xC0) >> 6);
    temp.asBytes[4] = ((tags->asBytes[6] & 0x03) << 6) | ((tags->asBytes[5] & 0xFC) >> 2);
    temp.asBytes[5] = ((tags->asBytes[5] & 0x03) << 6) | ((tags->asBytes[4] & 0xFC) >> 2);
    temp.asBytes[6] = ((tags->asBytes[4] & 0x03) << 6) | (tags->asBytes[7] & 0x3F);
    temp.asBytes[7] = (tags->asBytes[6] & 0xFC) | ((tags->asBytes[7] & 0xC0) >> 6);

    // Now copy it back.
    tags->asBytes[0] = temp.asBytes[0];
    tags->asBytes[1] = temp.asBytes[1];
    tags->asBytes[2] = temp.asBytes[2];
    tags->asBytes[3] = temp.asBytes[3];
    tags->asBytes[4] = temp.asBytes[4];
    tags->asBytes[5] = temp.asBytes[5];
    tags->asBytes[6] = temp.asBytes[6];
    tags->asBytes[7] = temp.asBytes[7];
#endif
}

static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes)
{
	yaffs_ExtendedTags t;
	yaffs_PackedTags2 pt;
	
	//added by mike
	unsigned char * oob;
	
	char oobData[spareSize];


	error = write(outFile,data,chunkSize);
	if(error < 0) return error;

	yaffs_InitialiseTags(&t);
	
	t.chunkId = chunkId;
//	t.serialNumber = 0;
	t.serialNumber = 1;	// **CHECK**
	t.byteCount = nBytes;
	t.objectId = objId;
	
	t.sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;

// added NCB **CHECK**
	t.chunkUsed = 1;

	if (convert_endian)
	{
    	    little_to_big_endian(&t);
	}

	nPages++;

	yaffs_PackTags2(&pt,&t);
//mike	
#if 0	
//	return write(outFile,&pt,sizeof(yaffs_PackedTags2));
	return write(outFile,&pt,spareSize);
#endif

   // * Need to write to the oob tags to the right position within the oob space
    if((oob_tags_pos < 0) || (oob_tags_pos > (spareSize-sizeof(yaffs_PackedTags2))))
    {
        oob_tags_pos = OOB_TAGS_POSITION_DEFAULT;
    }
    memset(oobData,0xFF,spareSize);
	oob = (unsigned char *)&pt;
#if 0	
	memcpy(oobData + 2, oob, 4);
	oob+=2;
	memcpy(oobData + 16, oob, 6);
	oob+=6;
	memcpy(oobData + 32, oob, 6);
#endif	
    memcpy(&(oobData[oob_tags_pos]),&pt, 16);
	//memcpy(&(oobData[oob_tags_pos]),&pt,sizeof(yaffs_PackedTags2));
    return write(outFile,oobData,spareSize);

}

#define SWAP32(x)   ((((x) & 0x000000FF) << 24) | \
                     (((x) & 0x0000FF00) << 8 ) | \
                     (((x) & 0x00FF0000) >> 8 ) | \
                     (((x) & 0xFF000000) >> 24))

#define SWAP16(x)   ((((x) & 0x00FF) << 8) | \
                     (((x) & 0xFF00) >> 8))
        
// This one is easier, since the types are more standard. No funky shifts here.
static void 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]);
    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]);
#else
    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]);
    oh->roomToGrow[6] = SWAP32(oh->roomToGrow[6]);
    oh->roomToGrow[7] = SWAP32(oh->roomToGrow[7]);
    oh->roomToGrow[8] = SWAP32(oh->roomToGrow[8]);
    oh->roomToGrow[9] = SWAP32(oh->roomToGrow[9]);
    oh->roomToGrow[10] = SWAP32(oh->roomToGrow[10]);
    oh->roomToGrow[11] = SWAP32(oh->roomToGrow[11]);
#endif
}

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[chunkSize];
	
	
	yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bytes;
	
	memset(bytes,0xff,sizeof(bytes));
	
	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)
	{
    		object_header_little_to_big_endian(oh);
	}
	
	return write_chunk(bytes,objId,0,0xffff);
	
}


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 %d\n",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[chunkSize];
								int nBytes;
								int chunk = 0;
								
								h = open(full_name,O_RDONLY);
								if(h >= 0)
								{
									memset(bytes,0xff,sizeof(bytes));
									while((nBytes = read(h,bytes,sizeof(bytes))) > 0)
									{
										chunk++;
										write_chunk(bytes,newObj,chunk,nBytes);
										memset(bytes,0xff,sizeof(bytes));
									}
									if(nBytes < 0) 
									   error = nBytes;
									   
									printf("%d data chunks written\n",chunk);
								}
								else
								{
									perror("Error opening file");
								}
								close(h);
								
							}							
														
						}
						else if(S_ISSOCK(stats.st_mode))
						{
							printf("socket\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
						}
						else if(S_ISFIFO(stats.st_mode))
						{
							printf("fifo\n");
							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 device\n");
							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 device\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
						}
						else if(S_ISDIR(stats.st_mode))
						{
							printf("directory\n");
							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 type\n");
				}
			}
		}
	}
	
	return 0;

}


int main(int argc, char *argv[])
{
	struct stat stats;
	
	
	if(argc < 3)
	{
//Mike
//offical 
#if 0
		printf("usage: mkyaffs2image dir image_file [convert]\n");
		printf("           dir        the directory tree to be converted\n");
		printf("           image_file the output file to hold the image\n");
        printf("           'convert'  produce a big-endian image from a little-endian machine\n");
#endif		
//patched
#if 0
        printf("usage: mkyaffs2image dir image_file [oob_ecc_size] [convert]\n");
        printf("           dir             the directory tree to be converted\n");
        printf("           image_file      the output file to hold the image\n");
		printf("           [oob_ecc_size]  the number of oob bytes reserved for ecc data (default is 0)\n");
        printf("           ['convert']     produce a big-endian image from a little-endian machine\n");
#endif
//now we need no other parameters:
		fprintf(stderr, "build YAFFS2 image specially for dm365 version : "__DATE__"\n");
        printf("This Tool is builded for dm365 specially\n");
        printf("           dir             the directory tree to be converted\n");
        printf("           image_file      the output file to hold the image\n");
		exit(1);
	}
//Mike			
//offical 
#if 0
    if ((argc == 4) && (!strncmp(argv[3], "convert", strlen("convert"))))
    {
        convert_endian = 1;
    }
#endif

//patched
#if 0
    if(argc == 4)
    {
        if(!strncmp(argv[3], "convert", strlen("convert")))
        {
            convert_endian = 1;
        }
        else
        {
            oob_tags_pos = atoi(argv[3]);
        }
    }
    else if(argc == 5)
    {
        oob_tags_pos = atoi(argv[3]);
        if(!strncmp(argv[4], "convert", strlen("convert")))
        {
            convert_endian = 1;
        }
    }
#endif
    
	if(stat(argv[1],&stats) < 0)
	{
		printf("Could not stat %s\n",argv[1]);
		exit(1);
	}
	
	if(!S_ISDIR(stats.st_mode))
	{
		printf(" %s is not a directory\n",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 %s\n",argv[2]);
		exit(1);
	}
	
	printf("Processing directory %s into image file %s\n",argv[1],argv[2]);
	error =  write_object_header(1, 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 directories\n"
		       "%d NAND pages\n",nObjects, nDirectories, nPages);
	}
	
	close(outFile);
	
	exit(0);
}	


真对上述修改,写入命令变为:

  mkyaffs2image DIR  app.img
flash_eraseall /dev/mtd5
./nandwriteyaffs -o /dev/mtd5 img/app.img

 经过多次修改,下面的二进制都静态链接到.a库而不需要拷贝.so了。。。

nanddump     mtd_debug          nandwrite

 

终于完善了。 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值