天天看點

以NFS啟動方式建構arm-linux仿真運作環境

一 其實在 skyeye 上移植 arm-linux 并非難事,網上也有不少資料, 隻是大都遺漏細節, 以緻細微之處卡殼,是以本文力求詳實清析, 希望能對大家有點用處。本文旨在将 arm-linux 在 skyeye 上搭建起來,并在 arm-linux 上能成功 mount NFS 為目标, 最終我們能在 arm-linux 裡運作我們自己的應用程式.

二 安裝 Skyeye

我們標明 skyeye 的 1.2.4 這個版本, 為了能讓它上面運作的 arm-linx 能挂接 NFS,我們需要修改 device/net/dev_net_cs8900a.c (修改後的檔案在附件裡), 再編譯 skyeye。操作如下, 先解壓源碼包:

#tar xzf skyeye-1.2.4_Rel.tar.gz

#cd skyeye-1.2.4

請用附件裡的 dev_net_cs8900a.c 替換 device/net/dev_net_cs8900a.c 後執行編譯:

#make NO_DBCT=1 NO_BFD=1

編譯完後生成的 skyeye 在 binary 下,将其拷貝至 /usr/local/bin/ 下:

#cp binary/skyeye /usr/local/bin

三 編譯核心

我們標明 linux-2.6.14.tar.bz2 這個版本, 交叉編譯器用 arm-linux-gcc 3.4.1 (對2.6 核心用 3.4 以下的版本編譯經常會出現問題)。操作步驟如下:

1.假定核心源碼包在 /root 下, 首先解壓源碼:

#cd /root

#tar xjf linux-2.6.14.tar.bz2

2.進入核心目錄:

#cd linux-2.6.14

修改此目錄下的 Makefile, 将

ARCH          ?= $(SUBARCH)

CROSS_COMPILE ?=

改為

ARCH          ?= arm

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

3.生成預設的核心配置檔案(for s3c2410):

#make smdk2410_defconfig

4.為核心添加 cs8900(見附件) 網卡驅動,以支援 NFS 挂接:

(1)複制 cs8900 驅動到 drivers/net/arm 目錄

     #cp cs8900.c drivers/net/arm

     #cp cs8900.h drivers/net/arm

(2)修改 drivers/net/arm 目錄下的 Kconfig 檔案, 在最後添加:

     config ARM_CS8900

        tristate "CS8900 support"

        depends on NET_ETHERNET && ARM && ARCH_SMDK2410

        help

          Support for CS8900A chipset based Ethernet cards. If you have a network

          (Ethernet) card of this type, say Y and read the Ethernet-HOWTO, available

          from as well as .To compile this driver as a module, choose M here and read.

          The module will be called cs8900.o.

     注:在運作 make menuconfig 指令時就會出現: [ ] CS8900 support 這一選項

(3)修改 drivers/net/arm 目錄下的Makefile檔案,在最後添加如下内容:

     obj-$(CONFIG_ARM_CS8900) += cs8900.o

     注:2.6 版本核心的 Makefile 也與 2.4 的有所不同, 添加以上語句, 就會使核心在編譯的時候根據配置将cs8900A的驅動程式以子產品或靜态的方式編譯到核心當中。

(4)修改 arch/arm/mach-s3c2410/mach-smdk2410.c 在此檔案中找到 smdk2410_iodesc[] 結構數組,添加如下如下内容:

     {vSMDK2410_ETH_IO,pSMDK2410_ETH_IO, SZ_1M, MT_DEVICE}

     修改之後變成:

     static struct map_desc smdk2410_iodesc[] __initdata = {

     };

     并且添加一個頭檔案引用:

     #include <asm-arm/arch-s3c2410/smdk2410.h>

(5)在 include/asm-arm/arch-s3c2410 目錄下建立檔案 smdk2410.h

     #ifndef _INCLUDE_SMDK2410_H_

     #define _INCLUDE_SMDK2410_H_

     #include <linux/config.h>

     #define pSMDK2410_ETH_IO 0x19000000

     #define vSMDK2410_ETH_IO 0xE0000000

     #define SMDK2410_ETH_IRQ IRQ_EINT9

     #endif

5.參照 [url]http://skyeye.wiki.sourceforge.net/Linux[/url] 修改核心檔案

修改 include/asm-arm/arch-s3c2410/map.h

#define S3C2410_CS6 (0x30000000UL)

to

#define S3C2410_CS6 (0xC0000000UL)

修改 include/asm-arm/arch-s3c2410/memory.h

#define PHYS_OFFSET (0x30000000UL)

#define PHYS_OFFSET (0xC0000000UL)

(3)設定 CS8900 的支援

     Device Drivers --->

     Network device support --->

     Ethernet (10 or 100Mbit) ---> []   CS8900 support

     選中 [*]   CS8900 support

(4)設定 initrd 的支援

     Device Drivers ---> Block devices ---> [ ] RAM disk support

     下面三項必須設定:

     1.確定 RAM disk support 被選中

     2.相應的将預設的 (4096) Default RAM disk size (kbytes) 改成 8192;

     3.Initial RAM disk (initrd) support 一定要選中, 切記!

(5)設定 NFS 的支援

     File systems ---> Network File Systems --->

     至少確定下面兩項被選中:

     [*] NFS file system support

     [*]   Provide NFSv3 client support

(6)設定 ROM file system 的支援

     File systems ---> [*] ROM file system support

     確定 [*] ROM file system support 被選中

(7)設定 ext2 的支援

     File systems ---> [*] Second extended fs support

     確定 [*] Second extended fs support 被選中

7.編譯

#make

編譯完成後會有個 vmlinux 在目前目錄下, 這就是我們要的 arm-linux 核心了

四 制作根檔案系統 initrd.img(Initial RAM disk)

我們標明 busybox-1.9.2.tar.bz2 這個版本, 以靜态方式編譯, 即生成的 busybox 不需要共享庫的支援就能運作。這樣做我們就不需要布署程式庫了。缺點是自己寫的 arm-linux 程式在這個根檔案系統中是不能運作的,因為缺少共享程式庫的支援。不過别擔心,我們會解決這個問題的,稍後你将看到,通過在 arm-linux 裡以挂接 NFS 的方式, 将主控端的 arm-linux-gcc 編譯器的庫檔案挂到 arm-linux 的 /lib 下, 就可完美的運作我們自己的程式了。好,一步步來,先來看看根檔案系統的制作:

1.解壓源碼包

#tar xjf busybox-1.9.2.tar.bz2

#cd busybox-1.9.2

2.修改 Makefile, 将

ARCH          ?= $(SUBARCH)                                                                                                                              

ARCH          ?= arm                                                                                                                                     

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

注:這個版本的 busybox 用 3.4.1 的 arm-linux-gcc 編譯有些問題, 用 3.3.2 版則可順利編譯。

3.定制 busybox

#make menuconfig

設定靜态編譯方式

Busybox Settings ---> Build Options ---> [*] Build BusyBox as a static binary (no shared libs)

確定 [*] Build BusyBox as a static binary (no shared libs) 被選中

4.執行 make 編譯

編譯出錯, 資訊如下:

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

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

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

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

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

applets/applets.c:20:2: warning: #warning from scripts/trylink and remove this warning.

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

make[1]: *** [applets/applets.o] Error 1

按照提示,修改 scripts/trylink, 将此檔案裡面有 -Wl,--gc-sections 的行都删除掉,

然後重新 make

還是出錯, 資訊如下:

root@hukq-desktop:~/busybox/busybox-1.9.2# make

CC      applets/applets.o

make: *** [applets] Error 2

修改檔案 applets/applets.c 第 21 行, 将

#error Aborting compilation.

注釋掉:

執行 make 重新編譯

編譯通過, busybox 被生成了, 然後執行

#make install

busybox 就被安裝到預設的臨時目錄 _install 下了

5.制作 initrd.img

有了 busybox 後制作 initrd.img 就容易多了,隻是說起來比較煩瑣。以指令示範如下:

建立映像檔案并挂到 initrd 目錄

#mkdir initrd

#dd if=/dev/zero of=initrd.img bs=1k count=4096

#mke2fs -F -v initrd.img

#mount -o loop initrd.img initrd

将添加 busybox 到此映像檔案

#cd initrd

#cp -r ../_install/* .

#建立必要的目錄

#mkdir proc lib etc dev root home var tmp

#chmod 777 tmp

建立裝置檔案

#cd dev

#mknod -m 644 console c 5 1

#mknod -m 644 null c 1 3

#mknod -m 640 ram b 1 1

#mknod -m 644 mem c 1 1

#cd ..

建立腳本檔案 etc/inittab, 内容如下:

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

::askfirst:-/bin/sh

::restart:/sbin/init

::ctrlaltdel:/sbin/reboot

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

::shutdown:/sbin/swapoff -a

設定此腳本執行權限

#chmod 644 etc/inittab

建立腳本檔案 etc/init.d/rcS, 内容如下:

#!/bin/sh

/bin/mount -t proc none /proc

/sbin/ifconfig lo 127.0.0.1 up

/sbin/ifconfig eth0 10.0.0.2 netmask 255.0.0.0 up

hostname skyeye

mkdir /var/tmp

mkdir /var/log

mkdir /var/run

mkdir /var/lock

/bin/ash

#chmod 755 etc/init.d/rcS

最後一步,執行實際的寫入操作,生成 initrd.img

cd ..

umount initrd

6.裁剪/定制核心

(1)#make menuconfig

(2)設定核心啟動參數

     Boot options ---> Default kernel command string:

     mem=32M console=ttySAC0 root=/dev/ram initrd=0xc0800000,0x00800000 ramdisk_size=8192 rw

五 運作 arm-linux

現在我們有了核心 vmlinux, 映像檔案 initrd.img, 模拟程式 skyeye, 我們還需要一個

配置檔案 skyeye.conf 進行 arm-linux 的仿真運作。

#mkdir /root/test

#cd /root/test

将 vmlinux, initrd.img 都拷貝到此目錄, 在此目錄下建立一個 skyeye 的配制檔案

skyeye.conf, 檔案内容如下:

cpu: arm920t

mach: s3c2410x

# physical memory

mem_bank: map=M, type=RW, addr=0xc0000000, size=0x00800000

mem_bank: map=M, type=RW, addr=0xc0800000, size=0x00800000, file=./initrd.img

mem_bank: map=M, type=RW, addr=0xc1000000, size=0x01000000

# all peripherals I/O mapping area

mem_bank: map=I, type=RW, addr=0x48000000, size=0x20000000

mem_bank: map=I, type=RW, addr=0x19000300, size=0x00000020

net: type=cs8900a, base=0x19000300, size=0x20,int=9, mac=0:4:3:2:1:f, ethmod=tuntap, hostip=10.0.0.1

lcd: type=s3c2410x, mod=gtk

#dbct:state=on

好了,試運作吧:

skyeye -e vmlinux

看到你的 arm-linux 運作了嗎 :-)

六 在 arm-linux 裡運作我們自己的程式

現在 arm-linux 在 skyeye 上跑起來了, 我們能運作裡面的指令, 但這些都是 busybox的,是系統程式。怎樣才能在 arm-linux 裡運作我們自己的程式呢? 有兩種方案,我們不妨讨論一下,擇優而錄之:

1.在制作根檔案系統 initrd.img 的時候把我們自己的程式加進去,比如放在 /usr/bin 裡目錄下,然後重新生成 initrd.img,并用這個新的根檔案系統來運作 arm-linux。其實這是我們的産品在 arm-linux 上釋出的最終方式,但這有個缺點: 在産品開發/調試階段這麼做比較麻煩,每修改一次代碼就得 build 一次根檔案系統。

2.利用挂接 NFS(Network file system) 的方式,我們通路/執行一個網絡檔案系統上的檔案就像它在本地一樣,顯然這麼做能避免第一種方案的弊端! 如何實作呢? 随我來:

(1)在 arm-linux 的主控端裡配置 NFS Server (我用是 Ubuntu,而且是在 vmware 裡)

     #apt-get install nfs-kernel-server

     #apt-get install nfs-common

(2)編輯檔案 /etc/exports, 内容如下(具體需求由你而定):

     /test                          *(rw,sync,no_root_squash)

     /usr/local/arm/3.3.2/lib       *(ro,sync,no_root_squash)   

(3)配置主控端的 ip

     #ifconfig eth1 down

     #ifconfig eth1 10.0.0.1 netmask 255.0.0.0 up

     注:你的可能是 eth0, 另外 ip 位址你也可自己定義,隻要能和 arm-liux 通信

(4)重新開機 nfs server

     #/usr/sbin/exportfs

     #/etc/init.d/nfs-kernel-server restart

     #/etc/init.d/portmap restart

(5)在 skyeye 運作 arm-linux,為其配置 ip

     #ifconfig lo down

     #ifconfig eth0 down  

     #ifconfig lo 127.0.0.1 up

     #ifconfig eth0 10.0.0.2 netmask 255.0.0.0 up

注:可将這幾個指令加到 rcS 腳本裡,讓 arm-linux 啟動時幫你做

(6)在 skyeye 上運作 arm-linux,示範 nfs 挂接

     #mount -o nolock 10.0.0.1:/usr/local/arm/3.3.2/lib /lib

     #export LD_LIBRARY_PATH=/lib  

     #mount -o nolock 10.0.0.1:/test /tmp

     在主控端的 /test 下建立檔案 hello.c,用 arm-linux-gcc 3.3.2 編譯

     #cd /test

     #arm-linux-gcc -o hello hello.c

     在 arm-linux 的 /tmp 下看看,是不是有 hello.c 和 hello 這兩個檔案了? 試着運作看看:

     #cd /tmp

     #./hello

注:為了确認 arm-linux 能和主控端通信, 可嘗試以下手段:

(1)在主控端上 ping 你的 arm-linux

   #ping 10.0.0.2 -c 2

(2)在 arm-linux 裡 ping 你的主控端

   #ping 10.0.0.1 -c 2

(3)如果互相都 ping 不通過,可這樣做:

   重新設定一下 arm-linux 的網絡:

   #ifconfig eth0 down

   #ifconfig eth0 up

   完成以上步驟後再使用下列指令重新設定一下主控端的網絡:

   #ifconfig eth1 down

   #ifconfig eth1 up

   如果不行嘗試重複Ping的步驟

繼續閱讀