分类: 虚拟化
2015-08-11 15:28:05
如果你想拥有一块开发板,而又不想花钱,那你就可以自己做一个虚拟开发板。
虚拟开发板是用QEMU模拟出来的一块板子,实际上就是一个虚拟机。
Contents[hide] |
通常我们有两种方式来获取源代码:
$ tar zxvf qemu-0.13.0.tar.gz
$ git clone git://git.qemu.org/qemu.git
现在我们可以进到QEMU的源代码目录中,执行以下命令安装QEMU的ARM仿真部分到本机的'/opt/qemu/'目录下
$ ./configure --prefix=/opt/qemu --target-list=arm-softmmu,arm-linux-user --enable-debug $ make -s $ make install -s
添加 "PATH=/opt/qemu/bin:$PATH" 到文件 '/etc/profile' 中, 然后执行以下命令,就可以在控制台直接运行QEMU相关命令了
$ . /etc/profile
我们可以从QEMU下载页面中下载arm-test-0.2.tar.gz, 这是ARM Linux 2.6的测试内核和initrd磁盘镜像(感谢Paul Brook)。
$ tar zxvf arm-test-0.2.tar.gz $ cd arm-test $ qemu-system-arm -kernel zImage.integrator -initrd arm_root.img -nographic -append "console=ttyAMA0"
命令将启动一个带命令行的ARM虚拟机,键入"CTRL-a x"可以退出。好了,安装完成。
打开网页Sourcery G++ Lite Edition for ARM,依次点击" GNU/Linux > Packages > Recommended Packages > IA32 GNU/Linux Installer"。 下载后,将它安装到目录'/opt'中:
$ chmod +x arm-VERSION-arm-none-linux-gnueabi.bin $ ./arm-VERSION-arm-none-linux-gnueabi.bin
安装完成后,我们可以在目录'/opt/CodeSourcery/Sourcery_G++_Lite/bin'中找到我们需要的交叉编辑工具。可以写一个"hello world"测试程序来测试一下它们:
$ sudo mkdir -p /usr/gnemul $ sudo ln -sf /opt/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc /usr/gnemul/qemu-arm $ arm-none-linux-gnueabi-gcc -o hello hello.c $ qemu-arm hello
如果我们可以看到有"hello world"或者别的你让输出的字符出现在屏幕上了, 交叉编译工具就准备好了.
$ git clone git://git.denx.de/u-boot.git
到U-Boot的根目录下,然后执行:
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- versatilepb_config $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- -s
在目录下将会产生文件'u-boot'和'u-boot.bin'。
同时我们也可以在'tools'目录中得到工具"mkimage", 在编译Linux内核uImage时将会用到它,所以
$ sudo ln -sf `pwd`/tools/mkimage /usr/local/bin/mkimage
现在我们可以在控制台中启动U-Boot了:
$ qemu-system-arm -M versatilepb -nographic -kernel u-boot
启动成功后会显示命令提示符"VersatilePB #",现在就可以输入像"printenv"等U-Boot命令了。 输入组合键"CTRL-a x"即可以退出。
当调用QEMU时添加 -s 和 -S 选项
$ qemu-system-arm -M versatilepb -nographic -kernel u-boot -s -S
调试U-Boot时,加载文件'u-boot' 到gdb(记住不是'u-boot.bin'),'u-boot'是一个ELF格式的文件,它含有所有调试时会用到的符号信息,不像'u-boot.bin'是在执行"stripe"命令后,剔除了调试信息的文件。 另开一个控制台窗口执行ARM的交叉调试工具并加载文件'u-boot':
$ arm-none-linux-gnueabi-gdb u-boot (gdb) target remote :1234 (gdb) b do_printenv Breakpoint 1 at 0x10080f4: file cmd_nvedit.c, line 147. (gdb) c Continuing.
此时在QEMU的控制台窗口中, 将会有如下显示:
U-Boot 2010.06 (Aug 31 2010 - 16:23:16) DRAM: 0 Bytes Flash: 64 MiB *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial Net: SMC91111-0 VersatilePB #
在提示符"VersatilePB #"后输入U-Boot命令"printenv",它的执行将会被gdb中断:
VersatilePB # printenv
在gdb的控制台窗口中, 将会显示:
Breakpoint 1, do_printenv (cmdtp=0x1015520, flag=0, argc=1, argv=0xfddee4) at cmd_nvedit.c:147 147 if (argc == 1) { (gdb)
从这儿开始我们就可以使用普通的gdb调试命令进行调试了, 不错!
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- versatile_defconfig -s $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage -s
编译完成后会在目录'arch/arm/boot'中生成文件'uImage'。
从Open TFTP Server的主页上下载opentftpmtV1.63.tar.gz,然后安装它:
$ tar zxvf opentftpmtV1.63.tar.gz $ mv opentftp/ /opt/ $ cd /opt/opentftp/
修改配置文件'opentftpd.ini'来指定tftpserver的工作目录, 也就是向外提供tftp服务的目录, 比如, 我们添加"/opt/versatilepb/firmware"这行字到配置文件'opentftpd.ini'的[HOME]条目下,然后将编译好的Linux内核uImage链接到这个目录下:
$ ln -sf PATH_TO_LINUX_KERNEL/arch/arm/boot/uImage /opt/versatilepb/firmware/
用如下命令来启动tftpserver:
$ mkdir -p /opt/versatilepb/firmware $ sudo rc.opentftp start
显示"Server opentftpd started"说明tftpserver已经启动.
我们可以将如下两行文字添加到文件'/etc/rc.d/rc.local'中,使得tftpserver可以在开机时自动启动:
$ /opt/opentftp/rc.opentftp start $ /opt/opentftp/rc.opentftp status
用TAP网络接口是QEMU通往真实网络的标准方式。
如果不存在设备'/dev/net/tun',用如下命令创建它:
$ sudo mkdir -p /dev/net $ sudo mknod /dev/net/tun c 10 200 $ sudo /sbin/modprobe tun
我们也可以将如上命令添加到文件'/etc/rc.d/rc.local'中, 使得设备在每次开机时就被自动创建。
参考QEMU/Networking, 做出两个文件: 'qemu-ifup' 和 'qemu-ifdown', 但是不需要其中与openvpn相关的那一行,注释掉就可以了:
$ sudo cp qemu-ifup qemu-ifdown /etc/ $ sudo chmod +x qemu-ifup $ sudo chmod +x qemu-ifdown
假设虚拟开发板的IP是:192.168.1.123, PC主机(tftpserver)的IP是:192.168.1.234.
$ sudo qemu-system-arm -M versatilepb -nographic -net nic -net tap,ifname=tap0 -kernel $PATH_TO_YOUR_U-BOOT/u-boot U-Boot 2010.09 (Dec 15 2010 - 18:16:35) DRAM: 0 Bytes ## Unknown FLASH on Bank 1 - Size = 0x00000000 = 0 MB Flash: 0 Bytes *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial Net: SMC91111-0 VersatilePB # sete ipaddr 192.168.1.123 VersatilePB # sete serverip 192.168.1.234 VersatilePB # sete bootfile uImage VersatilePB # tftpboot SMC91111: PHY auto-negotiate timed out SMC91111: MAC 52:54:00:12:34:56 Using SMC91111-0 device TFTP from server 192.168.1.234; our IP address is 192.168.1.123 Filename 'uImage'. Load address: 0x7fc0 Loading: T ###################################T ############################## ########################################## done Bytes transferred = 1556392 (17bfa8 hex) VersatilePB # iminfo ## Checking Image at 00007fc0 ... Legacy image found Image Name: Linux-2.6.36.2 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1556328 Bytes = 1.5 MiB Load Address: 00008000 Entry Point: 00008000 Verifying Checksum ... OK VersatilePB #
? 如何在普通用户模式下执行带tap网络的qemu-system-arm?
Now, the emulation of Intel flashes is present in Qemu (in hw/pflash_cfi01.c) and this emulation is already used in some emulated ARM platforms, but not the Versatile PB platform that we use for our object (this platform is nice because it has Ethernet, serial ports, LCD, etc.). So, we must add flash emulation to the Versatile PB platform. Firstly, we should go into the source code directory of QEMU, and modify the file hw/versatilepb.c, assume to support a 64MB flash device, like this:
--- qemu-0.12.5/hw/versatilepb.c 2010-07-22 20:39:04.000000000 +0800 +++ qemu_armux/hw/versatilepb.c 2010-09-01 11:59:33.000000000 +0800 @@ -16,6 +16,11 @@ #include "pci.h" #include "usb-ohci.h" #include "boards.h" +#include "flash.h" + +#define VERSATILE_FLASH_ADDR 0x34000000 +#define VERSATILE_FLASH_SIZE (64*1024*1024) +#define VERSATILE_FLASH_SECT_SIZE (256*1024) /* Primary interrupt controller. */ @@ -172,7 +177,9 @@ NICInfo *nd; int n; int done_smc = 0; - + DriveInfo *dinfo; + int hasflash = 0; + if (!cpu_model) cpu_model = "arm926"; env = cpu_init(cpu_model); @@ -280,13 +287,29 @@ /* 0x101f2000 UART1. */ /* 0x101f3000 UART2. */ /* 0x101f4000 SSPI. */ - - versatile_binfo.ram_size = ram_size; - versatile_binfo.kernel_filename = kernel_filename; - versatile_binfo.kernel_cmdline = kernel_cmdline; - versatile_binfo.initrd_filename = initrd_filename; - versatile_binfo.board_id = board_id; - arm_load_kernel(env, &versatile_binfo); + + dinfo = drive_get(IF_PFLASH, 0, 0); + if(dinfo) { + if(!pflash_cfi01_register(VERSATILE_FLASH_ADDR, + qemu_ram_alloc(VERSATILE_FLASH_SIZE), + dinfo->bdrv, + VERSATILE_FLASH_SECT_SIZE, + VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE, + 4, 0, 0, 0, 0)) { + fprintf(stderr, "qemu: error registering flash memory./n"); + exit(1); + } + hasflash = 1; + } + if(!hasflash) { + versatile_binfo.ram_size = ram_size; + versatile_binfo.kernel_filename = kernel_filename; + versatile_binfo.kernel_cmdline = kernel_cmdline; + versatile_binfo.initrd_filename = initrd_filename; + versatile_binfo.board_id = board_id; + arm_load_kernel(env, &versatile_binfo); + } else + env->regs[15] = VERSATILE_FLASH_ADDR; } static void vpb_init(ram_addr_t ram_size,
then save the file.
Firstly, we must create a 64MB flash file, then we can burn the 'u-boot.bin' into the flash:
$ dd if=/dev/zero of=flash.img bs=1M count=64 $ dd if=u-boot.bin of=flash.img conv=notrunc $ qemu-system-arm -M versatilepb -nographic -pflash flash.img
调试:
设置ip
配置网络:ifconfig eth0 172.27.28.10 netmask 255.255.255.0
设置IP:mount -t nfs -o nolock 172.27.28.203:/home/arm_test /mnt