我们知道, dm365的rbl 对 nand flash的支持比较特别,和uboot以及内核的不相同,需要打补丁,因此导致写oob的fs需要特别的操作,
特别是针对硬件开启ecc的内核和uboot(本人就是)
起初,不管怎么改nandwrite 和mkyaffs2image(这个东东很难下载到!!本人实在是无奈,从官网下载到了,和邮件列表上回复的时间一致的版本,方便打补丁嘛)
通过挂载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 |[email protected]{.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 需要接近于补丁的时间:
见此处,选中,某个时间段,点击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
此工具真的很难整。。
下载需要的依赖
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)):
注解关于 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 ([email protected])
* 2003 Thomas Gleixner ([email protected])
*
* 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "mtd/mtd-user.h"
#include "common.h"
#include
#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 at
*
*/
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 $@ [email protected] && rm -f [email protected] || mv [email protected] $@
$(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)/.$(
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
* 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
#include
#include
#include
#include
#include
#include
#include
#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
终于完善了。