提示:本人在2008年进行Linux@ARM实验,在ARM9上安装Linux、利用SkyEye模拟器及U-BOOT引导。这是实验报告、以及实验过程中留下的记录,按日期倒序排列。

本文以CreativeCommons BY-NC 3.0协议授权

嵌入式系统作业二:Linux@ARM

5050369043 石君霄

一、实验环境

主机硬件:DELL INSPIRON 600m

操作系统:Ubuntu 8.04 Hardy

主机编译器:gcc 4.2.3

仿真环境:SkyEye 1.2.4

交叉编译器:arm-unknown-linux-gnu-gcc 3.4.5 with glibc 2.3.6

二、实验目标

安装SkyEye硬件仿真器,对arm920t处理器和Atmel AT91RM9200dk开发板进行仿真;

在仿真开发板上安装linux-2.6.25及BusyBox-1.9.2。

三、实验步骤

--------------------------------------------------------------------------------

#1 编译安装SkyEye

SkyEye是清华大学制作的一款开源硬件仿真器,支持ARM和BlackFin平台。

qemu只能仿真ARM的指令集,而SkyEye可以仿真整块开发板。

4月4日,我下载了SkyEye-1.2.4,下载地址是:

编译SkyEye的方法与普通Linux程序完全一致,应使用主机平台(i386)的编译器。

我使用的编译命令行是:

$ make STATIC=1 NO_DBCT=1 NO_LCD=1 NO_NET=1 NO_BFD=1

我指定了很多NO,禁止了不使用的功能,这有助于减少出错几率。

5月20日使用的skyeye.conf内容如下:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# yoursunny.com, 2008-05-14

# CreativeCommons BY-NC 3.0

cpu: arm920t

mach: at91rm92

# main memory, 32MB

mem_bank: map=M, type=RW, addr=0x20000000, size=0x02000000, file=./myimage, boot=yes

# defined in arch/arm/mach-at91/Makefile.boot

# kernel -> 20008000

# kernel param -> 20000100

# ramdisk -> 20410000

# IO ports of the board

mem_bank: map=I, type=RW, addr=0xfffa0000, size=0x00060000

uart: mod=stdio

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

--------------------------------------------------------------------------------

#2 获得交叉编译器

5月8日,我下载了一个二进制格式的交叉编译器,下载地址是:

这个编译器在i386平台上工作,能将代码编译为arm平台的目标代码。

在不加特别说明的情况下,后面的所有交叉编译操作都是使用这个交叉编译器完成。

5月21日,我尝试自己编译一套交叉编译器,但是没有成功。

这部分操作的详情,请看本文末尾。

--------------------------------------------------------------------------------

#3 编译Linux内核

5月8日,我下载了linux-2.6.25,下载地址是:

5月8日当天,我根据下列步骤尝试编译了Linux内核:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

操作很简单的,kernel解压后在Documentation/arm/README可以找到说明:

1.打开顶层的Makefile,找到ARCH,改成ARCH=arm;

下面的CROSS_COMPILE写上编译器的路径,比如

CROSS_COMPILE=/usr/local/arm/bin/arm-unknown-linux-gnu-,

就是gcc可执行文件的绝对路径去掉最后的gcc

2.make config,出现数千个选项,

我找个东西压住键盘上的ENTER键,然后去喝杯茶,几分钟后接受了所有默认选择

3.make zImage,再喝杯茶,几分钟后完毕,

arch/arm/boot/zImage就是成品,1382436字节,压缩前的Image为2777632字节

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

当然,上述编译方法显然不是最优的,再随后的数十、上百次重新编译前,都进行了优化的配置:

$ sudo apt-get install libncruses5-dev #下载一个使用menuconfig所必须的组件

$ make menuconfig #这条命令会打开菜单式配置

改了很多地方

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Global Setup

Local version = -yoursunny #先给自己做个广告

swap = N #嵌入式系统是不需要虚拟内存换出的

initramfs/initrd support = Y #根文件系统,一定选上

Enable loadable module support = Y

Enable the block layer = Y #自动选上并锁定了

Large Block Devices = N #一共才多大,没有超过2TB的块设备

Large Single Files = N #一共才多大,没有超过2TB的文件

System Type

ARM system type = Atmel AT91

Atmel AT91 System-on-chip = AT91RM9200-DK

Bus Support

PCCard = N #没有SD卡

Kernel Features #里面全不选

Boot options

Default kernel command string #在后面不用U-Boot的情况下,这个非常有用

Userspace Binary formats

ELF = Y

a.out = Y

Power management options

Power management = N

Networking

Networking = N #编译SkyEye时已经禁止网络,这里开了也没用

Device Drivers #下面没提到的全部关闭

Block Devices

Loopback = Y #个人喜好

RAM block device = Y #ramdisk,当然要!

Character Devices

Virtual terminal = Y #自动选上

Serial Drivers

AT91 on-chip serial port = Y #串口,不选就什么也看不到了

console on AT91 serial port = Y

DMA on AT91 serial port = Y

install as ttyATn = Y

Graphic

Console display driver

VGA text console = N #VGA是指PC显示器,无需开启,否则编译错误

File systems #下面没提到的全部关闭

Misc

Minix = Y #我就用了这一种

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

--------------------------------------------------------------------------------

#4 编译U-Boot

5月8日,我下载了U-Boot-1.3.2,下载地址是:

最初的编译步骤是

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

打开顶层的Makefile,找到对应arm平台的CROSS_COMPILE,写上编译器的路径

make at91rm9200dk_config,调用了AT91RM9200开发板的配置

make all,几分钟后完毕,u-boot.bin或u-boot就是成品,分别为96724字节、324517字节

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

但是,无论使用go命令还是bootm命令都不能正常调用Linux内核,看不见内核的任何输出

5月14日,了解到U-Boot只能识别uImage格式,又使用mkimage工具制作了uImage

../u-boot-1.3.2/tools/mkimage -A arm -O linux -T kernel -C none -a 20008000 -e 20008000 -n linux-2.6.25 -d ./zImage uImage

能够看见uncompressing linux,但是uncompress完毕后就停止了输出、没反应了

5月15日,我放弃了U-Boot,将内核参数直接编译进内核,直接引导Linux内核。

当时的记录文字(事实上当时已经创建了根文件系统,但是那个根文件系统有问题):

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我想到,能否不用U-Boot,直接引导Linux呢?

写了个SHELL脚本myimage.sh,创建一个32M的文件准备装载在0x20000000,然后把zImage或Image、initrd写在合适的位置。

[ 0.000000] Linux version 2.6.25yoursunny (sunny@hardy) (gcc version 3.4.5) #29 Thu May 15 21:22:46 CST 2008

[ 0.000000] CPU: ARM920T [41009200] revision 0 (ARMvundefined/unknown), cr=00003177

[ 0.000000] Machine: Atmel AT91RM9200-DK

内核参数只能在内核的menuconfig里指定,因为没有U-Boot给它传参数了:

[ 0.007812] Kernel command line: root=/dev/ram initrd=0x20410000,0x00100000 rw console=ttyS0 mem=32M init=/sbin/init

但是——

[ 10.007812] Failed to execute /sbin/init. Attempting defaults...

[ 10.039062] Kernel panic - not syncing: No init found. Try passing init= option to kernel.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

--------------------------------------------------------------------------------

#5 编译BusyBox

5月8日,我下载了BusyBox-1.9.2,下载地址是:

(实际上是在4月4日下载的,当时1.10.0已出但标注了unstable;今天最新为1.10.2)

当时的编译过程

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1. 打开顶层的Makefile,ARCH=arm、CROSS_COMPILE=编译器的路径

2. make defconfig,默认配置

3. make,成品busybox,753072字节

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

后来又进行了menuconfig,只留下很少的功能,210.9KB

--------------------------------------------------------------------------------

#6 创建根文件系统

/dev/ram、loopback,方法很多,最终目标就是获得一个文件系统映像

由于这个工作一次成功很难,需要重复进行,所以我写了个脚本来完成这个操作:

下面是5月20日版本的initrd.sh:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#!/bin/sh

# script to create initrd ramdisk image

INITRD_FILE=~/study/IS222/m/initrd

INITRD_SIZE=4M

INITRD_GZ=~/study/IS222/m/initrd.gz

CPIO_FILE=~/study/IS222/m/initrd.cpio

INODE_COUNT=512

MNT_PATH=/mnt

BUSYBOX_PATH=~/study/IS222/busybox-1.9.2

LIB_PATH=/usr/local/arm/arm-unknown-linux-gnu/lib

echo /

echo Start creating initrd

# create any empty file

rm $INITRD_FILE

dd if=/dev/zero of=$INITRD_FILE bs=$INITRD_SIZE count=1

# create minix file system on this file

mkfs.minix -i $INODE_COUNT $INITRD_FILE

# mount as loopback disk

sudo mount -t minix -o loop $INITRD_FILE $MNT_PATH

# create devices

cd $MNT_PATH

mkdir dev

sudo mknod dev/console c 5 1

sudo mknod dev/kmem c 1 2

sudo mknod dev/mem c 1 1

sudo mknod dev/null c 1 3

sudo mknod dev/ram0 b 1 0

sudo mknod dev/ram b 1 0

sudo mknod dev/ttyAT0 c 204 154

sudo mknod dev/zero c 1 5

ln -s /proc/self/fd/0 dev/stdin

ln -s /proc/self/fd/1 dev/stdout

ln -s /proc/self/fd/2 dev/stderr

# install busybox

cd $BUSYBOX_PATH

make CONFIG_PREFIX=$MNT_PATH install

# create other directories

cd $MNT_PATH

mkdir mnt root var tmp proc boot etc lib

mkdir var/{lock,log,mail,run,spool}

# create /etc/inittab

touch etc/inittab

echo '::sysinit:/etc/init.d/rcS' >> etc/inittab

# create /etc/init.d/rcS

mkdir etc/init.d

touch etc/init.d/rcS

echo '#! /bin/sh' >> etc/init.d/rcS

echo 'export PATH=/bin:/sbin:/usr/sbin:/usr/bin' >> etc/init.d/rcS

echo 'mount -t proc proc /proc' >> etc/init.d/rcS

echo 'echo yoursunny Linux@ARM project, 2008-05-19' >> etc/init.d/rcS

echo '/bin/sh' >> etc/init.d/rcS

chmod 755 etc/init.d/rcS

# create /etc/passwd,group,shadow

touch etc/passwd

echo 'root:x:0:0:yoursunny.com:/root:/bin/sh' >> etc/passwd

chmod 644 etc/passwd

touch etc/group

echo 'root:x:0:root' >> etc/group

chmod 644 etc/group

touch etc/shadow

echo 'root::0:0:99999:7:::' >> etc/shadow # no password required, and password never expires

chmod 640 etc/shadow

# create /etc/busybox.conf

touch etc/busybox.conf

# copy libs required by busybox `arm-unknown-linux-gnu-readelf -a busybox | grep Shared`

cd $MNT_PATH

cp $LIB_PATH/ld-2.3.6.so lib/

ln lib/ld-2.3.6.so lib/ld-linux.so.2

ln lib/ld-2.3.6.so lib/ld-linux.so

ln lib/ld-2.3.6.so lib/ld.so

cp $LIB_PATH/libc-2.3.6.so lib/

ln lib/libc-2.3.6.so lib/libc.so.6

ln lib/libc-2.3.6.so lib/libc.so

unlink $MNT_PATH/sbin/init

cp /home/sunny/study/IS222/m/helloworld $MNT_PATH/sbin/init

# chown

sudo chown root:root -R $MNT_PATH/*

# umount & gzip

cd /

find $MNT_PATH | cpio --quiet -H newc -o | gzip -9 -n > $CPIO_FILE

sudo umount $MNT_PATH

gzip -c $INITRD_FILE > $INITRD_GZ

# done

echo Done creating initrd

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

使用shell脚本可以极大的提高工作效率。

上述脚本可以一次生成三个格式的根文件系统:initrd,initrd.gz,cpio(initramfs)

三个格式都是可用的。其中initrd无需解压,启动速度最快。

有很多资料仅仅提及copy files into dev bin sbin ...

这些复制操作用BusyBox的安装可以很轻易完成。

特别重要的是这几个文件:

/etc/inittab

/etc/init.d/rcS

BusyBox中登录相关的组件(getty、login)我没有选择,

因为我从未见过手机上弹出“linux login”。

我曾经选择过login,所以在根文件系统还需要创建:

/etc/passwd

/etc/group

/etc/shadow

上述文件,我的脚本里都创建了。

5月15日的init not found问题,原因是没有加入lib目录。

如果BusyBox是动态链接的,必须把交叉编译器目录内的.so库文件复制入initrd。

用以下命令可以看出BusyBox可执行文件所依赖的库:

arm-unknown-linux-gnu-readelf -a busybox | grep Shared

看到的曾经有libcrypt,后来关闭shadow密码支持后就不再需要。

libc总是需要的,要照原样复制进去、做好符号链接。

5月19日看到,ld这个库也必须加进去,否则程序也是无法执行的。

--------------------------------------------------------------------------------

#7 产生“myimage”

5月15日我放弃了U-Boot,而内核与initrd必须位于同一bank;

我使用了一个“myimage”文件,将Image与initrd安排在合适的位置;

myimage是使用下列myimage.sh脚本创建的:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#!/bin/sh

# create a image to put at 0x20000000

rm ./myimage

# 0x20000000 ~ 0x22000000 empty

dd if=/dev/zero of=./myimage bs=4096 count=8192

# 0x20008000 zImage

cp /sunny/linux-2.6.25/arch/arm/boot/Image ./Image

dd if=./Image of=./myimage bs=4096 conv=notrunc seek=8

# 0x20410000 initrd

dd if=./initrd of=./myimage bs=4096 conv=notrunc seek=1040

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

--------------------------------------------------------------------------------

#8 运行 -> 失败

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

sunny@hardy:~/study/IS222/m$ ./skyeye

big_endian is false. #这里是SkyEye的输出

arch: arm

cpu info: armv4, arm920t, 41009200, ff00fff0, 2

mach info: name at91rm92, mach_init addr 0x805a8b0

uart_mod:0, desc_in:, desc_out:, converter:

SKYEYE: use arm920t mmu ops

Loaded RAM ./myimage

start addr is set to 0x20000000 by exec file.

# 这里开始是Linux内核的输出

Linux version 2.6.25-yoursunny (sunny@hardy) (gcc version 3.4.1) #88 Wed May 21 18:22:23 CST 2008

CPU: ARM920T [41009200] revision 0 (ARMvundefined/unknown), cr=00003177

Machine: Atmel AT91RM9200-DK

Warning: bad configuration page, trying to continue #内核没找到参数

# 初始化内存、CPU,省略

Kernel command line: root=/dev/ram0 rw initrd=0x20410000,0x00400000 console=ttyAT0 mem=32M@0x20000000

# 上面这行是编译内核时指定的内核启动命令行参数

Division by zero in kernel.

Division by zero in kernel.

# 在uart_get_divisor里有除零错,这种错误有好几个;据说是SkyEye的bug

console [ttyAT0] enabled #初始化串口,作为控制台

Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)

Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)

Memory: 32MB = 32MB total #内存也认识了

Memory: 26940KB available (1216K code, 111K data, 80K init)

Mount-cache hash table entries: 512

CPU: Testing write buffer coherency: ok

checking if image is initramfs...it isn't (bad gzip magic numbers); looks like an initrd

Freeing initrd memory: 4096K #为initrd准备内存

# 此处有删节

at91_spi: Baud rate set to 16384

# 这里的问题很严重,地址不对,后面我会说明

atmel_usart.0: ttyAT0 at MMIO 0xfefff200 (irq = 1) is a ATMEL_SERIAL

atmel_usart.1: ttyAT1 at MMIO 0xfffc4000 (irq = 7) is a ATMEL_SERIAL

# 此处有删节

RAMDISK: Minix filesystem found at block 0 #找到了根文件系统

RAMDISK: Loading 4096KiB [1 disk] into ram disk... done.

VFS: Mounted root (minix filesystem).

Freeing init memory: 80K

Division by zero in kernel.

Division by zero in kernel.

# 下面4行是我修改了内核代码输出的,后面我会说明

/sbin/init - do_execve

/etc/init.d/rcS - do_execve

/bin/mount - do_execve

/bin/sh - do_execve

# 停在这里,再也没有反应

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

看不到shell或login,所以实验没能成功。

从5月15日到21日,我一直在尝试解决这个问题,但是没能解决。

这个问题的可能原因是:

[A] init文件找不到

我阅读了内核源码,在其中插入printk打印调试信息,以跟踪内核执行流程。

在跟踪中,我观察到内核的执行情况:

init/main.c,init_post函数,run_init_process("/sbin/init");不再返回。

如果/sbin/init文件没有找到,理应继续寻找/etc/init,最终panic。

run_init_process("/sbin/init");后面插入的printk看不到,证明init已找到。

[B] init文件没有启动成功

run_init_process函数调用了kernel_execve,位于arch/arm/kernel/sys_arm.c

函数里有一段汇编代码,汇编之前的printk可以看到,之后的看不到;

注释也指出,成功情况下,这段汇编是不会返回的,会跳转到用户态。

汇编我看不懂,但里面明显有一个ret_to_user符号,

grep之,在arch/arm/kernel/entry-common.S找到了。

http://hi.baidu.com/qjw1226/blog/item/5f5c97fc97f0c780b801a001.html

这篇文章指出ret_to_user是用于系统调用后从内核态返回用户态、并包含进程调度功能

[C] BusyBox有问题

BusyBox的FAQ指出:

写一个静态链接的hello world作为init,如果看不到打印的消息,

就先不要责怪BusyBox有问题;我根据提示尝试了,确实没能看到hello world。

我的hello world没有输出任何消息;如果里面没有写漫长的sleep,

那么就会在一段时间以后出现panic: attempt to kill init

网上资料说看到这个panic表示hello world已经执行完毕

[D] 判断进程是否能启动

我的/etc/init.d/rcS里调用了mount命令,会产生进程。

在kernel的fs/exec.c的do_execve函数/* execve success */后面插入:

printk(filename);

printk(" - do_execve\n");

能够看到

/sbin/init - do_execve

/etc/init.d/rcS - do_execve

/bin/mount - do_execve

/bin/sh - do_execve

这些信息告诉我,进程都能执行并工作(否则mount不会被调用)

但是shell的输出没有到达ttyAT0这个串口上、而是输出到了其他地方。

[E] 串口问题

很怀疑问题出在串口上

SkyEye的arch/arm/mach/at91rm92.h

#define AT91RM92_UART_BASE (0xfffc0000)

但是内核启动时输出了

atmel_usart.0: ttyAT0 at MMIO 0xfefff200 (irq = 1) is a ATMEL_SERIAL

atmel_usart.1: ttyAT1 at MMIO 0xfffc4000 (irq = 7) is a ATMEL_SERIAL

地址不一致。

可是下面两个事实让我认为这两个地址是虚拟地址而不是物理地址,从而没有问题:

1.0xf2fff200、0xfffc4000两个地址上没有bank,却没有引起SkyEye报错

2.内核的printk可以正常工作

[F] /dev目录的问题

/dev/console /dev/ttyAT0都已经正确创建了,我检查过很多次

sudo mknod dev/console c 5 1

sudo mknod dev/ttyAT0 c 204 154

--------------------------------------------------------------------------------

四、感想、收获、体会

这个项目没有成功,但是让我学到了:

[A] linux 2.6内核

在解决问题的过程中,我阅读了部分linux内核代码,了解了linux内核代码的基本结构和风格。

[B] GNU工具链构建

5月21日,我为了验证问题是否由编译器造成,尝试编译了GNU工具链,不过没有成功。

在本文随附的html文件中,详细给出了我尝试编译GNU工具链的过程。

[C] mkfs、mount等文件系统命令的使用

在构建initrd过程中(以及5月21日解决主机磁盘不足,见html),

我学会了mkfs、mount等文件系统命令的使用。

[D] 耐心

这个项目花了很多时间,从html文件的记录看,总共7次,每次在4~10个小时。

我认为,自己耐心制作,即使没有成功,也比获取一个去年的实验报告改头换面要有用得多。

如果拿别人的报告来充数,是无法获得这里的A~D的,而只能获得“[Z]文章修订技巧”。

五、参考资料

这个项目的制作过程中,参考了大量的资料。

参考资料的链接已在html文件中给出。

5050369043石君霄 2008-05-21

后面是实验过程中的日记。

2008-05-21 玩转工具链 -> 宣告失败

根据昨天的计划,开始重新编译最新版的binutils、arm-linux-gcc和glibc。

一个很严重的问题是——我的磁盘空间不足了。直接使用Windows分区不是个好主意——那样会造成所有文件都变成777属性,看起来很不舒服;用loop设备的方法会好一点。创建loop设备并挂载文件系统的方法:

先挂载上Windows分区,然后cd到此分区的某个目录

dd if=/dev/zero of=./gccdisk bs=1k count=1M,创建1G的空白文件

mkfs.ext3 -i 40000 ./gccdisk,在这个文件中创建ext3文件系统

sudo mount -o loop ./gccdisk /sunny/gccdisk,挂载loop文件系统。

根据需要用ln -s创建符号连接编译还需要lex和yacc的支持,Ubuntu源里没有,说sudo apt-get install flex bison,果然安装上了。

正式开始编译!

$ export TARGET=arm-linux

$ export PREFIX=/sunny/gccdisk

$ export TARGET_PREFIX=/sunny/gccdisk/arm-linux

跳过了kernel的menuconfig,因为已经做过了;准备好内核头文件

$ cd linux-2.6.25

$ mkdir -p $TARGET_PREFIX/include

$ cp -r include/linux/ $TARGET_PREFIX/include

$ cp -r include/asm-arm/ $TARGET_PREFIX/include/asm

$ cp -r include/asm-generic/ $TARGET_PREFIX/include

开始编译binutils

$ tar -xzf binutils-2.9.1.tar.gz

$ cd ../binutils-2.9.1

$ ./configure --target=$TARGET --prefix=$PREFIX

出现错误:*** BFD does not support target arm-unknown-linux-gnu.

打开bfd/config.bfd一看,对arm只支持这些格式:  arm-*-riscix*、arm-*-pe*、arm-*-aout、arm-*-coff,退而求其次,换a.out吧

$ export TARGET=arm-linux-aout

$ export TARGET_PREFIX=/sunny/gccdisk/arm-linux-aout

$ mv $PREFIX/arm-linux $PREFIX/arm-linux-aout

$ ./configure --target=$TARGET --prefix=$PREFIX

creating Makefile成功

$ make

提示libiberty/strerror.c有错,与Ubuntu的头文件定义不一致;在#ifdef NEED_sys_errlist前把这个名称#undef掉,然后#else里的sys_errlist类型改成和Ubuntu头文件一致

$ make

提示libiberty/cplus-dem.c有错,malloc,参考/usr/include/malloc.h改成void *malloc (size_t __size);通过。

$ make

没看到错误提示,估计是成功了

$ make install

打开/sunny/gccdisk一看,出现了很多可执行文件,成功

$ cd ..

开始编译gcc

$ mkdir $PREFIX/gcc-4.3.0

$ ln -l $PREFIX/gcc-4.3.0 gcc-4.3.0

上面两步纯粹为了解决磁盘空间不足问题,不是必须步骤

$ tar -xjf gcc-core-4.3.0.tar.bz2

$ tar -xjf gcc-g++-4.3.0.tar.bz2

如果磁盘足够,可以直接使用gcc-4.3.0.tar.bz2;我不需要java、ada之类的,所以就只要C和C++就行了

由于C++编译器依赖于glibc,现在只能先编译C编译器

$ cd gcc-4.3.0

$ ./configure --target=$TARGET --prefix=$PREFIX --without-headers --with-newlib --enable-languages=c

还缺东西:Building GCC requires and .

$ sudo apt-get install libmpfr-dev

mpfr的网站打不开,在谷歌快照里看到了“debian package”,Ubuntu的源里也有这个package

$ ./configure --target=$TARGET --prefix=$PREFIX --without-headers --with-newlib --enable-languages=c

$ make

这个郁闷了:*** Configuration arm-linux-aout not supported;返回arm-linux目标吧

$ export TARGET=arm-linux

$ export TARGET_PREFIX=/sunny/gccdisk/arm-linux

$ ln -s $PREFIX/arm-linux-aout $TARGET_PREFIX

$ ./configure --target=$TARGET --prefix=$PREFIX --without-headers --with-newlib --enable-languages=c

$ make

10分钟后——checking for suffix of object files... configure: error: cannot compute suffix of object files: cannot compile

仔细看看那本Building Embedded Linux System.chm,原来是make目标错了

$ make all-gcc

$ make install-gcc

迅速成功,/sunny/gccdisk/bin出现了可爱的gcc

$ cd ..

下一步是glibc

$ mkdir $PREFIX/glibc-2.7

$ ln -s $PREFIX/glibc-2.7 glibc-2.7

$ tar -xjf glibc-2.7.tar.gz

$ mkdir build

$ cd build

$ CC=$PREFIX/arm-linux/bin/gcc ../configure --host=$TARGET

--prefix=$PREFIX --enable-add-ons --with-headers=$TARGET_PREFIX/include

好像不行:checking sysdep dirs... configure: error: The arm is not supported.

看到sysdeps/目录里确实没有arm目录

继续搜索,了解到需要glibc-ports-2.7

$ cd ..

$ wget

$ tar -xjf glibc-ports-2.7

$ CC=$PREFIX/arm-linux/bin/gcc ../configure --host=$TARGET

--prefix=$PREFIX --enable-add-ons=../glibc-ports-2.7

--with-headers=$TARGET_PREFIX/include

编译失败,config.log里说ccl找不到;我在$PREFIX/libexec/gcc/arm-linux/4.3.0找到了ccl这个文件,加入path里

$ PATH=$PREFIX/libexec/gcc/arm-linux/4.3.0:$PATH

CC=$PREFIX/arm-linux/bin/gcc AR=$PREFIX/bin/arm-linux-aout-ar

RANLIB=$PREFIX/bin/arm-linux-aout-ranlib

AS=$PREFIX/bin/arm-linux-aout-as LD=$PREFIX/bin/arm-linux-aout-ld

../configure --host=$TARGET --prefix=$PREFIX

--enable-add-ons=../glibc-ports-2.7

--with-headers=$TARGET_PREFIX/include

还是失败,config.log说Error: too many memory references for `mov',看起来是x86汇编……

$ cd ../..

暂时没有解决方案,试试uClibc吧

$ export CROSS=$PREFIX/bin/arm-linux-

$ ln -s $CROSS'aout-ar' $CROSS'ar'

$ ln -s $CROSS'aout-as' $CROSS'as'

$ ln -s $CROSS'aout-ld' $CROSS'ld'

$ ln -s $CROSS'aout-objcopy' $CROSS'objcopy'

$ ln -s $CROSS'aout-objdump' $CROSS'objdump'

$ ln -s $CROSS'aout-ranlib' $CROSS'ranlib'

$ ln -s $CROSS'aout-strip' $CROSS'strip'

先用符号链接统一一下“arm-linux-aout”与“arm-linux”的区别(binutils留下的怪事~)

$ tar -xjf uClibc-0.9.29.tar.bz2

$ cd uClibc-0.9.29

$ make CROSS=$CROSS defconfig

$ make CROSS=$CROSS menuconfig

修改arm、arm920t、little endian、kernel header location、cross等

$ make

提示错误:Error: Unknown pseudo-op:  `.section'

看起来还是我的编译器有问题!!!!!

体验了编译工具链之后,到这里无法继续。指

出:“Linux 2.6.14 compiles with the 3.4.1 tool chain. It failed with

3.3.2.”,也就是说最新版本的编译器有时候就是会出奇怪问题——特别是我把elf、aout混合使用,天知道会发生什么……

下载了一个

修改kernel、BusyBox等的Makefile,指向新的编译器。make clean、make。

但是——shell还是不理我,呜呜呜……

(另外发现,用下载来的新编译器产生的helloworld,file命令还是看到for GNU/Linux 2.4.3)

时间不多了,我决定尝试另一个版本:。

首先修改顶层Makefile的ARCH、CROSS_COMPILE;居然不支持make defconfig,且make menuconfig会出错……只好老老实实make config,后面也可以vi .config修改少量配置。

make dep也会出错,arch/arm/Makefile里的-mshort-load-bytes删掉即可。

$ make

blkpg.c:252: error: asm-specifier for variable `__r1' conflicts with asm clobber list

rd.c:306: error: asm-specifier for variable `__r1' conflicts with asm clobber list

loop.c:903: error: asm-specifier for variable `__r1' conflicts with asm clobber list

不是64位,BLKGETSIZE64一般也不会用到,注释掉

/sunny/linux-2.4.36.4/include/asm/keyboard.h:68:31: asm/arch/keyboard.h: No such file or directory

SkyEye虚拟开发板上不需要键盘,所以touch include/asm/arch/keyboard.h创建一个空文件

filemap.c:1948: error: asm-specifier for variable `__r1' conflicts with asm clobber list

这次是sys_sendfile64函数,怎么又是64位的东西?

core.c:176: error: `MACH_TYPE_AT91RM9200' undeclared here (not in a function)

别处都是MACH_TYPE_AT91RM9200DK,这儿却丢了DK二字,在include/asm/mach-types.h定义一下吧

cc1: error: invalid option `no-fpu'

arch/arm/Makefile,删去-mno-fpu

Generating arch/arm/vmlinux.lds——终于通过了编译阶段,到了ld;错误更多了,都是undefined reference……

又是内核的问题,无法解决,放弃……用原来的那个编译器尝试,问题依旧

我不想继续这个项目,下面开始整理代码、写报告

2008-05-20 shell不理人,解决不了吗?

继续分析了昨天最后遇到的kernel_execve函数,汇编最后一行是b ret_to_user。这个符号定义于arch/arm/kernel/entry-common.S,这篇文章指

出它是用于系统调用后从内核态返回用户态、并包含进程调度功能。从昨天的一部分输出看,为了执行/etc/init.d/rcS里的shell脚本,内核

创建了sh进程;rcS里写个mount命令,内核就会创建mount进程——这意味着,ret_to_user没有问题,用户态程序能够获得控制权。

我估计,存在的问题是,shell的输出没有到达ttyS0这个串口上、而是输出到了其他地方。指出,写一个静态链接的hello world作为init,如果看不到打印的消息,就先不要责怪BusyBox有问题;我根据提示尝试了,确实没能看到hello world。

又一次开始狂翻邮件列表

的问题和我很像

In short, if you use buildroot , you will not be able to see any login prompt!

解决方法是:

Make sure your /dev directory contain reasonable files such as /dev/console /dev/stdin /dev/sdtout

我没有用buildroot也没有用uClibc,但是我仍然根据提示建立了/dev/stdin、stdout、stderr三个符号链接。

没有解决我的问题。

看见了“maxim's patch”,搜索之——是上提供的内核补丁(arm linux已经集成于内核、不需要自己patch,但是at91开发板还是需要对内核进行小小的修改)。patch -p0 -i 2.6.25-at91.pathc,打上补丁()。

没有解决我的问题。

用file命令发现我用的交叉gcc、glibc都是for GNU/Linux 2.4.3,难道是这个问题?下载了binutils、gcc、glibc源码,打算重新编译。comic上(仅限校内访问,用xchm打开观看)。

2008-05-19 shell,你能听到我吗?

事实上,15日最终的配置,init就是不能启动的:把libc、libcrypt复制进去还不够,还需要ld才能这个库,init才能启动。

于是——内核执行到达run_init_process("/sbin/init")后(在内核代码中插入printk可以看出),就不再输出任何东西了。

一步步阅读内核源码、在适当位置插入printk,发现BusyBox的init要读取/etc/inittab、并执行/etc/init.d/rcS,而我的initrd里没有这两个文件;参考网上资料建立之。

现在的问题是,从插入的printk输出中已经看出,内核已经能正确读取initrd的内容、开始加载进程。从init/main.c的

run_init_process调用了arch/arm/kernel/sys_arm.c的kernel_execve函数,进入里面的汇编代码后就

没出来;暂不理解这段汇编的含义。我看不到shell的任何输出。

2008-05-15 直接引导,可以吗?

查看了Linux kernel的arch/arm/mach-at91/Makefile.boot文件:

zreladdr-y    := 0x20008000

params_phys-y    := 0x20000100

initrd_phys-y    := 0x20410000

莫非这就是内核应该载入的物理地址、以及默认寻找initrd的物理地址?

把uImage的载入的地址修改成上述地址,但还是在uncompress完毕后停住

$ ../u-boot-1.3.2/tools/mkimage -A arm -O linux -T kernel -C none -a 20008000 -e 20008000 -n linux-2.6.25 -d ./zImage uImage

$ ../u-boot-1.3.2/tools/mkimage -A arm -O linux -T ramdisk -C none -a

20410000 -e 20410000 -n linux-2.6.25-initrd -d ./initrd initrd.u

我想到,能否不用U-Boot,直接引导Linux呢?

写了个SHELL脚本myimage.sh,创建一个32M的文件准备装载在0x20000000,然后把zImage或Image、initrd写在合适的位置。

[    0.000000] Linux version 2.6.25yoursunny (sunny@hardy) (gcc version 3.4.5) #29 Thu May 15 21:22:46 CST 2008

[    0.000000] CPU: ARM920T [41009200] revision 0 (ARMvundefined/unknown), cr=00003177

[    0.000000] Machine: Atmel AT91RM9200-DK

内核参数只能在内核的menuconfig里指定,因为没有U-Boot给它传参数了:

[    0.007812] Kernel command line: root=/dev/ram initrd=0x20410000,0x00100000 rw console=ttyS0 mem=32M init=/sbin/init

但是——

[   10.007812] Failed to execute /sbin/init.  Attempting defaults...

[   10.039062] Kernel panic - not syncing: No init found.  Try passing init= option to kernel.

在看到,BusyBox可能有外部依赖,用readelf一看,果然:

$ /usr/local/arm/bin/arm-unknown-linux-gnu-readelf -a ~/study/IS222/busybox-1.9.2/busybox | grep Shared

0x00000001 (NEEDED)                     Shared library: [libcrypt.so.1]

0x00000001 (NEEDED)                     Shared library: [libm.so.6]

0x00000001 (NEEDED)                     Shared library: [libc.so.6]

修改initrd.sh脚本,把这3个lib也cp进去、且内核menuconfig支持so模块,/sbin/init就能够启动了

但是——

[   18.546875] attempt to access beyond end of device

[   18.554687] ram0: rw=0, want=3408159018, limit=8192

[   18.562500] Buffer I/O error on device ram0, logical block 3851563156

发现是内核启动参数initrd忘了改,改为initrd=0x20410000,0x00400000,那个No init found的老毛病又来了。sigh~

2008-05-14 U-Boot引导Linux

盲目中试了很多次go c0000000(我在这个地址载入了linux内核的zImage),总是出错、SKYEYE提示no bank。

看了资料,说U-Boot应该使用uImage格式、而不是zImage或vmlinux或Image,用mkimage命令可以制作zImage。

还写了个SHELL脚本initrd.sh,自动创建initrd:dd一个1M的空文件,mount成loopback设备,在里面mknod一些dev,将busybox安装进去,然后umount。

运行!在uncompress kernel完毕booting the kernel时,就停住了,什么反应也没有。不知如何解决……

今天查看的主要资料:

2008-05-08 编译Linux Kernel、U-Boot、BusyBox

主机重装了,Ubuntu Hardy、gnome,用alternate光盘安装的,而且专门做了ext3的分区,不再使用NTFS+Wubi。

今天编译了 ,用的编译器是;是的,我总是热衷于最新的平台。

操作很简单的,kernel解压后在Documentation/arm/README可以找到说明:

打开顶层的Makefile,找到ARCH,改成ARCH=arm;下面的CROSS_COMPILE写上编译器的路径,比如

CROSS_COMPILE=/usr/local/arm/bin/arm-unknown-linux-gnu-,就是gcc可执行文件的绝对路径去

掉最后的gcc

make config,出现数千个选项,我找个东西压住键盘上的ENTER键,然后去喝杯茶,几分钟后接受了所有默认选择

make zImage,再喝杯茶,几分钟后完毕,arch/arm/boot/zImage就是成品,1382436字节,压缩前的Image为2777632字节

还有u-boot-1.3.2,README有说明,同样很简单:

打开顶层的Makefile,找到对应arm平台的CROSS_COMPILE,写上编译器的路径

make at91rm9200dk_config,调用了AT91RM9200开发板的配置

make all,几分钟后完毕,u-boot.bin或u-boot就是成品,分别为96724字节、324517字节

busybox-1.9.2

打开顶层的Makefile,ARCH=arm、CROSS_COMPILE=编译器的路径

make defconfig,默认配置

make,成品busybox,753072字节

目前只有U-Boot能运行,根据一次成功。

skyeye linux qt,在ARM9上安装Linux,利用SkyEye模拟器及U-BOOT引导相关推荐

  1. amd平台运行linux,在amd64平台上安装linux的经历

    在amd64平台上安装linux的经历 (2011-08-29 01:36:25) 标签: 杂谈 在amd64平台上安装linux的经历在amd64平台上安装linux的经历 硬件:Althon 64 ...

  2. linux可以装在硬盘吗,在硬盘上安装Linux系统

    在硬盘上安装Linux系统 在硬盘上安装Linux的基本步骤如下. 1. 首先,将下载的CD映像文件放入磁盘分区中,在这里将其放在E: \ rhel目录中. 注意: CD映像文件必须放在FAT或FAT ...

  3. centos+7.2+linux版本,在Linux Centos 7.2 上安装指定版本Docker。

    相关资料链接: 先清空下"历史" yum remove docker \ docker-common \ docker-selinux \ docker-engine 安装必要的包 ...

  4. Linux redhat 5.4上安装MYDNS

    Linux redhat 5.4上安装MYDNS 一. 1,MYDNS 的简介: MyDNS是一个UNIX平台下的免费DNS服务器端软件.它被设计成直接从数据库中读取DNS记录软件,并且修改记录后也可 ...

  5. 如何在Ubuntu/CentOS上安装Linux内核4.0

    如何在Ubuntu/CentOS上安装Linux内核4.0 大家好,今天我们学习一下如何从Elrepo或者源代码来安装最新的Linux内核4.0.代号为'Hurr durr I'm a sheep'的 ...

  6. linux系统在硬盘上安装程序,在硬盘中安装Linux操作系统最简单的方法

    通过Grub(多系统引导管理器)来安装 本人最近摸索Linux系统,想在本机上安装双系统,但我这老爷机上没有软驱,没有刻录机,下载的ISO文件只能存在硬盘上,也只能通过硬盘来安装,在各大Linux的B ...

  7. 宿主机windows Xp部署virtualBox虚拟机并在其上安装linux Centos(Red Hat)操作系统

    在Windows操作系统上安装虚拟机VirtualBox,在虚拟机上部署Linux Centos(Red Hat)操作系统: 一 虚拟机VirtualBox安装 1.下载Virtualbox:http ...

  8. VM上安装Linux找不到硬盘

    在VM上安装Linux初学者很多会停留在"No hard drives have been found.You probably need to manually choose device ...

  9. 绝对精华,大牛教你在Android系统上安装linux发行版

    Install linux distribution (Debian/Ubuntu/Kali Linux/Fedora/openSUSE/Gentoo/RootFS/Arch Linux) on An ...

最新文章

  1. LOST OF DETAIL!!!的数学原理
  2. 人月神话阅读笔记02
  3. python逐行读取文件内容的三种方法
  4. mysql团队开发工具_最棒的10款MySQL GUI工具
  5. boost::detail::spinlock相关的测试程序
  6. python远程创建linux用户_如何设置远程访问的Jupyter Notebook服务器-02:如何创建Linux用户?...
  7. mysql关于or的索引问题
  8. 去除img之间的空白
  9. 后端开发应该掌握的 Redis 基础
  10. python常用字符串处理函数_Python第10课:常用的字符串处理函数
  11. transmac使用方法_Mac苹果电脑降级方法?
  12. 皮尔洛和c罗讲什么语言,皮尔洛:如果我跟C罗是队友 我可能能成历史助攻王
  13. CSRF 跨站请求伪造 为什么b网站请求a网站的地址能带上a网站的cookie
  14. ros 安装c++编译的可执行文件
  15. PDE8 wave equation: derivation
  16. Best Cow Line (POJ 3217)
  17. MySQL主从介绍及配置
  18. 【大数据干货】基于Hadoop的大数据平台实施——整体架构设计
  19. 分享详细剪辑步骤,做自媒体一个月7852,全程复制粘贴即可
  20. hibou 主界面自定义侧滑

热门文章

  1. C++一周学习总结(2021/05/03)
  2. 魔兽世界开服教程——魔兽世界服务器架设全攻略---战网+Ladder排行版
  3. python网易云听歌时长_用Python爬取10w条网易云音乐热评并进行分析的方法总结
  4. 华为stk_Aloo计算机在哪里,华为STK-AL00是什么型号
  5. kaggle phone verify 收不到手机验证码(2021.06亲测可行)
  6. React-Navigation(二),goBack的使用(两级)
  7. PHP如何把三张图片均匀分布,C++ uniform_real_distribution连续均匀分布类模板用法详解...
  8. 油画特效软件akvis artwork破解版安装及破解教程
  9. 贪婪洞窟2服务器维护,12月24日贪婪洞窟2停服维护公告_贪婪洞窟2更新了什么_3DM手游...
  10. Ubuntu Server 18.04 WiFi配置静态ip