mkyaffs2image编译
http://blog.chinaunix.net/uid-26009923-id-3760474.html
http://blog.csdn.net/xingtian19880101/article/details/17504529
一. mkyaffs2image 是如何生成的
我们往往用 mkyaffs2image把文件系统打包成yaffs.bin格式,然后在u-boot 中用 nand.write.yaffs2 把文件系统烧到nand flash的指定位置上
但是mkyaffs2image是如何编译出来的呢? 其实mkyaffs2image是在yaffs文件系统的utils目录下,
只把其中的chunkSize spareSize 与 pagesPerBlock几个变量,按照nand_flash中的改一下就可以用
// Adjust these to match your NAND LAYOUT:
//#define chunkSize 8192
//#define spareSize 232
#define chunkSize 4096
//#define spareSize 218
#define spareSize 128
#define pagesPerBlock 128
我这儿只是改了 chunkSize 与 spareSize.但是貌似datasheet上的spareSize=218. 莫非datasheet也可以骗人。
二. mkyaffs2image分析
2. 下面是mkyaffs2image的main, 很简单的一个函数吧
其中, argc必须大于3
argv[1] = dir //文件系统的path
argv[2] = image_file //打包后生成yaffs.bin的路径
int main(int argc, char *argv[])
{
struct stat stats;
stat(argv[1],&stats);
if(!S_ISDIR(stats.st_mode)) //保证argv[1]必须是一个目录
exit(1);
outFile = open(argv[2],O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE); //写入到镜像yaffs.bin的fd保存在一个全局变量outFile中
process_directory(YAFFS_OBJECTID_ROOT,argv[1]); //1. 依次读取目录中的文件,写到yaffs.bin中
pad_image(); //2. 将yaffs.bin扩充到block对齐
close(outFile);
}
2.1 对目录的处理过程
static int process_directory(int parent, const char *path)
{
DIR *dir;
char full_name[500];
struct stat stats;
int equivalentObj;
int newObj;
struct dirent *entry;
nDirectories++;
dir = opendir(path); //打开目录
while((entry = readdir(dir)) != NULL) //遍历目录中的所有文件
{
if(strcmp(entry->d_name,".") || strcmp(entry->d_name,"..")) //如果是 . 或者 .. 则直接跳过
continue;
snprintf(full_name,sizeof(full_name),"%s/%s",path,entry->d_name); //构造文件的路径,存于full_name中
lstat(full_name,&stats); //获取目录下该文件的stat信息
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))
continue ; //不知道这TMD是什么类型的文件则跳过
newObj = obj_id++;
n_obj++;
if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0)
{
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);
write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname);
}
else if(S_ISREG(stats.st_mode)) //如果是普通文件
{
if(write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL) == 0) //1.先写入文件头
{
int h;
u8 bytes[chunkSize];
int n_bytes;
int chunk = 0;
h = open(full_name,O_RDONLY);
memset(bytes,0xff,sizeof(bytes));
while((n_bytes = read(h,bytes,sizeof(bytes))) > 0)
{
chunk++;
write_chunk(bytes,newObj,chunk,n_bytes); //2.再写入文件内容
memset(bytes,0xff,sizeof(bytes));
}
close(h);
}
}
else if(S_ISSOCK(stats.st_mode)) //如果是socket文件
write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); //只写入文件头
else if(S_ISFIFO(stats.st_mode)) //如果是FIFO文件
write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); //只写入文件头
else if(S_ISCHR(stats.st_mode)) //如果是字符设备文件
write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); //只写入文件头
else if(S_ISBLK(stats.st_mode)) //如果是块设备文件
write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); //只写入文件头
else if(S_ISDIR(stats.st_mode)) //如果是目录文件
if (write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL) == 0) //只写入文件头
process_directory(newObj,full_name); //并把这次的newObj作为parent,继续
}
}
closedir(dir);
return 0;
}
2.1.1
static int write_object_header(int id, enum yaffs_obj_type t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias)
{
u8 bytes[chunkSize];
struct yaffs_obj_hdr *oh = (struct yaffs_obj_hdr *)bytes;
memset(bytes,0xff,sizeof(bytes));
oh->type = t;
oh->parent_obj_id = parent;
if (strlen(name)+1 > sizeof(oh->name))
{
errno = ENAMETOOLONG;
return warn("object name");
}
memset(oh->name,0,sizeof(oh->name));
strcpy(oh->name,name);
if(t != YAFFS_OBJECT_TYPE_HARDLINK)
{
oh->yst_mode = s->st_mode;
oh->yst_uid = s->st_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->file_size = s->st_size;
}
if(t == YAFFS_OBJECT_TYPE_HARDLINK)
{
oh->equiv_id = equivalentObj;
}
if(t == YAFFS_OBJECT_TYPE_SYMLINK)
{
if (strlen(alias)+1 > sizeof(oh->alias))
{
errno = ENAMETOOLONG;
return warn("object alias");
}
memset(oh->alias,0,sizeof(oh->alias));
strcpy(oh->alias,alias);
}
return write_chunk(bytes,id,0,0xffff);
}
static int write_chunk(u8 *data, u32 id, u32 chunk_id, u32 n_bytes)
{
struct yaffs_ext_tags t;
struct yaffs_packed_tags2 pt;
char spareData[spareSize];
if (write(outFile,data,chunkSize) != chunkSize) //写4K
fatal("write");
memset(&t, 0, sizeof(t));
t.chunk_id = chunk_id;
t.serial_number = 1; // **CHECK**
t.n_bytes = n_bytes;
t.obj_id = id;
t.seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER;
t.chunk_used = 1;
nPages++;
memset(&pt, 0, sizeof(pt)); //函数将 yaffs_ext_tags转为yaffs_packed_tags2,并生成校验信息,
yaffs_pack_tags2(&pt,&t,0); //但最后一个函数是0,所以只转化保存校验信息
memset(spareData, 0xff, sizeof(spareData));
shuffle_oob(spareData, &pt);
if (write(outFile,spareData,sizeof(spareData)) != sizeof(spareData)) //写oob
fatal("write");
return 0;
}
注:
struct yaffs_packed_tags2 {
struct yaffs_packed_tags2_tags_only t; //数据
struct yaffs_ecc_other ecc; //校验信息
};
yaffs_packed_tags2是由数据和校难信息两部分组成的,但是这儿只用了数据不进行校验,所以内核里面也只是读出数据不校验
2.2 扩充yaffs.bin到一个block
static void pad_image(void)
{
u8 data[chunkSize + spareSize];
int padPages = (nPages % pagesPerBlock);
if (padPages)
{
memset(data, 0xff, sizeof(data));
for (padPages = pagesPerBlock-padPages; padPages; padPages--)
{
if (write(outFile, data, sizeof(data)) != sizeof(data))
fatal("write");
}
}
}
d 三. 实验一下
3.1 实验
a.新建目录fs_test,在fs_test新建一文件222.txt, 内空是"bbbcc"
sun@ubuntu:/tmp/mkyaffs/utils/test$ tree
.
└── fs_test
└── 222.txt
1 directory, 1 file
sun@ubuntu:/tmp/mkyaffs/utils/test$ cat fs_test/222.txt
bbbccc
b. 利用mkyaffs2image生成yaffs的打包文件fs.yaffs
sun@ubuntu:/tmp/mkyaffs/utils/test$ ../mkyaffs2image fs_test/ fs.yaffs
main[432]: mkyaffs2image: image building tool for YAFFS2 built Jul 3 2013
main[464]: Processing directory fs_test/ into image file fs.yaffs
Object 257, fs_test//222.txt is a
file,
1 data chunks written
pad_image[255]: nPages=2
main[480]: Operation complete.
2 objects in 1 directories
2 NAND pages
sun@ubuntu:/tmp/mkyaffs/utils/test$ ll
total 540
drwxrwxr-x 3 sun sun 4096 Jul 3 16:36 ./
drwxrwxr-x 5 sun sun 4096 Jul 3 15:36 ../
drwxrwxr-x 2 sun sun 4096 Jul 3 15:06 fs_test/
-rw------- 1 sun sun 540672 Jul 3 16:36 fs.yaffs
可以看出fs.yaffs的大小是540672=128×(4096+128)
c. 分析一下fs.yaffs
按page的记录内容,可以分为两种,一个是oh_page另一个是data_page
其中普通文件,需要一个oh_page,如果有内容还需要一个或多个data_page
其它的文件,则只需要一个oh_page就够了.
oh_page:
data_page:
sizeof(yaffs_obj_hdr)=0x200=512B
28B的信息就是结构体 yaffs_packed_tags2
struct yaffs_packed_tags2_tags_only {
unsigned seq_number;
unsigned obj_id;
unsigned chunk_id;
unsigned n_bytes;
};
struct yaffs_ecc_other {
unsigned char col_parity;
unsigned line_parity;
unsigned line_parity_prime;
};
struct yaffs_packed_tags2 {
struct yaffs_packed_tags2_tags_only t;
struct yaffs_ecc_other ecc;
};
3.2 oh_page与data_page的根本区别
int write_chunk(u8 *data, u32 id, u32 chunk_id, u32 n_bytes);
write_chunk(bytes,id,0,0xffff); //写oh_page chunk_id=0,写入oob
write_chunk(bytes,newObj,chunk,n_bytes); //写data_page chunk_id!=0,写入oob
其中 write_chunk的第2个参数id, oh_page与data_page相等的话说明这是同一个文件的头与数据区
其中 write_chunk的第3个参数chunk_id, 区分oh_page与data_page, oh_page的chunk_id=0
mkyaffs2image编译的更多相关文章
- jffs2和yaffs2文件系统制作工具的编译与使用
一 . 先准备文件 mtd-utils-1.4.5.tar.bz2 ftp://ftp.infradead.org/pub/mtd-utils/ zlib-1.2.5.tar.bz2 http://z ...
- ubuntu12.04下安卓编译环境搭建总结
前言: 因为工作需要,经常要编译安卓下的动态库,公司有已经搭建好环境的服务器,但是第一自己想自己搭建一下了解一个整个过程,另外,公司的服务器也经常出现问 题,导致编译不了,所以就想自己搭建环 ...
- 【转】Android 4.3源码的下载和编译环境的安装及编译
原文网址:http://jingyan.baidu.com/article/c85b7a641200e0003bac95a3.html 告诉windows用户一个不好的消息,windows环境下没法 ...
- 【转】高通平台android 环境配置编译及开发经验总结
原文网址:http://blog.csdn.net/dongwuming/article/details/12784535 1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通 ...
- Ubuntu12.04编译Android4.0.1源码全过程-----附wubi安装ubuntu编译android源码硬盘空间不够的问题解决
昨晚在编译源码,make一段时间之后报错如下: # A fatal error has been detected by the Java Runtime Environment: # # SIGSE ...
- hi3531 SDK已编译文件系统制作jffs2文件系统镜像并解决问题 .
一, 安装SDK 1.Hi3531 SDK包位置 在"Hi3531_V100R001***/01.software/board"目录下,您可以看到一个 Hi3531_SDK_Vx. ...
- 01.ubuntu16.06编译安装Hi3518EV200 SDK
转载,侵删 HI3518EV200 SDK安装并编译osdr. 1.开发环境 windows10电脑 + 虚拟机14 Pro + Ubuntu16.0.4 2.拷贝并解压.将 Hi3518E_SDK_ ...
- Android OTA在线升级二(升级包编译原理分析) 【转】
本文转载自:http://blog.csdn.net/huryjiang/article/details/7590015 1 升级包的制作 基本命令: Ø makeMtk [project[flav ...
- linux根文件系统制作之busybox编译和系统构建【转】
转自:http://blog.chinaunix.net/uid-29401328-id-5019660.html 介绍完相关文件后我们开始构建文件系统,涉及到的文件等到具体用到的时候再讲. 一.编译 ...
随机推荐
- BIND9源码分析之acl 的实现
BIND配置中一大堆一大堆的acl,什么allow-query, allow-recursion, allow-update还有view的match-clients等等等等. acl中的主要存储的就是 ...
- Linux安装JDK详细步骤(rpm方式)
1. 先从网上下载jdk(jdk-6u32-linux-i586-rpm) ,下载后放在/home目录中,当然其它地方也行. 进入安装目录 #cd /home#cp jdk-6u32-linux-i5 ...
- 程序安装制作不用愁—Wise installation入门教程
http://blog.csdn.net/terryzero/article/details/6731925最近有个项目需要把别人的工具包装集成下,所以就随便找了个制作安装的工具,正好找到了Wise ...
- 跳出框架iframe的操作语句
常用的iframe操作语句 ① 本页面跳转语句: "window.location.href" 或者 "location.href" ② 上一层页面跳转 ...
- 利用recv和readn函数实现readline函数
在前面的文章中,我们为了避免粘包问题,实现了一个readn函数读取固定字节的数据.如果应用层协议的各字段长度固定,用readn来读是非常方便 的.例如设计一种客户端上传文件的协议,规定前12字节表示文 ...
- 局域网不同用户同时登录同一个网站,会出现session乱窜的问题
出现这种问题的情景再现: 1.有一部分人访问网站会出现session乱窜的问题. 2.这部分人是在同一个局域网中. 3.不同菜单看到的信息是不同人的,或者同一个菜单翻页时有的时候看到的是自己的数据,有 ...
- eclipse逆向生成实体类注解方式或者xml方式
转载自:http://www.2cto.com/database/201501/372023.html http://blog.csdn.net/wangpeng047/article/details ...
- php 第三方DB库NOTORM
百度NOTORM找到该库的官网 :http://www.notorm.com/ 打开E:\AppServ\php7\php.ini 找到extension=php_pdo_mysql.dll 解开前面 ...
- unity camera aspect
camera的aspect默认是与screen保持一致,可以通过脚本将其设为指定值,如下: using UnityEngine;using System.Collections; public cla ...
- angularJS核心原理
一.angularJS优点和缺点 优点 1.1免去重复劳动-获取元素.给元素加事件.创建元素 1.2接管UI:angularJS根据数据创建UI元素,免去手工创建UI元素. 1.3自动同步:根据数据个 ...