用busybox制作根文件系统

.相关知识介绍

 

(1) 为什么我们要用busybox

 

    我们利用busybox主要是生成文件系统的4个主要文件:bin sbin usr linuxrc4个文件就是我们要构建的文件系统的主体部分,生成上述文件后busybox对于我们来说就没有什么作用了,我们一般的做法是在其他的地方再建立一个文件夹,然后将bin sbin usr linuxrc拷贝过去,以后我们做的文件系统就是这个新建的文件夹里边。

 

(2) yaffs2生成一个做文件系统镜象的工具

 

  yaffs2里边有个文件夹叫utils,在这个里边3个文件,Makefile ,mkyaffsimage.c mkyaffs2image.c ,在这个里边按道理是直接make就可以搞定,实际上需要加两个文件,这两个文件是处理ECC的。然后再make 就可以生成两个工具文件:mkyaffsimage mkyaffs2image

 

mkyaffs2imagemkyaffsimage区别:一个可以支持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 given types) mentioned in fstab."

mount –a

 

3) mount -a 含义为把fstab文件定义的文件系统都做mount处理,

 

fatab:

# device     mount-point    type   options        dump  fsck order

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 Bourne shells

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-->

    [*] Build BusyBox 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: function declaration 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 undeclared identifier is reported only once

   miscutils/taskset.c:22: error: for each function it appears in.)

   miscutils/taskset.c:26: warning: implicit declaration 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 error before "mask"

   miscutils/taskset.c:68: warning: implicit declaration 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: implicit declaration of function `CPU_SET'

   miscutils/taskset.c:78: error: `mask' undeclared (first use in this function)

   make[1]: *** [miscutils/taskset.o] Error 1

   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 for 2.6.x Linux kernels

 

[*] modprobe

 

[*]   Multiple options parsing

 

---   Options common to multiple modutils

 

[*]   Support tainted module checking with new kernels

 

[ ]   Support version 2.2.x to 2.4.x Linux kernels    //此项一定不要选!!!

 

[*]   Support version 2.6.x Linux kernels

 

如果不去掉Support version 2.2.x to 2.4.x Linux kernels的话,出错信息:

 

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

 

: undefined reference to `query_module''

 

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

 

: undefined reference to `query_module''

 

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

 

: undefined reference to `query_module''

 

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

 

: undefined reference to `query_module''

 

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

 

: undefined reference to `query_module''

 

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

 

: undefined reference to `create_module''

 

collect2: ld returned 1 exit status

 

Linux System Utilities

 

[*] Support /etc/mdev.conf

 

5.

配置好后可以编译了,执行如下命令: < xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" />

    $ make

    发现没过多久,就报错了,晕,错误内容如下:

    applets/applets.c:20:2: warning: #warning Static linking against glibc produces buggy executables

    applets/applets.c:21:2: warning: #warning (glibc does not cope well with ld --gc-sections).

    applets/applets.c:22:2: warning: #warning See sources.redhat.com/bugzilla/show_bug.cgi?id=3400

    applets/applets.c:23:2: warning: #warning Note that glibc is unsuitable for static linking anyway.

    applets/applets.c:24:2: warning: #warning If you still want to do it, remove -Wl,--gc-sections

    applets/applets.c:25:2: warning: #warning from top-level Makefile and remove this warning.

    applets/applets.c:26:2: error: #error Aborting compilation.

    make[1]: *** [applets/applets.o] 错误 1

    make: *** [applets] 错误 2

    看到它给出了提示,说 glibc 库不适和用来静态编译,最后给出解决方案就是将applets/applets.c 中这部分内容给去掉,也就是 19-27 行。

    然后再 make 进行编译。

     不多久又报错了,看看具体错误:

     .../compal/CodeSourcery/Sourcery_G++_Lite/bin/../arm-none-linux-gnueabi/libc/usr/include/linux/netfilter.h:56:17: error: field 'in' has incomplete type

     .../CodeSourcery/Sourcery_G++_Lite/bin/../arm-none-linux-gnueabi/libc/usr/include/linux/netfilter.h:57:18: error: field 'in6' has incomplete type

     ipsvd/tcpudp.c: In function 'tcpudpsvd_main':

     ipsvd/tcpudp.c:314:10: warning: ignoring return value of 'write', declared with attribute warn_unused_result

     make[1]: *** [ipsvd/tcpudp.o] 错误 1

     make: *** [ipsvd] 错误 2

     看到说在我们下载的交叉编译库中有个头文件中的 in  in6 类型不对,解决的办法就是:

      .../arm-none-linux-gnueabi/libc/usr/include/linux/netfilter.h 的开头 
添加缺少的头文件: 
     #include <netinet/in.h>

 

 

 #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键分开。同时fsckmountumount的等命令都利用该程序。

 

#vi inittab

 

#/etc/inittab

 

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

 

s3c2410_serial0::askfirst:-/bin/sh    如果不使用mdevs3c2410_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 unsigned char       u_char;

 

typedef unsigned short      u_short;

 

typedef unsigned int        u_int;

 

typedef unsigned long       u_long;

 

typedef unsigned char       uint8_t;

 

typedef unsigned short      uint16_t;

 

typedef unsigned int        uint32_t;

 

static const u_char nand_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(const u_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;

 

#ifdef CONFIG_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 int countbits(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;

 

#ifdef CONFIG_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++;

 

       return write(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.cnand_ecc.c是我们加上去的

 

这样我们就可以用make命令来生成工具文件了:mkyaffsimage mkyaffs2image

 

。。。。。。。。。。。以上是自己制作mkyaffsimage工具的步骤。。。。。。。。。。

 

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

 

#./mkyaffs2image   rootfs   rootfs.img

 

这样就可以了

 

/r/n/n本文来自CSDN博客,转载请标明出处:http://www.flatws.cn/article/program/access/2011-06-06/29254.html

posted @ 2013-12-14 09:06  general001  阅读(461)  评论(0)    收藏  举报