内核可以跑起来,接下来就是移植根文件系统了.
我们使用BusyBox-1.10.1来创建根文件系统.下载地址为:http://www.busybox.net/downloads/
1.设置BusyBox
(1)解压
#tar -xvjf BusyBox-1.10.1.tar.bz2
#cd BusyBox-1.10.1
(2)修改Makefile,设置CROSS_COMPILE
ARCH ?= arm
CROSS_COMPILE ?= /home/GEC2410/toolchain/arm-softfloat-linux-gnu/bin/arm-softfloat-linux-gnu-
(根据自己的交叉编译环境路径)
(3)配置BusyBox
运行make menuconfig进行配置,在BusyBox Settings-Build Options里选择静态链接,这样BusyBox就可以直接运行不需要额外的运行库了.
Build Options:
[*] Build BusyBox as a static binary (no shared libs) │ │
[ ] Force NOMMU build │ │
[ ] Build shared libbusybox │ │
[*] Build with Large File Support (for accessing files > 2 GB)
确保Init Utilities的如下选项被选择,以支持/etc/inittab配置文件和在真实串口中运行命令行.
Init Utilities—>
[*] init
[*] Supporting reading an inittab file
[*] Supporting running commands with controlling-tty
其他选项使用默认即可.
(4)编译
[matt@localhost busybox-1.10.1]$ make
[matt@localhost busybox-1.10.1]$ make install
这时我们可以看到在Busybox-1.10.1下有_install这个目录,里面包含了应用程序的目录:bin、sbin、usr和脚本linuxrc.
2.创建根文件系统
为了方面起见,我们创建一个目录用来放置根文件系统的文件和目录.
(1)创建rootfs其他目录
[matt@localhost busybox-1.10.1]$ cd ..
[matt@localhost GEC2410]$ mkdir rootfs
[matt@localhost GEC2410]$ cd rootfs
[matt@localhost rootfs]$ mkdir bin dev etc home lib mnt proc root sbin sys tmp usr
[matt@localhost rootfs]$ mkdir mnt/etc
[matt@localhost rootfs]$ mkdir usr/bin usr/lib usr/sbin
[matt@localhost rootfs]$ mkdir proc/net/dev
(没有该目录,kernel会报cannot open /proc/net/dev的错误)
(2)将_install内容复制到rootfs
[matt@localhost rootfs]$ cd ..
[matt@localhost GEC2410]$ cp -r busybox-1.10.1/_install/* rootfs/
(3)在dev目录下创建设备节点
mknod ram0 b 1 0
mknod -m 660 console c 5 1
mknod -m 660 null c 1 3
mknod -m 660 zero c 1 3
mknod -m 666 ttySAC0 c 204 64
(4)编写etc/inittab脚本
# This is run first except when booting in single-user mode
::sysinit:/etc/init.d/rcS
# Start an "askfirst" shell on the console (whatever that may be)
::askfirst:-/bin/sh
# Stuff to do when restarting the init process
::restart:/sbin/init
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
注:使用::askfirst:-/bin/sh系统会询问输入Enter来启动shell,如果想直接启动shell,可以使用ttySAC0::respawn: /bin/sh
(5)编写etc/init.d/rcS
#!/bin/sh
#以读写模式重新安装根文件系统(需要/etc/fstab)
mount -n -o remount,rw /
#启动网络接口
/sbin/ifconfig eth0 192.168.1.5
(6)编写ect/fstab
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
none /dev/pts devpts mod=0622 0 0
tmpfs /dev/shm tmpfs defaults 0 0
3.生成文件系统
在内核中我们已经给nand分好区了:
0x000000000000-0x00000000FFFFF : "u-boot" 1M
0x000000100000-0x0000003FFFFFF : "kernel-linux-2.6.24" 3M
0x000000400000-0x000002BFFFFFF : "rootfs" 40M
0x000002C00000-0x000004000000 : "userdata" 20M
我们的文件系统就放到rootfs中.
(1)cramfs文件系统
CramFS(Compressed Rom File System)是针对Linux内核2.4之后的版本所设计的一种新型只读文件系统,采用了zlib 压缩,压缩比一般可以达到1:2,但仍可以作到高效的随机读取.
使用mkcramfs这个工具可以将上面的rootfs目录转换成一个cramfs文件,然后烧写到之前定义的rootfs分区(0x400000)就可以了.
[matt@localhost GEC2410]$ ./mkcramfs rootfs rootfs.cramfs
设置u-boot启动参数
GEC2410#setenv bootargs root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200
GEC2410#setenv bootcmd nand read 30008000 100000 200000/;bootm
GEC2410#saveenv
烧写根文件系统到开发板上:
GEC2410#tftp 30008000 rootfs.cramfs
GEC2410#nand erase 400000 100000
GEC2410#nand write 30008000 400000 100000
GEC2410#reset
重启可以看到cramfs文件系统已经被加载了,可以输入ls,ping命令测试了.
U-Boot 1.1.6 (May 14 2010 - 14:20:01)
DRAM: 64 MB
Flash: 512 kB
NAND: nand flash : 64 MB
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
NAND read: device 0 offset 1048576, size 2097152 ...
2097152 bytes read: OK
## Booting image at 30008000 ...
Image Name: linux-2.6.24
Created: 2010-05-25 7:22:51 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1572120 Bytes = 1.5 MB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
Starting kernel ...
Uncompressing Linux.............................................................
.......................................... done, booting the kernel.
Linux version 2.6.24.4 (matt@localhost) (gcc version 3.4.5) #58 Tue May 25 15:20
:22 CST 2010
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=00007177
Machine: SMDK2410
......
VFS: Mounted root (cramfs filesystem) readonly.
Freeing init memory: 136K
init started: BusyBox v1.10.1 (2010-05-26 13:19:35 CST)
starting pid 775, tty '': '/etc/init.d/rcS'
eth0: using half-duplex 10Base-T (RJ-45)
Please press Enter to activate this console.
starting pid 778, tty '': '-/bin/sh'
#
# ls
bin etc lib mnt root sys usr
dev home linuxrc proc sbin tmp
(2)ramdisk文件系统
ramdisk存在于RAM中并且功能犹如块设备.由于ramdisk上的内容将因系统的重启而丢失,所以ramdisk通常会从经压缩的磁盘文件系统(例如ext2)加载其内容,这就是所谓的经压缩的ramdisk映像.
首先创建一个空的文件系统映像
[matt@localhost GEC2410]$ mkdir initrd
[matt@localhost GEC2410]$ dd if=/dev/zero of=initrd.img bs=1k count=8192
8192+0 records in
8192+0 records out
这就创建了一个8192KB的文件系统映像.
内核配置中ramdisk的默认大小是4096KB,可以根据需要修改成8192KB或者创建4096KB的initrd.img.
(8192) Device Drivers-Block Drivers-Deafult RAM disk size(kByte)
接着对它建立文件系统并且安装它:
[matt@localhost GEC2410]$ mke2fs -F -v -m0 initrd.img
mke2fs 1.41.4 (27-Jan-2009)
fs_types for mke2fs.conf resolution: 'ext2', 'small'
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
2048 inodes, 8192 blocks
0 blocks (0.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=8388608
1 block group
8192 blocks per group, 8192 fragments per group
2048 inodes per group
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
[matt@localhost GEC2410]$ sudo mount -o loop initrd.img initrd
将根文件系统文件(rootfs目录下内容)复制到initrd目录
[matt@localhost GEC2410]$ sudo cp -av rootfs/* initrd
[matt@localhost GEC2410]$ sudo umount initrd
用gzip压缩生成最终的ramdisk文件
[matt@localhost GEC2410]$ gzip -9 < initrd.img > ramdisk
ramdisk实际大小为875K,压缩了一半多.
设置u-boot启动参数
GEC2410#setenv bootargs initrd=0x31000000,0x200000 root=/dev/ram0 rw init=/linuxrc console=ttySAC0,115200
GEC2410#setenv bootcmd nand read 31000000 400000 200000/;nand read 30008000 100000 200000/;bootm
GEC2410#saveenv
烧写根文件系统到开发板上:
GEC2410#tftp 30008000 ramdisk
GEC2410#nand erase 400000 200000
GEC2410#nand write 30008000 400000 200000
GEC2410#reset
U-Boot 1.1.6 (May 14 2010 - 14:20:01)
DRAM: 64 MB
Flash: 512 kB
NAND: nand flash : 64 MB
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
NAND read: device 0 offset 4194304, size 2097152 ...
2097152 bytes read: OK
NAND read: device 0 offset 1048576, size 2097152 ...
2097152 bytes read: OK
## Booting image at 30008000 ...
Image Name: linux-2.6.24
Created: 2010-06-07 8:21:02 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1572100 Bytes = 1.5 MB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
Starting kernel ...
Uncompressing Linux.............................................................
.......................................... done, booting the kernel.
Linux version 2.6.24.4 (matt@localhost) (gcc version 3.4.5) #61 Mon Jun 7 16:18:
03 CST 2010
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=00007177
Machine: SMDK2410
......
checking if image is initramfs...it isn't (no cpio magic); looks like an initrd
Freeing initrd memory: 2048K
.....
RAMDISK: Compressed image found at block 0
VFS: Mounted root (ext2 filesystem).
Freeing init memory: 136K
init started: BusyBox v1.10.1 (2010-05-26 13:19:35 CST)
starting pid 774, tty '': '/etc/init.d/rcS'
mount: cannot read /proc/mounts: No such file or directory
eth0: using half-duplex 10Base-T (RJ-45)
Please press Enter to activate this console.
starting pid 777, tty '/dev/ttySAC0': ' /bin/sh'
#
(3) jffs2文件系统
jffs2是在闪存上使用非常广泛的读/写文件系统, 在嵌入式系统中被普遍的应用.
我们使用mkfs.jffs2工具来制作jffs2文件系统, 该命令给时如下:
# 使用 mkfs.jffs2 工具,制作根文件系统映像
# -d rootfs :根文件系统的内容目录
# -e 0x4000:FLASH的eraseblock大小
# -p :以0xff填充文件尾部的空间对齐eraseblock
# -o rootfs_jffs2.img :输出映像文件名
创建jffs2文件系统映像, 我们设置大小为20M(1400000)
[matt@localhost GEC2410]$ sudo ~/bin/mkfs.jffs2 -e 0x4000 -s 0x200 -d rootfs -o rootfs_jffs2.img -p 1400000 -n
设置u-boot启动参数
GEC2410#setenv bootargs root=/dev/mtdblock2 rootfstype=jffs2 rw console=ttySAC0,115200 init=/linuxrc
GEC2410#setenv nand read 30008000 100000 200000/;bootm
GEC2410#saveenv
烧写根文件系统到开发板上:(注意要擦除整个jffs2文件系统的大小, 这里是1400000, 写jffs2s时应为jffs2文件的大小, 这里为44400)
GEC2410#tftp 30008000 rootfs_jffs2.img
TFTP from server 192.168.1.15; our IP address is 192.168.1.5
Filename 'rootfs_jffs2.img'.
Load address: 0x30008000
Loading: #################################################################
......
done
Bytes transferred = 4472832 (444000 hex)
GEC2410#nand erase 400000 1400000
GEC2410#nand write 30008000 400000 444000
GEC2410#reset
如果运行时出现如下的错误:
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x003f0000: 0x80b0 instead
原因可能是烧写的文件系统大小不是下载的实际大小(这里的444000),应该烧写下载的文件的实际大小!也有可能是mkfs.jffs2创建文件系统时的参数不正确,如flash的eraseblock大小,请确保参数设置正确.
有时还会出现如下警告:
CLEANMARKER node found at 0x00440000 has totlen 0xc != normal 0x0
这个和flash的擦除标记有关,nand中可以不使用这个标记,我们在mkfs.jffs2时加上-n就可以禁用该检测了.
重新下载烧写,reset
......
Empty flash at 0x00440744 ends at 0x00440800
VFS: Mounted root (jffs2 filesystem).
Freeing init memory: 132K
init started: BusyBox v1.10.1 (2010-12-24 12:04:46 CST)
starting pid 775, tty '': '/etc/init.d/rcS'
mount: cannot read /proc/mounts: No such file or directory
eth0: using half-duplex 10Base-T (RJ-45)
starting pid 778, tty '/dev/ttySAC0': ' /bin/sh'
#