我们知道, 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 <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 <[email protected]> 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 $@ [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)/.$(<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 <[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. * 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
终于完善了。