qemu使用uboot通过网络加载 linux kernel。
原理图:
通过网桥,将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 \