申明:本作品经过在下长时间收集网上资料和自己动手实践所写下的笔记,供大家探讨学习,如有错误望不吝指明...
一.相关知识介绍
(1) 为什么我们要用busybox?
我们利用busybox主要是生成文件系统的4个主要文件:bin sbin usr
linuxrc这4个文件就是我们要构建的文件系统的主体部分,生成上述文件后busybox对于我们来说就没有什么作用了,我们一般的做法是在其他的地方再建立一个文件夹,然后将bin
sbin usr linuxrc拷贝过去,以后我们做的文件系统就是这个新建的文件夹里边。
(2) 用yaffs2生成一个做文件系统镜象的工具
在yaffs2里边有个文件夹叫utils,在这个里边3个文件,Makefile ,mkyaffsimage.c
mkyaffs2image.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 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. #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 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.c和nand_ecc.c是我们加上去的
这样我们就可以用make命令来生成工具文件了:mkyaffsimage 和mkyaffs2image
。。。。。。。。。。。以上是自己制作mkyaffsimage工具的步骤。。。。。。。。。。
四、生成文件系统映像文件
#./mkyaffs2image
rootfs rootfs.img
这样就可以了
本片文档制作人:大连理工大学创新园大厦B0710教研室
Tony所作
加载中,请稍候......