日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

mkyaffs2image编译

發布時間:2025/1/21 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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编译的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。