文件系統以及mkyaffsimage工具的製作

文件系統以及mkyaffsimage工具的製作

(2010-09-06 10:25:29)
   

申明:本作品經過在下長時間收集網上資料和自己動手實踐所寫下的筆記,供大家探討學習,如有錯誤望不吝指明...

一.相關知識介紹

(1) 爲什麼我們要用busybox?

   我們利用busybox主要是生成文件系統的4個主要文件:bin sbin usrlinuxrc這4個文件就是我們要構建的文件系統的主體部分,生成上述文件後busybox對於我們來說就沒有什麼作用了,我們一般的做法是在其他的地方再建立一個文件夾,然後將binsbin usr linuxrc拷貝過去,以後我們做的文件系統就是這個新建的文件夾裏邊。

(2) 用yaffs2生成一個做文件系統鏡象的工具

 在yaffs2裏邊有個文件夾叫utils,在這個裏邊3個文件,Makefile ,mkyaffsimage.cmkyaffs2image.c,在這個裏邊按道理是直接make就可以搞定,實際上需要加兩個文件,這兩個文件是處理ECC的。然後再make就可以生成兩個工具文件:mkyaffsimage 和mkyaffs2image

mkyaffs2image和mkyaffsimage區別:一個可以支持2k頁面,一個僅僅512頁面。

(3) busybox文件系統啓動順序

默認初始化文件是:/sbin/init,如果要從 /linuxrc腳本運行的話需要在內核傳遞參數裏設置 init=/linuxrc

如果不採用 linuxrc 的話就會執行 /sbin/init 腳本,它會去分析/etc/inittab 腳本:

1)/sbin/init ->/etc/inittab
#id: runlevels: action:process
:: sysinit:/etc/init.d/rcS
console::  askfirst:-/bin/sh
:: ctrlaltdel:/sbin/reboot

::shutdown:/bin/umount -a -r
2)/sbin/init -> /etc/inittab ->/etc/init.d/rcS
#!/bin/sh
echo "********* /etc/init.d/rcS **********"
export PATH=/sbin:/bin:
export HOSTNAME=Tony

echo "initial ip address....."
/sbin/ifconfig eth0 192.168.0.33

echo "Mount all filesystems (of the giventypes) mentioned in fstab."
mount –a

3) mount -a含義爲把fstab文件定義的文件系統都做mount處理,

fatab:
# device    mount-point   type  options      dump  fsckorder
proc         /proc      proc  defaults      0    0
tmpfs        /tmp       tmpfs  defaults      0    0
sysfs        /sys       sysfs  defaults      0    0
4)/sbin/init -> /etc/inittab ->/etc/profile
# /etc/profile: system-wide .profile file for the Bourneshells
echo "********* /etc/profile *************"
PATH=/bin:/sbin:/usr/bin:/usr/sbin


二、文件系統製作

編譯組合: busybox-1.7.3  arm-linux-gcc-3.4.1

宿主機:redhat 9

目標機:FL2440

交叉編譯器:arm-linux-gcc-3.4.1

1.#tar -jxvf busybox-1.7.3.tar.bz2

2.#cd busybox-1.7.3

3.#vi Makefile  修改編譯工具鏈和體系結構

ARCH                ?= arm

CROSS_COMPILE      ?= /usr/local/arm/3.4.1/bin/arm-linux-

4.#make menuconfig

Busybox Setting----->
      Build option-->
    [*] BuildBusyBox as a static binary (no shared libs)

Shells ----->

Choose your default shell (ash) >

[X] ash

Miscellaneous Utilities --->

[ ] taskset 要去掉不然會出現以下錯誤

    miscutils/taskset.c:17: error: parse error before '*' token
   miscutils/taskset.c:18: warning: functiondeclaration isn't a prototype
   miscutils/taskset.c: In function`__from_cpuset':
   miscutils/taskset.c:22: error: `CPU_SETSIZE'undeclared (first use in this function)
   miscutils/taskset.c:22: error: (Each undeclaredidentifier is reported only once
   miscutils/taskset.c:22: error: for eachfunction it appears in.)
   miscutils/taskset.c:26: warning: implicitdeclaration of function `CPU_ISSET'
   miscutils/taskset.c:26: error: `mask'undeclared (first use in this function)
   miscutils/taskset.c: In function`taskset_main':
   miscutils/taskset.c:47: error: `cpu_set_t'undeclared (first use in this function)
   miscutils/taskset.c:47: error: parse errorbefore "mask"
   miscutils/taskset.c:68: warning: implicitdeclaration of function `CPU_ZERO'
   miscutils/taskset.c:68: error: `new_mask'undeclared (first use in this function)
   miscutils/taskset.c:69: error: `CPU_SETSIZE'undeclared (first use in this function)
   miscutils/taskset.c:71: warning: implicitdeclaration of function `CPU_SET'
   miscutils/taskset.c:78: error: `mask'undeclared (first use in this function)
   make[1]: *** [miscutils/taskset.o] Error1
   make: *** [miscutils] Error 2

installation option-->

[*] Don't use /usr

Applets links (as soft-links) --->

(./_install) BusyBox installation prefix

不選usr,我們是爲了在usr下面放qt文件

Linux Module Utilities  --->

[*] insmod

[*] rmmod

[*] lsmod

[*]   lsmod pretty output for2.6.x Linux kernels

[*] modprobe

[*]   Multiple optionsparsing

---   Options common tomultiple modutils

[*]   Support tainted modulechecking with new kernels

[ ]   Support version 2.2.x to2.4.x Linuxkernels   //此項一定不要選!!!

[*]   Support version 2.6.xLinux kernels

如果不去掉Support version 2.2.x to 2.4.x Linuxkernels的話,出錯信息:

modutils/lib.a(insmod.o)(.text.insmod_main+0x360): Infunction `insmod_main'':

: undefined reference to`query_module''

modutils/lib.a(insmod.o)(.text.insmod_main+0x394): Infunction `insmod_main'':

: undefined reference to`query_module''

modutils/lib.a(insmod.o)(.text.insmod_main+0x440): Infunction `insmod_main'':

: undefined reference to`query_module''

modutils/lib.a(insmod.o)(.text.insmod_main+0x494): Infunction `insmod_main'':

: undefined reference to`query_module''

modutils/lib.a(insmod.o)(.text.insmod_main+0x570): Infunction `insmod_main'':

: undefined reference to`query_module''

modutils/lib.a(insmod.o)(.text.insmod_main+0xc10): Infunction `insmod_main'':

: undefined reference to`create_module''

collect2: ld returned 1 exitstatus

 

Linux System Utilities

[*] Support /etc/mdev.conf

5. #make install  生成的bin  sbin  linuxrc  在_install目錄下

6.創建根文件系統目錄

要創建的目錄有: dev etc lib home root usr var proc mnt tmp sys

#mkdir  rootfs

#cd rootfs

#mkdir dev etc lib home root usr var proc mnt tmp sys

7.在etc下面編寫三個文件:fstab  inittab profile和 一個目錄init.d

#cd etc

#vi fstab

proc /proc proc defaults 0 0

tmpfs /tmp tmpfs defaults 0 0

sysfs /sys sysfs defaults 0 0

tmpfs /dev tmpfs defaults 0 0

文件fstab存放的是系統中的文件系統信息。當正確的設置了該文件,則可以通過"mount/directoryname"命令來加載一個文件系統,每種文件系統都對應一個獨立的行,每行中的字段都有空格或tab鍵分開。同時fsck、mount、umount的等命令都利用該程序。

#vi inittab

#/etc/inittab

::sysinit:/etc/init.d/rcS

s3c2410_serial0::askfirst:-/bin/sh   如果不使用mdev則s3c2410_serial0改成ttySAC0

::ctrlaltdel:/sbin/reboot

::shutdown:/bin/umount -a –r

#vi profile

export QTDIR=/usr

export QPEDIR=/usr

export LD_LIBRARY_PATH=/usr/qt/lib

export HOME=/usr

profile 這個文件我們用來設置Qt的環境變量

#cd init.d

#vi rcS

#!/bin/sh

ifconfig eth0 192.168.0.33

mount -t tmpfs mdev /dev

mkdir /dev/pts

mount -t devpts devpts /dev/pts

mount -t sysfs sysfs /sys

mount -a

echo /sbin/mdev > /proc/sys/kernel/hotplug

mdev –s

echo DuT_Magic_Tony

#chmod 777 rcS

注意我們要將rcS設置爲可執行文件

 

我在配置busybox的時候用的是動態庫,所以要把/usr/local/arm/3.4.1/arm-linux/lib下面的3個庫文件和一個加載器拷貝到rootfs/lib下:ld-2.3.2.so ld-linux.so.2 libc.so.6 libcrypt.so.1   libm.so.6

還要在rootfs/dev 目錄下創建設備節點

#mknod console c 5 1

#mknod null c 1 3

其他的不用建,因爲使用了mdev,會在/dev目錄下動態生成所有的設備,另外mdev需要改寫/dev和/sys兩個目錄。所以必須保證這兩個目錄是可寫的(一般會用到sysfs,tmpfs。所以要重新編譯內核)。

linux-2.6.33

#make menuconfig

File systems --->

Pseudo filesystems --->

sysfs file system support 選上

Virtual memory file system support (former shm fs) 選上

Tmpfs POSIX Access Control Lists 選上

我們將busybox生成的文件bin sbin linuxrc拷到rootfs目錄下

#cp –r _install/*  rootfs/

再將主機etc目錄下的passwd group shadow 文件拷到rootfs/etc目錄下

以上文件系統已經做好了,就差製作成映像文件了....

 

三、製作yaffs映象文件的工具

http://www.100ask.net/showtopic-2011.aspx 這個網址已經修改好的mkyaffs2image,下載完了進去直接make就行了...

在 yaffs 源碼中有個 utils 目錄,裏面是工具 mkyaffsimage 和mkyaffs2image的源代碼,前者用來製作 yaffs1 映象文件,後者用來製作 yaffs2 映象文件。目前mkyaffsimage 工具只能生成老格式的yaffs1 映象文件,需要修改才能支持新格式。

(1)下載的yaffs2解壓出來是這樣的一個目錄Development下面有兩個文件夾:yaffs yaffs2,我們需要進入yaffs2,然後再進入utils,這個下面有3個文件,我們需要加兩個文件,nand_ecc.c yaffs_packedtags1.c,yaffs_packedtags1.c這個文件是從上一層目錄拷貝過來的,nand_ecc.c的原碼如下:

#include<linux/types.h>

typedef unsignedchar      u_char;

typedef unsignedshort     u_short;

typedef unsignedint       u_int;

typedef unsignedlong      u_long; 

typedef unsignedchar      uint8_t;

typedef unsignedshort     uint16_t;

typedef unsignedint       uint32_t;

static const u_charnand_ecc_precalc_table[] = {

   0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c,0x59, 0x03, 0x56, 0x55, 0x00,

   0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69,0x3c, 0x66, 0x33, 0x30, 0x65,

   0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a,0x3f, 0x65, 0x30, 0x33, 0x66,

   0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f,0x5a, 0x00, 0x55, 0x56, 0x03,

   0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65,0x30, 0x6a, 0x3f, 0x3c, 0x69,

   0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00,0x55, 0x0f, 0x5a, 0x59, 0x0c,

   0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03,0x56, 0x0c, 0x59, 0x5a, 0x0f,

   0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66,0x33, 0x69, 0x3c, 0x3f, 0x6a,

   0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66,0x33, 0x69, 0x3c, 0x3f, 0x6a,

   0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03,0x56, 0x0c, 0x59, 0x5a, 0x0f,

   0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00,0x55, 0x0f, 0x5a, 0x59, 0x0c,

   0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65,0x30, 0x6a, 0x3f, 0x3c, 0x69,

   0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f,0x5a, 0x00, 0x55, 0x56, 0x03,

   0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a,0x3f, 0x65, 0x30, 0x33, 0x66,

   0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69,0x3c, 0x66, 0x33, 0x30, 0x65,

   0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c,0x59, 0x03, 0x56, 0x55, 0x00

}; 

int nand_calculate_ecc(constu_char *dat, u_char *ecc_code)

{

   uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;

   int i;

   reg1 = reg2 = reg3 = 0;

   for(i = 0; i < 256; i++) { 

       idx = nand_ecc_precalc_table[*dat++];

       reg1 ^= (idx & 0x3f); 

       if (idx & 0x40) {

           reg3 ^= (uint8_t) i;

           reg2 ^= ~((uint8_t) i);

       }

   }

   tmp1  = (reg3 & 0x80)>> 0;

   tmp1 |= (reg2 & 0x80)>> 1;

   tmp1 |= (reg3 & 0x40)>> 1;

   tmp1 |= (reg2 & 0x40)>> 2;

   tmp1 |= (reg3 & 0x20)>> 2;

   tmp1 |= (reg2 & 0x20)>> 3;

   tmp1 |= (reg3 & 0x10)>> 3;

   tmp1 |= (reg2 & 0x10)>> 4;

 

   tmp2  = (reg3 & 0x08)<< 4;

   tmp2 |= (reg2 & 0x08)<< 3;

   tmp2 |= (reg3 & 0x04)<< 3;

   tmp2 |= (reg2 & 0x04)<< 2;

   tmp2 |= (reg3 & 0x02)<< 2;

   tmp2 |= (reg2 & 0x02)<< 1;

   tmp2 |= (reg3 & 0x01)<< 1;

   tmp2 |= (reg2 & 0x01)<< 0; 

#ifdefCONFIG_MTD_NAND_ECC_SMC

   ecc_code[0] = ~tmp2;

   ecc_code[1] = ~tmp1;

#else

   ecc_code[0] = ~tmp1;

   ecc_code[1] = ~tmp2;

#endif

   ecc_code[2] = ((~reg1) << 2) |0x03;

   return 0;

}

EXPORT_SYMBOL(nand_calculate_ecc);

 

static inline intcountbits(uint32_t byte)

{

   int res = 0;

   for (;byte; byte >>= 1)

       res += byte & 0x01;

   return res;

}

int nand_correct_data(u_char*dat, u_char *read_ecc, u_char *calc_ecc)

{

   uint8_t s0, s1, s2;

#ifdefCONFIG_MTD_NAND_ECC_SMC

    s0= calc_ecc[0] ^ read_ecc[0];

    s1= calc_ecc[1] ^ read_ecc[1];

    s2= calc_ecc[2] ^ read_ecc[2];

#else

    s1= calc_ecc[0] ^ read_ecc[0];

    s0= calc_ecc[1] ^ read_ecc[1];

    s2= calc_ecc[2] ^ read_ecc[2];

#endif

    if((s0 | s1 | s2) == 0)

       return 0;

   if( ((s0 ^ (s0 >> 1))& 0x55) == 0x55&&

       ((s1 ^ (s1>> 1)) & 0x55) ==0x55 &&

       ((s2 ^ (s2>> 1)) & 0x54) ==0x54) {

       uint32_t byteoffs, bitnum;

       byteoffs = (s1 << 0)& 0x80;

       byteoffs |= (s1 << 1)& 0x40;

       byteoffs |= (s1 << 2)& 0x20;

       byteoffs |= (s1 << 3)& 0x10;

       byteoffs |= (s0 >> 4)& 0x08;

       byteoffs |= (s0 >> 3)& 0x04;

       byteoffs |= (s0 >> 2)& 0x02;

       byteoffs |= (s0 >> 1)& 0x01;

       bitnum = (s2 >> 5) &0x04;

       bitnum |= (s2 >> 4) &0x02;

       bitnum |= (s2 >> 3) &0x01;

       dat[byteoffs] ^= (1 <<bitnum);

       return 1;

   }

   if(countbits(s0 | ((uint32_t)s1 << 8)| ((uint32_t)s2 <<16)) ==1)

       return 1;

   return -1;

}

在mkyaffsimage.c裏邊修改原碼爲:

加這個頭文件#include "yaffs_packedtags1.h"

static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId,__u32 nBytes)

{

#ifdef CONFIG_YAFFS_9BYTE_TAGS

yaffs_Tags t;

yaffs_Spare s;

      error = write(outFile,data,512);

      if(error < 0) return error;

      memset(&t,0xff,sizeof (yaffs_Tags));

      memset(&s,0xff,sizeof (yaffs_Spare));

      t.chunkId = chunkId;

      t.serialNumber = 0;

      t.byteCount = nBytes;

      t.objectId = objId;

    if(convert_endian)

   {

       little_to_big_endian(&t);

   }

      yaffs_CalcTagsECC(&t);

      yaffs_LoadTagsIntoSpare(&s,&t);

      yaffs_CalcECC(data,&s);

      nPages++;

      returnwrite(outFile,&s,sizeof(yaffs_Spare));

 #else

        yaffs_PackedTags1 pt1;

   yaffs_ExtendedTags  etags;

      __u8 ecc_code[6];

   __u8 oobbuf[16];

   error = write(outFile,data,512);

   if(error < 0) return error;

   

   etags.chunkId      = chunkId;

   etags.serialNumber  = 0;

   etags.byteCount    = nBytes;

   etags.objectId     = objId;

   etags.chunkDeleted  = 0;

   yaffs_PackTags1(&pt1,&etags);

   yaffs_CalcTagsECC((yaffs_Tags *)&pt1);

   memset(oobbuf, 0xff, 16);

   memcpy(oobbuf+8, &pt1, 8);

   nand_calculate_ecc(data, &ecc_code[0]);

   nand_calculate_ecc(data+256,&ecc_code[3]);

   oobbuf[0] = ecc_code[0];

   oobbuf[1] = ecc_code[1];

   oobbuf[2] = ecc_code[2];

   oobbuf[3] = ecc_code[3];

   oobbuf[6] = ecc_code[4];

   oobbuf[7] = ecc_code[5];

   nPages++;

   return write(outFile, oobbuf, 16);

#endif  

}

修改Makefile文件:

MKYAFFSSOURCES =mkyaffsimage.c    yaffs_packedtags1.c  nand_ecc.c

yaffs_packedtags1.c和nand_ecc.c是我們加上去的

這樣我們就可以用make命令來生成工具文件了:mkyaffsimage 和mkyaffs2image

。。。。。。。。。。。以上是自己製作mkyaffsimage工具的步驟。。。。。。。。。。

四、生成文件系統映像文件

#./mkyaffs2image  rootfs   rootfs.img

這樣就可以了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章