qemu使用uboot通过网络加载 linux kernel
qemu使用uboot通过网络加载 linux kernel。
参考文章:
https://www.cnblogs.com/edver/p/12117349.html
https://www.zhaixue.cc/qemu/qemu-u-boot.html
https://zhuanlan.zhihu.com/p/547338158
http://m.blog.chinaunix.net/uid-20788636-id-1841290.html
原理图:
通过网桥,将OS镜像(uImage),通过网络协议下载到U-Boot中,从而通过U-Boot启动OS:
如果有人出现了uboot第一次执行下载时失败,但后面正常,则可以参考我这里对.h代码的修改,即执行下载命令前,先ping一下。
1 #!/bin/sh 2 3 4 5 # 1. 6 # 修改busybox的Makefile的两个变量为: 7 # ARCH ?= arm 8 # CROSS_COMPILE ?= arm-linux-gnueabi- 9 # 10 cd u-boot-2022.10/ 11 vim Makefile 12 13 14 15 16 17 # 2. 18 # 编译, 如果出现错误, 安装: sudo apt install libssl-dev 19 make vexpress_ca9x4_defconfig 20 make -j 4 21 22 23 24 25 26 # 3. 27 # 使用qemu启动u-boot进行测试 28 sh testiboot/test_uboot.sh 29 # test_uboot.sh内容 30 # #!/bin/sh 31 # # 测试u-boot 32 # # 上级路径 33 # top_path="/home/thinks2/ProgramProject/qemu_study/" 34 # src_path="tftpboot/u-boot" 35 # # 内核文件路径 36 # kernel_path=${top_path}${src_path} 37 # qemu-system-arm \ 38 # -M vexpress-a9 \ 39 # -m 512M \ 40 # -kernel ${kernel_path} \ 41 # -sd rootfs.ext3 \ 42 # -nographic \ 43 44 45 46 47 48 # 4. 49 # 准备uImage内核, 指定加载地址, 编译uImage 50 cd .. 51 cd linux-4.19.269/ 52 make LOADADDR=0x60003000 uImage -j 4 53 54 55 56 57 58 # 5. 59 # 细心的朋友发现, 目前加载u-boot的方法使用还是-kernel选项, 也就是把u-boot当做内核挂载的, 60 # 而真实的系统启动, 不可能同时挂载两个内核启动(只能选择一个启动). 那么, 如何来模拟呢? 61 # 62 # u-boot实体机中, 我们常常采用tftp引导内核, 我们也可以在启动u-boot以后, 让u-boot通过tftp引导内核. 63 # 需要做两件事情: 64 # 1.搭建好tftp环境 65 # 2.构建网桥, 让qemu可以访问, 从而让qemu和ubuntu之间可以通过该网桥来访问 66 67 68 69 # 安装tftp和相关依赖, 设置好路径 70 sudo apt install tftp-hpa tftpd-hpa xinetd uml-utilities bridge-utils 71 72 73 74 # 设置tftp配置路径文件 75 sudo vim /etc/default/tftpd-hpa 76 # 将下面的内容复制近来 77 TFTP_USERNAME="tftp" 78 TFTP_DIRECTORY="/home/thinks2/ProgramProject/qemu_study/tftpboot" # 该路径即为tftp可以访问到的路径 79 TFTP_ADDRESS=":69" 80 TFTP_OPTIONS="--secure" 81 # 重启tftp服务 82 sudo /etc/init.d/tftpd-hpa restart 83 84 85 86 # 配置完以后, 创建tftp目录, 给最高权限. 把内核, 设备树, 根文件系统,u-boot全部复制到这里 87 cd .. 88 mkdir tftpboot 89 cd tftpboot 90 cp ../u-boot-2022.10/u-boot ./ 91 cp ../linux-4.19.269/arch/arm/boot/uImage ./ 92 cp ../linux-4.19.269/arch/arm/boot/dts/vexpress-v2p-ca9.dtb ./ 93 94 95 96 97 98 # 6. 99 # 修改网卡信息, 设置桥接 100 ifconfig # 查看网卡名 101 102 103 104 # 修改/etc/netplan/01-network-manager-all.yaml的信息配置: 105 sudo vim /etc/netplan/01-network-manager-all.yaml 106 # t添加以下内容: 107 ethernets: 108 # 这里设置的是你还需要上网的网卡, ifconfig查看 109 wlp0s20f3: 110 dhcp4: yes 111 112 # 这里设置的是网桥br0需要接入的网卡, 进行静态IP设置, ifconfig查看 113 enp0s31f6: 114 dhcp4: no 115 addresses: [192.168.70.50/24] 116 117 118 119 bridges: 120 #这里设置的是br0网桥, 进行静态IP设置 121 br0: 122 dhcp4: no 123 interfaces: 124 # 声明br0网桥接入的网卡是enp0s31f6 125 - enp0s31f6 126 addresses: [192.168.70.30/24] 127 128 129 130 # 输入sudo netplan apply使其生效, 再输入ifconfig查看网卡信息 131 sudo netplan apply 132 ifconfig 133 134 135 136 137 138 # 7. 139 # 修改/etc/qemu-ifdown信息配置 140 sudo vim /etc/qemu-ifdown 141 # 添加以下内容: 142 echo sudo brctl delif br0 $1 143 sudo brctl delif br0 $1 144 145 146 147 echo sudo tunctl -d $1 148 sudo tunctl -d $1 149 150 151 152 echo brctl show 153 brctl show 154 155 156 157 158 159 # 8. 160 # 修改/etc/qemu-ifup信息配置 161 sudo vim /etc/qemu-ifup 162 # 添加以下内容: 163 echo sudo tunctl -u $(id -un) -t $1 164 sudo tunctl -u $(id -un) -t $1 165 166 167 168 echo sudo ifconfig $1 0.0.0.0 promisc up 169 sudo ifconfig $1 0.0.0.0 promisc up 170 171 172 173 echo sudo brctl addif br0 $1 174 sudo brctl addif br0 $1 175 176 177 178 echo brctl show 179 brctl show 180 181 182 183 # 这里设置的是网桥br0的地址: 该地址不能与宿主机的ip相同 184 sudo ifconfig br0 192.168.70.30 185 186 187 188 189 190 # 9. 191 # 给 u-boot-2022.10/include/configs/vexpress_common.h添加代码: 192 # /* 193 # 1. 设置u-boot这边的地址(和br0同一网段即可) 194 # CONFIG_IPADDR 192.168.70.40 195 # 196 # 2. 设置服务器地址(即br0网桥的地址) 197 # CONFIG_SERVERIP 192.168.70.30 198 # */ 199 # #define CONFIG_IPADDR 192.168.70.40 200 # #define CONFIG_SERVERIP 192.168.70.30 201 # #define CONFIG_NETMASK 255.255.255.0 202 # 203 # 204 # /* 205 # 必须: make menuconfig -> Boot options -> 勾除Enable a default value or bootcmd 206 # 1. 从tft下载uImage 207 # tftp 0x60003000 uImage 208 # 209 # 2. 从tftp下载设备树 210 # tftp 0x60500000 vexpress-v2p-ca9.dtb 211 # 212 # 3. 设置根文件系统挂载位置、权限、控制台设备 213 # setenv bootargs "root=/dev/mmcblk0 rw console=ttyAMA0" 214 # 215 # 4. 设置启动地址 216 # bootm 0x60003000-0x60500000 217 # */ 218 # 219 # 220 # *********** 这里需要注意: *********** 221 # 新版本的uboot有一个配置u-boot启动时是否执行指令的选项: make menuconfig -> Boot options -> Enable a default value or bootcmd 222 # 1. 当勾选该选项后, 在.config文件中, 会出现一个参数: CONFIG_BOOTCOMMAND 223 # 这时, 修改.config文件中的该参数: .config -> CONFIG_BOOTCOMMAND 为命令字符串(以一行的格式) 224 # .config会在make的时候, 自动生存autocfg.h文件, 这个头文件里会进行宏定义CONFIG_BOOTCOMMAND 225 # 226 # 2. 如果不想修改.config文件, 需要勾除该选项, 227 # 勾除该选项后, 在.config文件中, 会删掉参数: CONFIG_BOOTCOMMAND 228 # 这时, 可以在u-boot-2022.10/include/configs/vexpress_common.h代码中添加下面的头文件定义即可 229 # 230 # 图方便的话, 建议使用方法2 231 # ************************************ 232 # 233 # /* 必须: make menuconfig -> Boot options -> 勾除Enable a default value or bootcmd */ 234 # #ifndef CONFIG_BOOTCOMMAND 235 # #define PING_COMMAND "ping 192.168.70.30;" 236 # #define CONFIG_BOOTCOMMAND \ 237 # PING_COMMAND \ 238 # "tftp 0x60003000 uImage;" \ 239 # "tftp 0x60500000 vexpress-v2p-ca9.dtb;" \ 240 # "setenv bootargs 'root=/dev/mmcblk0 rw console=ttyAMA0';" \ 241 # "bootm 0x60003000 - 0x60500000;" 242 # #endif 243 # 244 # 如果是在新版本的u-boot上, 可能使用上面的写法无法设置ipaddr, serverip, 则使用下面的代码: 245 # 246 # #ifndef CONFIG_BOOTCOMMAND 247 # 248 # #define SET_IPADDR "setenv ipaddr 192.168.131.130;" 249 # #define SET_SERVERIP "setenv serverip 192.168.131.100;" 250 # #define PING_COMMAND "ping 192.168.131.100;" 251 # 252 # #define CONFIG_BOOTCOMMAND \ 253 # SET_IPADDR \ 254 # SET_SERVERIP \ 255 # PING_COMMAND \ 256 # "tftp 0x60003000 uImage;" \ 257 # "tftp 0x60500000 vexpress-v2p-ca9.dtb;" \ 258 # "setenv bootargs 'root=/dev/mmcblk0 rw console=ttyAMA0';" \ 259 # "bootm 0x60003000 - 0x60500000;" 260 # #endif 261 # 262 cd .. 263 cd u-boot-2022.10/ 264 vim include/configs/vexpress_common.h 265 266 267 268 # 重新编译u-boot 269 make -j 4 270 271 272 273 # 将编译好的u-boot镜像复制到tftpboot里 274 cd .. 275 cp u-boot-2022.10/u-boot tftpboot/ 276 277 278 279 # 280 # 手动设置: 281 # # 设置u-boot这边的地址(和br0同一网段即可) 282 # setenv ipaddr 192.168.70.40 283 # # 设置服务器地址(br0网桥的地址: 该地址不能与宿主机的ip相同) 284 # setenv serverip 192.168.70.30 285 # # 从tft下载uImage 286 # tftp 0x60003000 uImage 287 # # 从tftp下载设备树 288 # tftp 0x60500000 vexpress-v2p-ca9.dtb 289 # # 设置根文件系统挂载位置、权限、控制台设备 290 # setenv bootargs "root=/dev/mmcblk0 rw console=ttyAMA0" 291 # # 设置启动地址 292 # bootm 0x60003000 - 0x60500000 293 # 294 295 296 297 298 # 10. 299 # 修改test_uboot.sh, 添加: 300 # -nic tap,ifname=tap0 \ 301 # -append "root=/dev/mmcblk0 rw console=ttyAMA0" \ 302 vim test_uboot.sh 303 # 输入启动指令, 需要以sudo方式启动test_uboot.sh再启动 304 sudo sh test_uboot.sh 305 # test_uboot.sh内容: 306 # #!/bin/sh 307 # # 测试u-boot 308 # # 上级路径 309 # top_path="/home/thinks2/ProgramProject/qemu_study/" 310 # src_path="tftpboot/u-boot" 311 # # 内核文件路径 312 # kernel_path=${top_path}${src_path} 313 # qemu-system-arm \ 314 # -M vexpress-a9 \ 315 # -m 512M \ 316 # -kernel ${kernel_path} \ 317 # -nic tap,ifname=tap0 \ 318 # -append "root=/dev/mmcblk0 rw console=ttyAMA0" \ 319 # -sd rootfs.ext3 \ 320 # -nographic \
最终的qemu的加载运行脚本test_uboot.sh:
1 #!/bin/sh 2 3 4 5 # 测试u-boot 6 7 8 9 # 上级路径 10 top_path="/home/thinks2/ProgramProject/qemu_study/" 11 src_path="tftpboot/u-boot" 12 13 14 15 # 内核文件路径 16 kernel_path=${top_path}${src_path} 17 18 19 20 qemu-system-arm \ 21 -M vexpress-a9 \ 22 -m 512M \ 23 -kernel ${kernel_path} \ 24 -nic tap,ifname=tap0 \ 25 -append "root=/dev/mmcblk0 rw console=ttyAMA0" \ 26 -sd rootfs.ext3 \ 27 -nographic \