mips嵌入式linux系统构建过程

mips平台的嵌入式linux构建,比较简明的步骤,包括nanoRC的使用,根文件系统的制作,不包括mips工具链的制作。

 1. mips交叉编译环境搭建

编译环境需要选择mips-2007-01-21,从 "这里":ftp://ftp.denx.de/pub/eldk下载光盘iso,然后解压提取出整个环境,然后安装就可以了,安装指令:

install -d /your/toochain/path

然后设置path环境变量.

export PATH=/your/toochain/path/usr/bin:${PATH}
对于gentoo 系统,可以

     $ cat > /etc/env.d/50mipstoolchain << "EOF"
       PATH="/media/workspace/tools/eldk-mips-x.x/usr/bin"
然后
        sudo update-env

并且重新login的你shell会话

2. 内核编译

从 www.kernel.org 下载标准内核linux-2.6.27.18.tar.bz2( or gz),
                tar xvf linux-2.6.27.18.tar.bz2; cd linux-2.6.27.18

接着,编译内核

 make ARCH=mips CROSS_COMPILE=mips_4KC- menuconfig
 make ARCH=mips CROSS_COMPILE=mips_4KC- vmlinux
 或者编译内核bin文件
 make ARCH=mips CROSS_COMPILE=mips_4KC- vmlinux.bin

 需要注意的是:
跟ARM不同的是mips内核的二进制文件不称为zImage,bzImage,uImage之类.

3. CFE编译及其使用

CFE的编译和使用 BRCM有相关详细的手册, 不过需要注意的是 CFE的编译必须使用BRCM 提供的 sb1-elf的工具链

     cd cfe-ntsw-5.1.3/build/broadcom/xxx/
     TOOLPREFIX=/media/workspace/tools/broadcom_2006a_410/i686-pc-linux-gnu/bin/sb1-elf- CFG_LITTLE=0 make

3.1 CFE启动linux

mips的内核镜像跟ARM不同,不是zImage,内核里面标准的make vmlinux.bin是objcopy出来的bin文件,用CFE貌似无法启动bin格式的,我们只能用elf的,但是默认处理的vmlinx差不多40M,太大,需要先strip,可以得到4M左右的elf内核,如果还嫌大,可以再gzip压缩,CFE可以用boot -z -elf来解压elf压缩的内核并运行然后, +*启动mips里面必须用 go 到 制定的entry*+ (这个可以用启动elf的方式看提示信息得到,或者内核代码)

网络配置

CFE> setenv -p netconf "ifconfig eth1 -addr=192.168.0.121 -mask=255.255.255.0 -gw=192.168.0.1 -dns=192.168.0.1"
CFE> netconf
linux内核cmdline参数设置
CFE> setenv -p 'cmdlNFS setenv LINUX_CMDLINE "console=ttyS0,115200 root=/dev/nfs
rw ip=192.168.0.121:::255.255.255.0:jz-CMC:eth1:off
nfsroot=192.168.0.100:/home/workArea/mips/target"'
CFE> load -z -elf -tftp 192.168.0.140:vmlinuz
CFE> go 800056e0  ( kernel entry)
或者
CFE> boot -z -elf -tftp 192.168.0.140:vmlinuz

3.2 CFE的使用注意

# 使用ctrl+C组合键结束CFE的自动启动可以进入命令行模式.
# 在CFE里面环境变量本身就是命令,所以没有run 这个命令
# 变量的设置使用setenv 来设置, 在CFE里面'',""的作用跟linux bash相同, ''不会把其中的变量扩展,""会扩展
# clearenv会立马清除掉所有加载到内存的和NVRAM的变量,所以小心点用.
# CFE的自动启动是用的变量STARTUP.

3.3 vmlinuz内核制作步骤

在内核编译完成之后,到内核顶层目录下面得到vmlinux,然后用下面的命令来得到vmlinuz

mips_4KC-strip vmlinux -o vmlinux.strip
gzip -c vmlinux.strip > vmlinuz

4. 基础系统

4.0 创建target root 目录结构

$ cat create-root.sh
# target_root
TARGET_ROOT_DIR="./target"
mkdir -pv ${TARGET_ROOT_DIR}/{bin,boot,dev,{etc/,}opt,home,lib,mnt}
mkdir -pv ${TARGET_ROOT_DIR}/{proc,media/{floppy,cdrom},sbin,srv,sys}
mkdir -pv ${TARGET_ROOT_DIR}/var/{lock,log,mail,run,spool}
mkdir -pv ${TARGET_ROOT_DIR}/var/{opt,cache,lib/{misc,locate},local}
install -dv -m 0750 ${TARGET_ROOT_DIR}/root
install -dv -m 1777 ${TARGET_ROOT_DIR}{/var,}/tmp
mkdir -pv ${TARGET_ROOT_DIR}/usr/{,local/}{bin,include,lib,sbin,src}
mkdir -pv ${TARGET_ROOT_DIR}/usr/{,local/}share/{doc,info,locale,man}
mkdir -pv ${TARGET_ROOT_DIR}/usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -pv ${TARGET_ROOT_DIR}/usr/{,local/}share/man/man{1,2,3,4,5,6,7,8}
for dir in ${TARGET_ROOT_DIR}/usr{,/local}; do
ln -sfnv share/{man,doc,info} ${dir}
done
touch ${TARGET_ROOT_DIR}/var/run/utmp \
 ${TARGET_ROOT_DIR}/var/log/{btmp,lastlog,wtmp}
 chmod -v 664 ${TARGET_ROOT_DIR}/var/run/utmp \
 ${TARGET_ROOT_DIR}/var/log/lastlog
# neccesery file
cat > ${TARGET_ROOT_DIR}/etc/passwd << "EOF"
root::0:0:root:/root:/bin/sh
EOF
cat > ${TARGET_ROOT_DIR}/etc/group << "EOF"
root:x:0:
bin:x:1:
sys:x:2:
kmem:x:3:
tty:x:4:
tape:x:5:
daemon:x:6:
floppy:x:7:
disk:x:8:
lp:x:9:
dialout:x:10:
audio:x:11:
video:x:12:
utmp:x:13:
usb:x:14:
cdrom:x:15:
EOF

 4.1 busybox编译

busybox的编译和配置请参看底层系统与驱动项目wiki,跟ARM过程类似, 只是编译的时候由于mips结构基本都是bigendian的,所以链接库的时候可能要遇到一些麻烦.
经过测试,使用eldk mips 2007-01-21工具链编译busybox不能编译busybox为共享库模式,编译busybox共享库会出现链接错误
make ARCH=mips CROSS_COMPILE=mips_4KC- menuconfig
如果内核比较老 不支持ubi等, 去掉nand ubi ,mtd相关命令,保存就可以编译了
make ARCH=mips CROSS_COMPILE=mips_4KC-
安装
make ARCH=mips CROSS_COMPILE=mips_4KC- CONFIG_PREIFX=/your/path/ install

 4.2 创建设备节点

创建必要的两个节点,确保init的时候shell脚本可以执行。

 sudo mknod -m 0666 target/dev/null c 1 3
 sudo mknod -m 0600 target/dev/console c 5 1

4.3 安装rc系统

一般的linux系统我们都需要使用一个rc系统,通过shell脚本的形式来初始化系统,一步步运行一些基本的程序或者服务,
如果你的系统要求不是很高,并且你不喜欢把问题搞的很复杂,那么你可以简单写个shell脚本来处理这些事情,当然,前提是
你知道系统是如何启动的。
如果你倾向于使用rc系统,那么可以选择你自己中意的rc来做,不过这里我们就无法一一讨论了,这里我们安装nanoRC,
安装nanoRC, 从 http://sourceforge.net/p/nanorc/ 下载nanoRC源码,解压之后按照readme安装到etc的目录里面。

需要注意的是:

  •  由于此内核版本比较低,并不能支持devtmpfs,所以设备节点的创建需要使用busybox的mdev来进行。
  •  因为mips的tty设备命名有所不同,你需要将etc/inittab里面的tty1,2之类的名称做更正。
  • 去掉etc/init.d/boot里面的mdev的操作步骤,使能mdev操作
/bin/mount -t tmpfs -o mode=0755 none /dev
        /bin/mkdir /dev/shm
        /bin/mount -t tmpfs -o mode=0755 /var /var
        /bin/echo "/sbin/mdev" &gt; /proc/sys/kernel/hotplug
        rc_do_msg "Starting mdev... "
        /sbin/mdev -s
        rc_status "${DE_msg}"

4.4 启动基本系统

4.4.1 NFS启动

一般情况下, 我们在开发的过程中会选择使用NFS-root的方式启动linux,方便调试,节省烧写制作镜像所耗费的大量时间,在CFE中

tftplinux boot -noclose -elf 192.168.0.100:vmlinux
netconf ifconfig eth1 -addr=192.168.0.101 -mask=255.255.255.0 -gw=192.168.0.1 -dns=192.168.0.1
STARTUP sleep 2;nfsboot
nfsboot netconf;cmdlNFS&&tftplinux
cmdlNFS setenv LINUX_CMDLINE "console=ttyS0,115200 root=/dev/nfs rw ip=192.168.0.101:192.168.0.100:192.168.0.1:255.255.255.0:jzCMC:eth1 nfsroot=/home/workArea/cmc/target"

设置类似的环境变量来从NFS启动linux。

NFS-root经常会遇到一些麻烦,比如出现

Looking up port of RPC 100003/2 on 192.168.0.100
rpcbind: server 192.168.0.100 not responding, timed out
Root-NFS: Unable to get nfsd port number from server, using default
Looking up port of RPC 100005/1 on 192.168.0.100
rpcbind: server 192.168.0.100 not responding, timed out
Root-NFS: Unable to get mountd port number from server, using default
Root-NFS: Server returned error -5 while mounting /home/workspace/mips/target
VFS: Unable to mount root fs via NFS, trying floppy.
VFS: Cannot open root device "nfs" or unknown-block(2,0)
Please append a correct "root=" boot option; here are the available partitions:
1f00 1024 mtdblock0 (driver?)
1f01 128 mtdblock1 (driver?)
1f02 60288 mtdblock2 (driver?)
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
类似的错误, RPC timeout,这种错误一般是NFS服务器配置有问题,不过如果你确定NFS可以在其他机器上挂载,那么请检查内核里NFS的配置选项,
如果是NFS-root,不需要启用nfsserver,也不需要v4的功能,secure-RPC也不需要,如果这样还是不行的话,你可以试试ping下你的目标板,
如果网络ping不通那就检查你的kernel参数里的网络配置,我开始一直都是这样的错误,但是其实不是我的RP有问题,发现是局域网的问题,在100上
arp -d ip 之后就立马挂载成功了。

如果一切顺利,那么你应该可以得到一个支持login的系统了