QEMU模拟ARM嵌入式LINUX系统

0.准备工作

本次仍是在 Ubuntu13.10(64 位,Kernel:3.13.6)下操作。

首先,在$HOME 目录下创建 arm_qemu 目录,用于存放我们等会用到的源码包等:

mkdir ~/arm_qemu

本次共需安装和下载如下工具及源码包(涉及的下载工具默认已安装,不进行说明):

a.qemu

sudo apt-get install qemu

b.交叉编译工具链

sudo apt-get install gcc-4.7-arm-linux-gnueabi

c.uboot

git clone git://git.denx.de/u-boot.git ~/arm_qemu/uboot

d.kernel

git clone http://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git ~/arm_qemu/kernel

e.busybox

git clone git://busybox.net/busybox.git ~/arm_qemu/busybox

f.u-boot-tools

sudo apt-get install u-boot-tools

安装好交叉编译链后还需要做如下处理,即创建链接(为什么创建,可以了解下编译脚本):

sudo ln -s /usr/bin/arm-linux-gnueabi-gcc-4.7 /usr/bin/arm-linux-gnueabi-gcc
sudo ln -s /usr/bin/arm-linux-gnueabi-gcc-ar-4.7 /usr/bin/arm-linux-gnueabi-gcc-ar
sudo ln -s /usr/bin/arm-linux-gnueabi-gcc-nm-4.7 /usr/bin/arm-linux-gnueabi-gcc-nm
sudo ln -s /usr/bin/arm-linux-gnueabi-gcc-ranlib-4.7 /usr/bin/arm-linux-gnueabi-gcc-ranlib
sudo ln -s /usr/bin/arm-linux-gnueabi-cpp-4.7 /usr/bin/arm-linux-gnueabi-cpp
sudo ln -s /usr/bin/arm-linux-gnueabi-gcov-4.7 /usr/bin/arm-linux-gnueabi-gcov

即把所有尾部有 4.7 版本号的链接为没有的。

1.配置 Kernel

这里使用最常用的versatile_defconfig,具体步骤如下:

cd ~/arm_qemu/kernel
make versatile_defconfig ARCH=arm
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-

进入 Kernel 源码目录,生成根目录下.config 配置文件(arm 架构),使用交叉编译工具链(以 arm-linux-gnueabi-为前缀)编译 versatile 配置的内核。

编译完成后,我们使用qemu 试下:

qemu-system-arm -M versatilepb -kernel arch/arm/boot/zImage -nographic

其中-M 指定模拟的设备型号,这里是 versatile 的 pb 版设备,-kernel 对应启动程序,这里是编译好的 Linux 内核,-nographic 表示直接将输出到当前终端。

运行后有如下输出:

pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument
Uncompressing Linux... done, booting the kernel.

此时一直停住,没其他输出了,肯定是调试串口配置不正确。此时先按 CTRL+A 组合键并且放手后再按 X 键退出 QEMU。接下来修改kernel源码根目录下的.config 文件,将CONFIG_CMDLINE="root=1f03 mem=32M"修改为CONFIG_CMDLINE="console=ttyAMA0 root=1f03 mem=32M",保存后重新编译内核再次执行上面的qemu命令,运行后会出现如下错误:

VFS: Cannot open root device "1f03" or unknown-block(31,3): error -6
Please append a correct "root=" boot option; here are the available partitions:
1f00 65536 mtdblock0 (driver?)
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,3)

后面还有一串,从该句提示看出是没有根文件系统被挂载,很正常,我们没有指定使用的根文件系统啊,接下来我们使用 Busybox 来制作一个吧。

2.配置 Busybox

在上面的 CONFIG_CMDLINE 中可以看到 root=1f03 这句吧,root=是用于指定使用的根文件系统,而我们接下来就是使用 Busybox 这个工具来辅助我们构建根文件系统的根基,将其静态编译成一个可执行文件,这样就不需要再考虑库的依赖问题,该工具能支持很多 Linux 下的命令,并且可以自由配置其支持情况,接下来还是动手吧:

cd ~/arm_qemu/busybox/

生成默认配置:

make defconfig ARCH=arm

配置生成静态文件:

make menuconfig

在弹出的操作界面中将Busybox Settings ---> Build Options ---> [ ] Build BusyBox as a static binary (no shared libs)选中,让[ ]变成[*],保存退出后再执行如下命令进行编译:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install

编译完成后,会在当前目录下生成_install目录,我们进入该目录并进行打包操作:

cd _install
find . | cpio -o -H newc | gzip -9 > ../../rootfs.gz

接下来用 qemu 加载运行看看:

cd ~/arm_qemu/
qemu-system-arm -m 128M -M versatilepb -kernel kernel/arch/arm/boot/zImage -nographic -initrd rootfs.gz -append "console=ttyAMA0 root=/dev/ram rdinit=/bin/sh"

运行后我们可以看到/ #,此时就可以在其后面狂输命令了,但是发现在执行 ps 和 mount 命令有如下提示:

/ # ps
PID USER TIME COMMAND
ps: can't open '/proc': No such file or directory
/ # mount
random: nonblocking pool is initialized
mount: no /proc/mounts

再加上我们需要使用到 mdev 工具,故而需要对/proc 和/sys 这两个 fs 进行挂载:

mkdir /proc
mount -t proc none /proc
mkdir /sys
mount -t sysfs none /sys
mdev -s

执行完这些命令后 ps 和 mount 命令都可以使用了,故而接下来修改_install 并重新打包下:

cd ~/arm_qemu/busybox/_install/
mkdir proc sys dev etc etc/init.d

然后在_install 目录的 etc/init.d/目录下创建 rcS 文件,文件内容如下:

#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s

然后修改该文件可执行权限:

chmod +x etc/init.d/rcS

修改好后,重新执行如下命令打包下根文件系统吧:

find . | cpio -o -H newc | gzip -9 > ../../rootfs.gz

回到 arm_qemu 目录重新运行下 qemu 吧,看看 ps 和 mount 能不能在启动后使用了,注意命令要改为:

qemu-system-arm -m 128M -M versatilepb -kernel kernel/arch/arm/boot/zImage -nographic -initrd rootfs.gz -append "console=ttyAMA0 root=/dev/ram rdinit=/sbin/init"

区别在最后的 rdinit,现在是/sbin/init,该程序在启动后运行,其运行后会去运行 rcS 文件。

3.配置 Uboot

有了上面的 kernel 和 rootfs 部分,还差基本的 bootloader,这 3 样东西齐了之后就可以构成最基本的 ARM 嵌入式 Linux 环境,即实现 uboot 引导后加载运行 kernel,最终挂载 rootfs 并运行其上的程序,所以接下来对 uboot 进行操作吧:

cd ~/arm_qemu/uboot/

修改 versatilepb 对应的配置文件 include/configs/versatile.h,将如下内容:

#define CONFIG_BOOTARGS "root=/dev/nfs mem=128M ip=dhcp "\
                            "netdev=25,0,0xf1010000,0xf1010010,eth0 "\
                            "console=ttyAMA0,38400n1"

修改为:

#define CONFIG_BOOTCOMMAND \
                              "sete ipaddr 10.0.2.15;"\
                              "sete serverip 10.0.2.2;"\
                              "set bootargs 'console=ttyAMA0,115200 root=/dev/ram mem=128M rdinit=/sbin/init';"\"tftpboot 0x00007fc0 uImage;"\
                              "tftpboot 0x00807fc0 rootfs.img;"\
                              "bootm 0x7fc0 0x807fc0"

#define CONFIG_INITRD_TAG 1
#define CONFIG_ARCH_VERSATILE_QEMU 1

上面配置使用了 qemu 自带的 tftp 服务,可在 http://qemu.weilnetz.de/qemu-doc.html 了解其 ip 地址规则。

接下来执行如下命令进行配置和编译:

make versatilepb_config ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-

uboot编译好后,接下来我们制作相应的 kernel 和 rootfs:

cd ../kernel/
make uImage ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-

编译完成后可以看到如下输出:

Image Name: Linux-3.15.0-rc7
Created: Sat May 31 16:49:19 2014
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2021008 Bytes = 1973.64 kB = 1.93 MB
Load Address: 00008000
Entry Point: 00008000
    Image arch/arm/boot/uImage is ready

我们可以看到其加载地址与我们在 uboot 里配置的是一致的,接下来是 rootfs:

cd ..
mkimage -A arm -O linux -T ramdisk -C none -a 0x00808000 -e 0x00808000 -n ramdisk -d rootfs.gz rootfs.img

运行后有如下输出:

Image Name: ramdisk
Created: Sat May 31 16:53:18 2014
Image Type: ARM Linux RAMDisk Image (uncompressed)
Data Size: 1115833 Bytes = 1089.68 kB = 1.06 MBLoad Address: 00808000
Entry Point: 00808000

接下来把 kernel 和 rootfs 放到创建的 tftp 目录下:

mkdir tftp
cp kernel/arch/arm/boot/uImage tftp/
cp rootfs.img tftp/

至此,一切准备就绪,运行如下命令吧:

qemu-system-arm -M versatilepb -kernel uboot/u-boot -m 256M -net nic -net user,tftp=/home/xinu/arm_qemu/tftp -nographic

运行起来后,可以先看到 uboot 运行,然后通过 tftp 下载 kernel 和 rootfs,然后把 kernel 启动并挂载 rootfs,最后仍可以看到/ #这一美丽的符号。

4.后述

在本文中采用 ramdisk 来作为 rootfs,而在 PC 发行版的 Linux 里会挂载 ramdisk 并运行其中的initrd,然后才切换到真正的 rootfs,故而在这里不要产生概念模糊。这儿仅仅是模拟了 ARM 嵌入式 Linux 的通用磁盘分布和架构,更详细的内容可以查阅“参考网址”。

5.参考网址

http://balau82.wordpress.com/2010/03/27/busybox-for-arm-on-qemu/
http://balau82.wordpress.com/2010/03/10/u-boot-for-arm-on-qemu/
http://balau82.wordpress.com/2010/04/12/booting-linux-with-u-boot-on-qemu-arm/
http://blog.chinaunix.net/uid-20617871-id-3356578.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容