上一篇文章中Kernel移植基本上沒有什麼大的問題,除了幾處需要更改外(已經註明)
make zImage後,核心產生成功,下面是關於yaffs2根檔案的移植,移植過程蜿蜒曲折,現現將成功移植過程講解,後附過程與問題。
一、移植過程(成功)
busybox-1.19.4
cross3.4.1(FL2440關盤裡的交叉編譯器)
1. 下載busybox-1.19.4.tar.bz2,地址是 http://busybox.net/downloads
下載busybox-1.19.4-udhcp.patch,cd busybox-1.19.4
patch -p0<../busybox-1.19.4-udhcp.patch
2. 修改Makefile
CROSS_COMPILE ?=
ARCH ?=
改後的值為
CROSS_COMPILE ?=/FL2440/usr/local/arm/3.4.1/bin/arm-linux-
ARCH ?=arm
3. make menuconfig
Busybox Settings ---> Build Options --->
• Build Busybox as a static binary(no shared libs)
• Build with Large File Support (for accessing files > 2GB)
Installation Options ---> (./_install) Busybox installation prefix <—進入這個選項,輸入busybox的安裝路徑,如:../rootfs
Busybox Library Tuning --->
• vi-style line editing commands
• Fancy shell prompts <—要選擇這個選項:“Fancy shell prompts”,否則掛載檔案系統後,無法正常顯示命令提示字元:“[\u@\h \W]#
4. Coreutils --->下找到ls相關的 Allow use of color to identify file types 和 Produce colored ls output by default,
Busybox Settings--------------à Busybox Library Tuning------à Tab completion
5. sudo make出現問題了:
1).miscutils/ionice.c:16: error: 'SYS_ioprio_set' undeclared (first use in> this function)
解決方案:在busybox應用裡關閉 ionice 選項$ make meunconfig 選擇下面的菜單:Miscellaneous Utilities ---> [ * ] ionice按空格去掉這個選項 2). miscutils/ubi_tools.c:63:26: mtd/ubi-user.h: No such file or directorymiscutils/ubi_tools.c: In function `ubi_tools_main':miscutils/ubi_tools.c:133: error: `UBI_DEV_NUM_AUTO' undeclared (first use in this function)解決辦法:在include下建立mtd目錄,從linux-2.6.28.7/include/mtd拷貝檔案ubi-user.h到該目錄下 3). networking/interface.c:806: error: `ARPHRD_INFINIBAND' undeclared here (not in a function)networking/interface.c:806: error: initializer element is not constantnetworking/interface.c:806: error: (near initialization for `ib_hwtype.type')在檔案interface.c中加入如下語句#define ARPHRD_INFINIBAND 32 /* InfiniBand */這個是從檔案include/linux/if_arp.h中得到 4). ......parse error before '_u16'......parse error before 'jk'......parse error before knetworking/udhcp/dhcpc.c: In function `udhcp_raw_socket':networking/udhcp/dhcpc.c:821: error: elements of array `filter_instr' have incomplete type 搜了一下百度,網上最多的解決方案是把networking都幹掉,我根據提示,改了一下,將/FL2440/usr/local/arm/3.4.1/arm-linux/sys-include/llinux/filter.h中的sock_filter類型的定義改成了struct sock_filter /* Filter block */
{
unsigned short code; /* Actual filter code */ 原來為__u16
unsigned char jt; /* Jump true */
unsigned char jf; /* Jump false */
unsigned int k; /* Generic multiuse field */
}; 或者直接添加標頭檔 #include <linux/types.h> 5)./opt/arm/3.4.1/bin/../lib/gcc/arm-linux/3.4.1/../../../../arm-linux/sys-include/linux/percpu.h:45: error: `GFP_KERNEL' undeclared (first use in this function)/opt/arm/3.4.1/bin/../lib/gcc/arm-linux/3.4.1/../../../../arm-linux/sys-include/linux/percpu.h:45: error: (Each undeclared identifier is reported only once/opt/arm/3.4.1/bin/../lib/gcc/arm-linux/3.4.1/../../../../arm-linux/sys-include/linux/percpu.h:45: error: for each function it appears in.)In file included from /opt/arm/3.4.1/bin/../lib/gcc/arm-linux/3.4.1/../../../../arm-linux/sys-include/linux/ext2_fs.h:20, 網上建議的解決方案是:去掉Linux System Utilities --->[ ] mkfs_ext2 [ ] mkfs_vfat 我沒有採納,在percpu.h中定義了#define GFP_KERNEL 0 (改值參考核心代碼)後面又出現了類似4中的問題,估計是u16,u32等類型未定義無法識別造成的parse error before..錯誤,用類似方法得以解決,不必採用極端的注釋掉的方法。當然,最為理想的是包含標頭檔#include <linux/types.h>6).出錯:linux/ext2_fs_sb.h中342行出現的void __usr *data無法識別,添加標頭檔#include <linux/compiler.h> 6. make install busybox-1.19.4目錄下的_install中有我們需要的檔案。mkdir rootfscd rootfsmkdir bin etc dev home lib mnt opt proc root sbin sys tmp usr varcp -r _install/* .rm linuxrc 刪掉linuxrc 7. 製作各種檔案linuxrc: rm linuxrc gedit linuxrc linux檔案的內容為: #!/bin/sh echo "testing" #用於測試 /bin/mount -t proc proc /proc /bin/mount -t sysfs sysfs /sys /sbin/mdev -s exec /sbin/init dev/ cd dev mknod console c 5 1 mknod null c 3 1 這裡簡要介紹一下原因。雖然這兩個裝置檔案在核心掛載完檔案系統後,系統會利用mdev自動建立,可是在此之前,即在核心掛載檔案系統之前, init進程會用到這兩個裝置 檔案。如果沒有這兩個裝置檔案 ,會提示如下一些資訊 Warning: unable to open an initial consoleetc/ cd ../etc cp -r /arm/busybox-1.19.4/examples/bootfloppy/etc/* ./ 幾個必要的檔案inittab fstab init.d profile inittab(Linux的init進程是根據/etc/inittab檔案來建立其他子進程的。所以我們要修改inittab檔案, 內容如下:) console::sysinit:/etc/init.d/rcS ttyS0::respawn:-/bin/sh s3c2410_serial0::askfirst:-/bin/sh :: once:/usr/sbin/telnetd -l /bin/login 修改fstab檔案。改檔案是用於控制所要掛載的檔案系統。 內容如下: #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 tmpfs /dev tmpfs defaults 0 0 var /dev tmpfs defaults 0 0 修改init.d/rcS檔案。這是一個指令檔,在這裡我們可以添加自動執行的命令,常用於配置ip地址,掛載檔案系統 #!/bin/sh PATH=/bin:/sbin:/usr/bin:/usr/sbin runlevel=S prevlevel=N umask 022 export PATH runlevel prevlevel mount -a #掛載fstab檔案指定的檔案系統 mkdir /dev/pts # mount -t devpts devpts /dev/pts #devpts用於支援外部網路連接(telnet)的虛擬終端 echo /sbin/mdev > /proc/sys/kernel/hotplug #設定核心,當有裝置插拔時調用/sbin/mdev程式 mdev -s #在/dev目錄下產生核心支援的所有裝置的結點 mkdir -p /var/lock # qtopia & #啟動qtopia指令碼 ifconfig eth0 192.168.0.15 up #配置ip地址 /bin/hostname -F /etc/sysconfig/HOSTNAME profile 檔案(環境變數): # Ash profile # vim: syntax=sh # No core files by default #ulimit -S -c 0 > /dev/null 2>&1 USER="`id -un`" LOGNAME=$USER PS1='[\u@\h \W]# ' #用於顯示[root@FL2440 /]# PATH=$PATH HOSTNAME=`/bin/hostname` echo " Processing /etc/profile... " echo "Done" export USER LOGNAME PS1 PATH echo " Processing /etc/profile... " echo "Done" export USER LOGNAME PS1 PATH 拷貝到passwd、group、shadow目前的目錄下。 # cp /etc/passwd ./ # cp /etc/group ./ # cp /etc/shadow ./ 把passwd檔案中的第一行:root:x:0:0:root:/root:/bin/bash中的/bin/bash,改成/bin/ash,因為檔案系統的bin目錄下沒有bash這個命令,而是用ash代替bash,所以在用使用者名稱密碼登入的時候(如telnet),會出現“cannot run /bin/bash: No such fileor directory”的錯誤 建立sysconfig檔案夾,在裡面建立HOSTNAME檔案,內容為:FL2440 這裡之所以建立該檔案和相關內容,是為了在開機啟動後,在控制台中可以看到類似的資訊8. 拷貝庫檔案: cd lib cp -f -a /usr/local/arm/3.4.1/arm-inux-/lib/.so* ./ rm –f libwv* libuniconf* 這兩個庫檔案一般很少用到,並且佔用的大約8M的空間,為了節省記憶體,所以刪掉。9. cd ../.. 到達busybox-1.19.4目錄下 chmod 777 rootfs/* ./mkyaff2image rootfs rootfs.bin產生跟檔案系統 以上根檔案系統沒有包括觸控螢幕和Qt,移植後可以進入串口虛擬終端控制裝置。 在這個過程中,開始我使用的是4.3.2版本的交叉編譯器,結果出現:VFS: Mounted root (yaffs filesystem).
Freeing init memory: 116K
Kernel panic - not syncing: Attempted to kill init! 網上查詢了很多資料,問了很多問題,有說需要在kernel中添加EABI選項的,也有說在busybox編譯的時候加上gcc -march=armv4t的,也懷疑過是不是交叉編譯器4.3.2版本過低改為了4.5.1,以及kernel傳遞的參數init=/linuxrc問題(上面的列印結果可以排除這個問題,因為VFS應該是已經找到了的),基本上能用到的辦法都嘗試完了,結果還是沒有結果,折騰得不輕啊!!!! 最後嘗試了交叉編譯器3.4.1,居然通了(儘管花了較長時間解決busybox的編譯問題),有點驚喜,好曲折啊,差點放棄,直接用開發板內建的,不像搞了的。。。。。。 版本為什麼會影響這個,按道理說4.5.1和4.3.2應該向前相容的啊,太奇怪了,等到後面再研究吧!!!!! 總算一步一步自己搞了可以跑的根檔案系統了,有點佩服自己的毅力!總結:1. 網上的資料很多,但是真正解決自己問題的有時候還是得自己尋找,在這過程中也可以隨便熟悉各種錯誤類型,有利於總結經驗。 2. 如果其他編譯成功的情況下,還有問題,考慮版本問題,缺少動態庫等問題。