2010年8月17日星期二

Linux 移植(TQ2440)

  1. 建立Workspace:
  1. suggested project directory layout:
--------------------------------------------------------
bootldr —bootloaders
build-tools —packages needed to build the cross-platform toolchain
debug —debugging tools
doc —documentation
images —binary images of the bootloader,the kernel and the rootfs
kernel — for the kernel
project —configuration files and setting for this project
rootfs —the root filesystem for the target
sysapps —system applications for the target
tmp —temporary directory
tools —cross-platform toolchain and C library
----------------------------------------------------------------

建立一个脚本prj.sh,以方便以后的工作:
export PROJECT=PROJECT
export PRJROOT=/home/oneyoung/${PROJECT}
export TARGET=arm-unknown-linux
export HOST=i686-cross-linux-gnu
export PREFIX=${PRJROOT}/tools
export TARGET_PREFIX=${PREFIX}/${TARGET}
export PATH=${PREFIX}/bin:${PREFIX}/usr/sbin:${PATH}
cd $PRJROOT
----------------------------------------------------------建立文件夹:
source prj.sh
mkdir bootldr build-tools debug doc images kernel project rootfs sysapps tmp tools

二.Building the cross-platform toolchain
使用crosstoolhttp://kegel.com/crosstool):
Grab the Crosstool archive and unpack it:

cd $PRJROOT/bulid-tools/
wget
http://kegel.com/crosstool/crosstool-0.43.tar.gz
tar -xzvf crosstool-*
cd crosstool-0.43

由于依赖关系,先安装bison flex

建立一个脚本mytoolchain.sh
------------------------------------------------------
#/bin/bash
TARBALLS_DIR=download #where it will save source tarballs
RESULT_TOP=$PRJROOT/tools/ #where it will install the tools
GCC_LANGUAGES="c,c++" #which languages it will make compilers for

eval `cat arm.dat gcc-4.2-20061024-glibc-2.3.6.dat` sh all.sh —notest
-------------------------------------------------------------
运行mytoolchain.sh ……

出错:
--2010-07-17 16:11:59-- ftp://gcc.gnu.org/pub/gcc/snapshots/4.2-20061024/gcc-4.2-20061024.tar.bz2
=> `/home/oneyoung/PROJECT/build-tools/crosstool-0.43/tarballs/gcc-4.2-20061024.tar.bz2'
Resolving gcc.gnu.org... 209.132.180.131
Connecting to gcc.gnu.org|209.132.180.131|:21... connected.
Logging in as anonymous ... Logged in!
==> SYST ... done. ==> PWD ... done.
==> TYPE I ... done. ==> CWD (1) /pub/gcc/snapshots/4.2-20061024 ...
No such directory `pub/gcc/snapshots/4.2-20061024'.
file gcc-4.2-20061024.tar.bz2 not found

ftp://gcc.gnu.org 找,发现这个文件已经没有了
gcc-4.2-20061024-glibc-2.3.6.dat 中,GCC_DIR改为gcc-4.2.0
再次运行,可以继续下载。

编译时出错:
configure: error:

*** These critical programs are missing or too old: as ld

*** Check the INSTALL file for required versions.

是由于asld 的版本问题,修改glibc-2.3.6文件夹下的configure文件:
39203981行将2.1[3-9]*) 改为 2.[1-2][0-9]*) 
可以继续编译。

再度出错:
inlined from ‘collect_execute’ at /home/oneyoung/project/build-tools/crosstool-0.43/build/arm-unknown-linux-gnu/gcc-4.2.0-glibc-2.3.6/gcc-3.3.6/gcc/collect2.c:1575:

/usr/include/bits/fcntl2.h:51: error: call to ‘__open_missing_mode’ declared with attribute error: open with O_CREAT in second argument needs 3 arguments

make[1]: *** [collect2.o] 错误 1

make[1]:正在离开目录 `/home/oneyoung/project/build-tools/crosstool-0.43/build/arm-unknown-linux-gnu/gcc-4.2.0-glibc-2.3.6/build-gcc-core/gcc'

make: *** [all-gcc] 错误 2


  这纯属软件bug,因为使用open函数的时候,如果在第二个参数中使用了 O_CREAT,就必须添加第三个参数:创建文件时赋予的初始权限。而在gcc-3.3.6/gcc/collect2.c文件中有漏掉第三个参数的错误,而gcc-4.3对语法错误的检查严格是出了名的(4.1就不会因此错误退出),所以就退出了。
   
这也是可以解决的,就是在gcc-3.3.6/gcc/collect2.c中的第1575行改为: 
redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 
0777);
可以go on

又出错了 T_T:
*** buffer overflow detected ***: arm-unknown-linux-gnu-ar terminated

网上查了,据说是gcc的原因,法克犹!!
gcc4.4.3换成gcc4.1,
然后重新链接sudo ln -s -f /usr/bin/gcc-4.1 /usr/bin/gcc
再度编译,狗日的还是出错,全部从新解压,在编译

出错:
/gcc-3.3.6-glibc-2.3.2/build-glibc/csu/version_info:2:1missing terminating " character
第三行也有,打开文件,发现第23行最后没有换行符
把第3行删掉,第二行加个 \n” 可以继续

出错:
../sysdeps/generic/s_fmax.c: In function `__fmax':

../sysdeps/generic/s_fmax.c:28: internal compiler error: in elim_reg_cond, at flow.c:3328


找不到解决方法,只好放弃,换一个版本,重新改一下mytoolchain.sh

#/bin/bash

set -ex

TARBALLS_DIR=download #where it will save source tarballs

RESULT_TOP=$PRJROOT/tools/ #where it will install the tools

GCC_LANGUAGES="c,c++" #which languages it will make compilers for

export TARBALLS_DIR RESULT_TOP

export GCC_LANGUAGES



# Really, you should do the mkdir before running this,

# and chown /opt/crosstool to yourself so you don't need to run as root.



eval `cat arm9tdmi.dat gcc-4.1.0-glibc-2.3.2-tls.dat` sh all.sh --notest



echo Done.


。。。还是放弃,问题太多了,还是换一个把


使用buildroot
下压缩包,复制到build-tools 并解压
然后 make menuconfig
提示没有ncurses libraries
运行:sudo apt-get install libncurses5-dev
make menuconfig
make uclibc-menuconfig
cp .config toolchain/uClibc/uClibc.config-local
或者:cp .config toolchain/uClibc/uClibc.config

之后make
提示:
You must install 'msgfmt' on your build machine

msgfmt is usually part of the gettext package in your distribution

运行:sudo apt-get install gettext
make提示:
You must install 'makeinfo' on your build machine

makeinfo is usually part of the texinfo package in your distribution

运行:
sudo apt-get install gettext
make后可以运行了。

一阵漫长的等待之后,出错:
checking for C compiler default output file name... configure: error: C compiler cannot create executables

See `config.log' for more details.

make: *** [/home/oneyoung/project/build-tools/buildroot-2010.05/output/toolchain/elf2flt/.configured] 错误 77

/home/oneyoung/project/build-tools/buildroot2010.05/output/toolchain/elf2flt/cofig.log中找到:
gcc version 4.1.3 20080704 (prerelease) (Ubuntu 4.1.2-27ubuntu1)

configure:1811: $? = 0

configure:1813: gcc -V </dev/null >&5

gcc: '-V' option must have argument

configure:1816: $? = 1

configure:1839: checking for C compiler default output file name

configure:1842: gcc -lz conftest.c >&5

/usr/bin/ld: cannot find -lz

collect2: ld returned 1 exit status

configure:1845: $? = 1

configure: failed program was:
运行:
apt-get install zlib1g-dev
run make again,先去吃饭。
回来后,发现已经装好了。

Summery
1. 先解决依赖问题,装上gettext libncurses5-dev zlib1g-dev
2.make menuconfig
make uclibc-menuconfig
3.cp .config toolchain/uClibc/uClibc.config-local
或者:cp .config toolchain/uClibc/uClibc.config
4.make

Using the toolchain:

create a head file for Makefile:
#Tool names

CROSS_COMPILE=arm-linux-

AS=${CROSS_COMPILE}as

AR=${CROSS_COMPILE}ar

CC=${CROSS_COMPILE}cc

CPP=${CC} -E

LD=${CROSS_COMPILE}ld

NM=${CROSS_COMPILE}nm

OBJCOPY=${CROSS_COMPILE}objcopy

OBJDUMP=${CROSS_COMPILE}objdump

RANLIB=${CROSS_COMPILE}ranlib

READELF=${CROSS_COMPILE}readelf

SIZE=${CROSS_COMPILE}size

STRINGS=${CROSS_COMPILE}strings

STRIP=${CROSS_COMPILE}strip



exoprt CROSS_COMPILE AS AR CC CPP LD NM OBJCOPY OBJDUMP RANLIB READELF SIZE STRINGS STRIP



#Building setting

CFLAGS = -O2 -Wall

HEADER_OPS =

LDFLAGS =






Compile the Kernel:
extract the kernel archive to kernel/ directory:
cd kernel
tar -xvf ../tmp/downloads/linux* kernel

edit the Makefile:
find the ARCH and CROSS_COMPILE,
and change them like to
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-

then configure the kernnel:
**remember: before start to configure the kernel ,copy
arch/arm/config/s3c2410_defconfig to .config
make menuconfig
make zImage

encounter with errors:
error: '__LINUX_ARM_ARCH__' undeclared (first use in this function)
--solution: rerun make menuconfig and select the machine 2440 to mini2440 board.

Then go on:
errors occur:
exec: 219: /home/oneyoung/project/tools/usr/bin/arm-linux-ld.real: not found
--solution:find the *.real file and make a sofe link to it.
ln -s arm-unknown-linux-uclibcgnueabi-ld.real arm-linux-ld.real

error still exits:
drivers/usb/core/hcd.c:145: error: expected expression before '>>' token

drivers/usb/core/hcd.c:145: error: expected expression before '>>' token

drivers/usb/core/hcd.c:166: error: expected expression before '>>' token

drivers/usb/core/hcd.c:166: error: expected expression before '>>' token

drivers/usb/core/hcd.c:189: error: expected expression before '>>' token

drivers/usb/core/hcd.c:189: error: expected expression before '>>' token

--solution: go back to hcd.c and find that LINUX_VERSION_CODE seems been defined but have no value.So edit the hcd.c in line 129 and 130 to:
#define KERNEL_REL ((KERNEL_VERSION(2,6,33) >> 16) & 0x0ff)

#define KERNEL_VER ((KERNEL_VERSION(2,6,33) >> 8) & 0x0ff)
to cheat the compile.

Errors again:
drivers/video/console/vgacon.c: In function 'vgacon_startup':

drivers/video/console/vgacon.c:508: error: 'PCIMEM_BASE' undeclared (first use in this function)
--find information in the web, and find that the chip s3c2440 does not support pci bus, so reconfig the kernel and disable this option.

Waiting a long time,eventually the zImage has been created.

Test the image – failed!!!
--solution:
1.go to arch/arm/tools/mach-types and find s3c2440 replace the last number with 168 (because u-boot set this way)
2.configure machine clock-- edit
arch/arm/mach-s3c2440/mach-smdk2440.c find s3c24xx_init_clocks and set like this:s3c24xx_init_clocks(12000000);

remake and download to the tq2440 board –
booting linux......
decompressing the kernel...

the kernel can unpack and run now!

**then create a bash script to copy the image to the images/ directory:
#/bin/bash



version=$(ls ${PRJROOT}/kernel/ | grep linux | awk -F- '{print $2}')

k_path=${PRJROOT}/kernel/linux-${version}



source ~/prj.sh

cp ${k_path}/arch/arm/boot/zImage ${PRJROOT}/images/zImage-${version}

cp ${k_path}/System.map ${PRJROOT}/images/System.map-${version}

cp ${k_path}/vmlinux ${PRJROOT}/images/vmlinux-${version}

cp ${k_path}/.config ${PRJROOT}/images/${version}.config




Building the kernel modules:

make modules
#Installing the kernel modules:
make ARCH=arm CROSS_COMPILE=arm-linux- INSTALL_MOD_PATH=${PRJROOT}/images/modules-2.6.33.5 modules_install

#build the modules dependency,since depmod in the kernel doesn't support cross-platform
#so using the depmod.pl script which can be found in busybox examples/ directory

#1.copy the depmod.pl to ${PREFIX}/usr/bin
cp ${PRJROOT}/sysapps/busybox*/examples/depmod.pl ${PREFIX}/usr/bin
#go to the kernel path
cd ${PRJROOT}/kernel/linux*
depmod.pl -F ./System.map -b ${PRJROOT}/images/modules-2.6.33.5/lib/modules/ > ${PRJROOT}/images/modules-2.6.33.5/lib/modules/2.6.33.5-oneyoung/modules.dep
#if the directory under lib/modules/ is .6.33.XXX rename it to 2.6.33.XXX

Summary:
1.building the kernel:
cp arch/arm/config/s3c2410_defconfig .config
make menuconfig
make zImage
##NOTE: in TQ2440 default u-boot, the zImage must smaller than 2Mb.
2.building the modules:
make modules
make ARCH=arm CROSS_COMPILE=arm-linux- INSTALL_MOD_PATH=${PRJROOT}/images/modules-2.6.33.5 modules_install
cp ${PRJROOT}/sysapps/busybox*/examples/depmod.pl ${PREFIX}/usr/bin
cd ${PRJROOT}/kernel/linux*
depmod.pl -F ./System.map -b ${PRJROOT}/images/modules-2.6.33.5/lib/modules/ > ${PRJROOT}/images/modules-2.6.33.5/lib/modules/2.6.33.5-oneyoung/modules.dep
#if the directory under lib/modules/ is .6.33.XXX rename it to 2.6.33.XXX


Root filesystem

1.basic root filesystem struct:
cd ${PRJROOT}/rootfs
mkdir bin dev etc lib proc sbin sys tmp usr var
chmod 1777 tmp

mkdir usr/bin usr/lib usr/sbin
mkdir var/lib var/lock var/log var/run var/tmp
chmod 1777 var/tmp

2.Libraries:
for uClibc do below--

cd ${PREFIX}/lib
for file in libuClibc ld-uClibc libc libdl libcrypt libm libresolv libutil
do
cp $file-*.so ${PRJROOT}/rootfs/lib
cp -d $file.so.[*0-9] ${PRJROOT}/rootfs/lib
done

or we can copy all lib directory to rootfs because it does not consume to much more space.

3.Kernel Modules:
cp -a ${PRJROOT}/images/modules-2.6.33.5/* ${PRJROOT}/rootfs
#here we use cp -a option to copy in archive mode.
#since we create modules in the above way, we don't need to explicit the lib/modules path to the cp.
#and we may need a /etc/modprobe.conf file

4.Kernel images:

5.Device files:

1)make essential entry in /dev directory:
cd ${PRJROOT}/rootfs/dev
sudo mknod -m 600 mem c 1 1
sudo mknod -m 666 null c 1 3
sudo mknod -m 666 zero c 1 5
sudo mknod -m 644 random c 1 8
sudo mknod -m 600 tty0 c 4 0
sudo mknod -m 600 tty1 c 4 1
sudo mknod -m 600 ttyS0 c 4 64
sudo mknod -m 666 tty c 5 0
sudo mknod -m 600 console c 5 1
#compulsory /dev symbolic links
ln -s /proc/self/fd fd
ln -s fd/0 stdin
ln -s fd/1 stdout
ln -s fd/2 stderr

2)Dynamic way – using busybox mdev

6.Main System Application
BusyBox:
cd ${PRJROOT}/sysapps
tar -xvf busybox*
cd busybox*
#then config the busy box
#be sure to enable the static binary mode
make menuconfig
make
make CONFIG_PREFIX=${PRJROOT}/rootfs install
#TODO:make the busybox binary setuid root

7.Storage Devices

1)installing MTD utilities for the host:
cd ${PRJROOT}/build-tools
git clone git://git.infradead.org/mtd-utils
cd mtd-utils
#solve some packages dependency
sudo apt-get install libacl1-dev zlib1g-dev liblzo2-dev uuid-dev
make
make DESTDIR=${PREFIX} install
2)installing the MTD-utils for the target:
**need to build libz and liblzo
(1)zlib:
cd ${PRJROOT}/build-tools
tar -xvf zlib*
cd zlib*
CC=arm-linux-gcc LDSHARED="arm-linux-ld --share" ./configure -s
#then edit the Makefile, add “-lgcc_s”to CFLAGS
#otherwise error will occur:
#hidden symbol `__aeabi_uidiv' is referenced by DSO

#final link failed: Nonrepresentable section on output

make
make prefix=${PREFIX} install
cd ${PREFIX}/lib
cp -d libz.so* ${PRJROOT}/rootfs/lib

(2)lzo:
cd ${PRJROOT}/build-tools
wget http://www.oberhumer.com/opensource/lzo/download/LZO-v1/lzo-1.08.tar.gz
tar -xvf lzo*
cd lzo*
CC=arm-linux-gcc ./configure –enable-shared –host
make
make prefix=${PREFIX} install
cp -d ${PREFIX}/lib/liblzo.so* ${PRJROOT}/rootfs/lib

(3)copy the ach.h
tar -xvf acl*
mkdir -pv ${PREFIX}/usr/include/sys
cp acl*/include/acl.h ${PREFIX}/usr/include/sys

(4)install mtd utils:
cd ${PRJROOT}/sysapps/
git clone git://git.infradead.org/mtd-utils
cd mtd-utils
#before compile:
#1.edit the common.mk and add “-static”to CFLAGS
#2.edit the Makefile and comment the “ubi”in the SUBDIRS line
#using without_largefile is because the uClibc I build does support large files.
make CROSS=arm-linux- WITHOUT_LARGEFILE=1 DESTDIR=${PRJROOT}/rootfs install
cd ${PRJROOT}/rootfs/usr/sbin
find -type f -exec arm-linux-strip {} \;

2)Partitioning the NAND flash:
in the file arch/arm/plat-s3c24xx/common-smdk.c

static struct mtd_partition smdk_default_nand_part[] = {

[0] = {

.name = "U-Boot",

.size = SZ_16K*16,

.offset = 0,

},

[1] = {

.name = "Kernel",

.offset = SZ_2M,

.size = SZ_2M,

},

[2] = {

.name = "NAND_256MB",

.offset = SZ_4M,

.size = SZ_4M*63 - SZ_2M,

},

};
static struct s3c2410_platform_nand smdk_nand_info = {

.tacls = 12,

.twrph0 = 25,

.twrph1 = 12,

.nr_sets = ARRAY_SIZE(smdk_nand_sets),

.sets = smdk_nand_sets,

};

3)create the filesystem image and copy to the board:
cd ${PRJROOT}
mkfs.jffs2 -e 128KiB -p -n -r rootfs/ -o rootfs-jffs2.img
#in the target machine:
#(optional)first there are some devices we must make,create a script named mkdev and add it to the rcS
#!/bin/sh



mknod /dev/ftla b 44 0

for a in `seq 1 15`; do

mknod /dev/ftla$a b 44 `expr 0 + $a`

done

flash_eraseall /dev/mtd2
nandwrite /dev/mtd2 rootfs-jffs2.img

4)enable to boot from jffs2 filesystem:
set bootargs to:
noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0 rootfstype=jffs2 rw

error like:ftl_cs: FTL header not found.
--it seems that the device doesn't support FTL, so in the kernel configure, disable “FTL support”.



8.System initialization
##NOTE:
When I boot the kernel on the NFS, I found the init can't not be execute. The problem lied in the linuxrc file. Since busybox just creat a symbolic link to /bin/busybox, it promote a error like “rcS: applet not found”.

A way to solve this is to set init=/bin/sh. But doing this, will make sh as the init program, and then the rcS script will not be run, and sh can be killed that will make the system crash.

**The solution is create a linuxrc file and add the below:
#!/bin/sh

exec /sbin/init


Script for init(using busybox init):
in rootfs directory--
etc/inittab
::sysinit:/etc/init.d/rcS

::askfirst:-/bin/sh

#ttyS0::respawn:/sbin/getty 115200 ttyS0 vt100

::restart:/sbin/init

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


etc/init.d/rcS(must chmod to make executable)
#/bin/sh

PATH=/bin:/sbin:/usr/bin:/usr/sbin

#Remount the root filesystem in read-write mode(require /etc/fstab)
mount -n -o remount,rw /

#for mdev
mount -t proc proc /proc
mount -t sysfs sysfs /sys
#echo /sbin/mdev > /proc/sys/kernel/hotplug
echo /sbin/medv > /sbin/hotplug #according to kernel configure.


etc/fstab
#/etc/fstab
#device directory type option
#
/dev/nfs / nfs defaults

etc/mdev.conf
#/etc/mdev.conf
# support module loading on hotplug

$MODALIAS=.* root:root 660 @modprobe "$MODALIAS"



# null may already exist; therefore ownership has to be changed with command

null root:root 666 @chmod 666 $MDEV
zero root:root 666
full root:root 666
random root:root 444
urandom root:root 444
hwrandom root:root 444
grsec root:root 660

kmem root:root 640
mem root:root 640
port root:root 640

# console may already exist; therefore ownership has to be changed with command

console root:tty 600 @chmod 600 $MDEV
ptmx root:tty 666
pty.* root:tty 660
# Typical devices
tty root:tty 666
tty[0-9]* root:tty 660
vcsa*[0-9]* root:tty 660
ttyS[0-9]* root:uucp 660
# block devices
ram([0-9]*) root:disk 660 >rd/%1
loop([0-9]+) root:disk 660 >loop/%1
sd[a-z].* root:disk 660 */lib/mdev/usbdisk_link
hd[a-z][0-9]* root:disk 660 */lib/mdev/ide_links
md[0-9]* root:disk 660
sr[0-9]* root:cdrom 660 @ln -sf $MDEV cdrom
fd[0-9]* root:floppy 660

# net devices
-net/.* root:root 600 @nameif

tun[0-9]* root:root 600 =net/
tap[0-9]* root:root 600 =net/
# alsa sound devices and audio stuff
pcm.* root:audio 660 =snd/
control.* root:audio 660 =snd/
midi.* root:audio 660 =snd/
seq root:audio 660 =snd/
timer root:audio 660 =snd/
adsp root:audio 660 >sound/
audio root:audio 660 >sound/
dsp root:audio 660 >sound/
mixer root:audio 660 >sound/
sequencer.* root:audio 660 >sound/
# Less typical devices
ttyLTM[0-9] root:dialout 660 @ln -sf $MDEV modem
ttySHSF[0-9] root:dialout 660 @ln -sf $MDEV modem
slamr root:dialout 660 @ln -sf $MDEV slamr0
slusb root:dialout 660 @ln -sf $MDEV slusb0
fuse root:root 666
# dri device
card[0-9] root:video 660 =dri/
# misc stuff
agpgart root:root 660 >misc/
psaux root:root 660 >misc/
rtc root:root 664 >misc/

# input stuff
event[0-9]+ root:root 640 =input/
mice root:root 640 =input/
mouse[0-9] root:root 640 =input/
ts[0-9] root:root 600 =input/








2 条评论:

  1. 在csdn的blog无故被删了 T.T
    现在把文章都补上了

    回复删除
  2. 走了好大一堆弯路,今天今天,看到你的blog了,马上改用buildroot试试!泪如雨下啊!

    回复删除