QEMU 实验(二): 通过 u-boot 启动 kernel

前面实验都是依赖于 QEMU 的 -kernel 来将内核拷贝到内存并启动, 为了模拟更真实的硬件, 我们必须舍弃该方法, 通过 u-boot 来启动

u-boot 和 kernel 的编译和启动参考QEMU 实验(一), 这里不会再过多描述

在 u-boot 命令行中通过 sd 卡启动

首先创建一个 sd 卡的镜像文件用来模拟真实 sdcard, 将内核和设备树放到镜像文件中, 然后使用 u-boot 命令行把内核和设备树加载到内存并运行内核

dd if=/dev/zero of=sdcard.img bs=1024 count=102400
mkfs.fat sdcard.img
mount -o loop sdcard.img /mnt
cp zImage vexpress-v2p-ca9.dtb /mnt
umount /mnt

使用 QEMU 启动 u-boot, 参考

$ qemu-system-arm -M vexpress-a9 -m 256M -kernel u-boot -sd sdcard.img -nographic
=> mmcinfo 
=> load mmc 0:0 0x60008000 zImage
=> load mmc 0:0 0x61000000 vexpress-v2p-ca9.dtb
=> setenv bootargs "root=/dev/mmcblk0 rw console=ttyAMA0"
=> bootz 0x60008000 - 0x61000000
  • mmcinfo 可查看有哪些 mmc 设备
  • load <硬件接口> <设备号:分区> <加载地址> <文件名>
  • setenv bootargs 用来传递环境变量给内核, 这里只告知了将sd卡挂载为可读写根文件系统, 并将控制台定向到串口0
  • bootm <kernel地址> <ramdisk地址> <dtb地址> 可使用 - 略过参数,比如上面不需要 ramdisk,所以中间有 -

内核成功启动后将会去根文件系统运行第一个用户程序 /sbin/init, 但是我们没有拷贝任何程序到 sdcard, 所以内核返回 No working init found. 不过参考QEMU 实验(一)可以很轻松地将 Busybox 拷贝到 SD 卡, 这里不再赘述

从 tftp 网络中启动

  • 安装 tftp 服务器
     apt-get install tftpd-hpa        # tftp server 
     apt-get install tftp-hpa         # tftp client, for test
     mkdir ~/tftpboot
     chmod 777 ~/tftpboot
     vim /etc/default/tftpd-hpa
    

    更改 TFTP_DIRECTORY 为 ~/tftpboot

  • 本地测试
     $ touch ~/tftpboot/a.txt
     $ tftp 127.0.0.1 
     tftp> get a.txt
    
  • u-boot 启动测试
    $ cp zImage vexpress-v2p-ca9.dtb ~/tftpboot
    $ ifconfig                        # 拷贝ip地址, 例如 192.168.1.20
    
    => setenv ipaddr 192.168.1.21     # 设置本机 ip 地址
    => setenv serverip 192.168.1.20   # 设置服务器 ip 地址
    => tftp 0x60008000 zImage
    => tftp 0x61000000 vexpress-v2p-ca9.dtb
    => setenv bootargs "root=/dev/mmcblk0 rw console=ttyAMA0"
    => bootz 0x60008000 - 0x61000000
    
    参考 uboot通过tftp的方式加载Linux内核文件

自动脚本

u-boot 支持运行脚本, 我们可以使用脚本来让u-boot自动运行上面的命令行, 不过 u-boot 并不会直接运行纯文本文件, 他需要对脚本文件使用 mkimage 进行打包, 加入头信息, 这是为了安全考虑的.
新建一个文件 boot.cmd , 然后直接拷贝上面的命令行内容到文件
boot.cmd

load mmc 0:0 0x60008000 zImage
load mmc 0:0 0x61000000 vexpress-v2p-ca9.dtb
setenv bootargs "root=/dev/mmcblk0 rw console=ttyAMA0"
bootz 0x60008000 - 0x61000000

然后执行

mkimage -C none -A arm -T script -d boot.cmd boot.scr

将 boot.scr 拷贝到 sdcard 的根目录, 就像我们拷贝内核和设备树那样, 只要在 u-boot 中能够将它加载进内存即可.

$ qemu-system-arm -M vexpress-a9 -m 256M -kernel u-boot -sd sdcard.img -nographic
=> load mmc 0:0 0x62000000 boot.scr
=> source 0x62000000

source <addr> 将执行在放在内存 addr 处的 .scr 脚本

让 u-boot 启动后自动加载 sd 卡中的 kernel

在 u-boot 中, 通过 printenv 可以看到环境变量信息, 其中有如下信息

boot_scripts=boot.scr.uimg boot.scr
boot_targets=mmc1 mmc0 pxe dhcp 

变量 boot_scripts 指定了u-boot启动后默认加载的命令脚本, boot_targets 指定了从那个地方加载, 据此我们可以生成一个 boot.scr 放在 SD 卡, u-boot 启动后会自动加载并执行. 但是在前一节自动脚本中, 我们也放在了sdcard 且名称也为 boot.scr 但是为什么没有自己启动? 这是因为 u-boot 默认是识别设备的第一个分区, 我们没有给sdcard进行分区, 因此无法启动. (只有一个分区和不分区是不同的, 不分区压根没有分区表, 也就没分区的概念, 分区后即使只有一个分区, 也是有分区表的)

此外不要忘记更改 load mmc 的磁盘位置, 要更改为分区1
boot.cmd

load mmc 0:1 0x60008000 zImage
load mmc 0:1 0x61000000 vexpress-v2p-ca9.dtb
setenv bootargs "root=/dev/mmcblk0p1 rw console=ttyAMA0"
bootz 0x60008000 - 0x61000000

重新生成一下:

mkimage -C none -A arm -T script -d boot.cmd boot.scr

然后是重新生成 sdcard.img:

dd if=/dev/zero of=sdcard.img bs=1024 count=102400
fdisk sdcard.img                                        # 简单起见这里只分一个区
losetup -f                                              # 查询可用的块设备地址, 记下来如 /dev/loop16
losetup -P /dev/loop16 sdcard.img                       # 关联块设备   
lsblk                                                   # 可以看到块设备已经关联, 并且看到分区信息   
mkfs.fat  /dev/loop16p1                                 # 格式化第一分区                       
mount /dev/loop16p1 /mnt                                # 挂载块设备的第一分区
cp boot.scr zImage vexpress-v2p-ca9.dtb /mnt            # 复制到 第一分区 
umount /mnt                                             # 卸载设备

启动

qemu-system-arm -M vexpress-a9 -m 1024M -kernel u-boot -sd sdcard.img -nographic

[注意] 这里设置了 1024M 内存, 因为vexpress-a9板子执行 printenv 时看到环境变量默认 scriptaddr=0x88000000, 启动脚本检测存在后会被拷贝到这个地方并使用 source 执行. 而 bdinfo 显示DRAM bank 启始地址是 0x60000000, 如果内存只有 256M, 则RAM到不了0x88000000, 是无法加载启动脚本的. 虽然这一项可以更改该参数并重新编译 u-boot, 不过, 目前最好还是按官方原本设置为好.

启动后, u-boot 会被 Qemu 加载到内存, 然后 u-boot 初始化设备, 并探测到 sdcard 的第一分区有 boot.scr, 它会将其加载到 scriptaddr 地址处并执行, 而执行的 boot.scr 被我们定义为 加载同目录下的内核以及设备树并执行, 因此 Linux 内核被成功启动.

u-boot 打包

参考

可将 u-boot kernel dtb rootfs 都打包在一个镜像文件中然后下载到 NorFlash 中直接运行, 使用 dd 进行操作

mkimage -A arm -C none -O linux -T kernel -d zImage -a 0x00010000 -e 0x00010000 zImage.uimg
mkimage -A arm -C none -O linux -T ramdisk -d rootfs.img.gz -a 0x00800000 -e 0x00800000 rootfs.uimg
dd if=/dev/zero of=flash.bin bs=1 count=6M
dd if=u-boot.bin of=flash.bin conv=notrunc bs=1
dd if=zImage.uimg of=flash.bin conv=notrunc bs=1 seek=2M
dd if=rootfs.uimg of=flash.bin conv=notrunc bs=1 seek=4M

然后可以直接将文件加载到内存运行:

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

推荐阅读更多精彩内容