开发环境

  • ubuntu 20.04
  • VMware Workstation Pro 16
  • 基于qemu(模拟器),vexpress-a9 平台
  • 搭建Linux 6.0.1 (当前最新版本)

准备

安装qemu

  • 安装在 虚拟机的ubuntu 20.04 上,当然有条件,可以直接安装在ubuntu 主机上
$ sudo apt-get install qemu
$ sudo apt-get install qemu-system
$ qemu-system-arm -M help /* 查看支持的板子的列表 */
  • 使用 ​​vexpress-a9​​ 平台,这是arm 平台

交叉编译工具链

  • 解压 ​​gcc-linaro-13.0.0-2022.10-x86_64_arm-linux-gnueabihf.tar.xz​
/* arm gcc 交叉编译器存放的目录,可以放在自己的用户目录home下 */
mkdir /home/zhangsz/tools
xz -d gcc-linaro-13.0.0-2022.10-x86_64_arm-linux-gnueabihf.tar.xz
tar xvf gcc-linaro-13.0.0-2022.10-x86_64_arm-linux-gnueabihf.tar -C /home/zhangsz/tools/
  • 添加到环境变量
/* 环境变量追加到 /etc/profie 中 */
$ sudo vim /etc/profile

export PATH=$PATH:/home/zhangsz/tools/gcc-linaro-13.0.0-2022.10-x86_64_arm-linux-gnueabihf/bin

/* 环境变量生效 */
$ source /etc/profile

ubuntu 20.04 qemu linux6.0.1 开发环境搭建_ubuntu

  • 查看当前的arm gcc 版本

命令 ​​$ arm-linux-gnueabihf-gcc -v​

$ arm-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/home/zhangsz/tools/gcc-linaro-13.0.0-2022.10-x86_64_arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/13.0.0/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: '/home/tcwg-buildslave/workspace/tcwg-gnu-build_2/snapshots/gcc.git~master/configure' SHELL=/bin/bash --with-mpc=/home/tcwg-buildslave/workspace/tcwg-gnu-build_2/_build/builds/destdir/x86_64-pc-linux-gnu --with-mpfr=/home/tcwg-buildslave/workspace/tcwg-gnu-build_2/_build/builds/destdir/x86_64-pc-linux-gnu --with-gmp=/home/tcwg-buildslave/workspace/tcwg-gnu-build_2/_build/builds/destdir/x86_64-pc-linux-gnu --with-gnu-as --with-gnu-ld --disable-libmudflap --enable-lto --enable-shared --without-included-gettext --enable-nls --with-system-zlib --disable-sjlj-exceptions --enable-gnu-unique-object --enable-linker-build-id --disable-libstdcxx-pch --enable-c99 --enable-clocale=gnu --enable-libstdcxx-debug --enable-long-long --with-cloog=no --with-ppl=no --with-isl=no --disable-multilib --with-float=hard --with-fpu=vfpv3-d16 --with-mode=thumb --with-tune=cortex-a9 --with-arch=armv7-a --enable-threads=posix --enable-multiarch --enable-libstdcxx-time=yes --enable-gnu-indirect-function --with-sysroot=/home/tcwg-buildslave/workspace/tcwg-gnu-build_2/_build/builds/destdir/x86_64-pc-linux-gnu/arm-linux-gnueabihf/libc --enable-checking=release --disable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/home/tcwg-buildslave/workspace/tcwg-gnu-build_2/_build/builds/destdir/x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --host=x86_64-pc-linux-gnu --target=arm-linux-gnueabihf
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 13.0.0 20221001 (experimental) [master revision 5299155bb80e90df822e1eebc9f9a0c8e4505a46] (GCC)

编译Linux 内核

  • Linux 内核解压缩到 ubuntu 中
$ mkdir /home/zhangsz/linux
$ mkdir /home/zhangsz/linux/kernel

/* 解压缩 tar.gz 格式的 linux kernel 文件 */
$ tar xzvf linux-6.0.1.tar.gz -C /home/zhangsz/linux/kernel
  • 配置与编译 ​​vexpress-a9​​ 平台
/* ubuntu 根据需求安装一些依赖 */
$ sudo apt-get install bison
$ sudo apt-get install flex
$ sudo apt-get install make

/* vexpress-a9 平台的 默认配置文件 */
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- vexpress_defconfig

/* 直接编译,如果编译报错,安装依赖继续编译,直到编译完成 */
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4
  • 编译 Linux 的产物
/* 默认编译会生成 zImage */
/home/zhangsz/linux/linux-6.0.1/arch/arm/boot/zImage

/* 同时编译生成了设备树文件,注意是 dtb 文件 */
/home/zhangsz/linux/linux-6.0.1/arch/arm/boot/dts/vexpress-v2p-ca9.dtb

qemu 启动Linux

  • qemu 因为是模拟器,所以不需要 u-boot 引导,就可以直接启动 Linux 内核
  • 把Linux 内核生成的产物,也就是 ​​zImage​​ 与 ​​vexpress-v2p-ca9.dtb​​,拷贝到一个目录下,如
  • 执行命令:
$ ls
vexpress-v2p-ca9.dtb zImage


$ qemu-system-arm -M vexpress-a9 -m 512M -kernel zImage -dtb vexpress-v2p-ca9.dtb -nographic -append "console=ttyAMA0"
  • 此时发现,有了Linux 的启动信息,当前没有根文件系统,所以没有 shell 命令行

ubuntu 20.04 qemu linux6.0.1 开发环境搭建_qemu_02

  • 完整的启动信息如下
$ qemu-system-arm -M vexpress-a9 -m 512M -kernel zImage -dtb vexpress-v2p-ca9.dtb -nographic -append "console=ttyAMA0"
pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument
Booting Linux on physical CPU 0x0
Linux version 6.0.1 (zhangsz@zhangsz) (arm-linux-gnueabihf-gcc (GCC) 13.0.0 20221001 (experimental) [master revision 5299155bb80e90df822e1eebc9f9a0c8e4505a46], GNU ld (Linaro_Binutils-2022.10) 2.39.50.20221001) #1 SMP Fri Oct 14 21:05:09 CST 2022
CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
OF: fdt: Machine model: V2P-CA9
Memory policy: Data cache writeback
Reserved memory: created DMA memory pool at 0x4c000000, size 8 MiB
OF: reserved mem: initialized node vram@4c000000, compatible id shared-dma-pool
cma: Reserved 16 MiB at 0x7f000000
Zone ranges:
Normal [mem 0x0000000060000000-0x000000007fffffff]
Movable zone start for each node
Early memory node ranges
node 0: [mem 0x0000000060000000-0x000000007fffffff]
Initmem setup node 0 [mem 0x0000000060000000-0x000000007fffffff]
CPU: All CPU(s) started in SVC mode.
percpu: Embedded 15 pages/cpu s30356 r8192 d22892 u61440
Built 1 zonelists, mobility grouping on. Total pages: 130048
Kernel command line: console=ttyAMA0
printk: log_buf_len individual max cpu contribution: 4096 bytes
printk: log_buf_len total cpu_extra contributions: 12288 bytes
printk: log_buf_len min size: 16384 bytes
printk: log_buf_len: 32768 bytes
printk: early log buf free: 14916(91%)
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes, linear)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes, linear)
mem auto-init: stack:all(zero), heap alloc:off, heap free:off
Memory: 490808K/524288K available (8192K kernel code, 638K rwdata, 1844K rodata, 1024K init, 180K bss, 17096K reserved, 16384K cma-reserved)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
trace event string verifier disabled
rcu: Hierarchical RCU implementation.
rcu: RCU event tracing is enabled.
rcu: RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
GIC CPU mask not found - kernel will fail to boot.
GIC CPU mask not found - kernel will fail to boot.
L2C: platform modifies aux control register: 0x02020000 -> 0x02420000
L2C: DT/platform modifies aux control register: 0x02020000 -> 0x02420000
L2C-310 enabling early BRESP for Cortex-A9
L2C-310 full line of zeros enabled for Cortex-A9
L2C-310 dynamic clock gating disabled, standby mode disabled
L2C-310 cache controller enabled, 8 ways, 128 kB
L2C-310: CACHE_ID 0x410000c8, AUX_CTRL 0x46420001
rcu: srcu_init: Setting srcu_struct sizes based on contention.
sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 89478484971ns
clocksource: arm,sp804: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275 ns
smp_twd: clock not found -2
Console: colour dummy device 80x30
Calibrating local timer... 97.27MHz.
Calibrating delay loop... 2007.04 BogoMIPS (lpj=10035200)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
CPU: Testing write buffer coherency: ok
CPU0: Spectre v2: using BPIALL workaround
CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
Setting up static identity map for 0x60100000 - 0x60100060
rcu: Hierarchical SRCU implementation.
rcu: Max phase no-delay instances is 1000.
smp: Bringing up secondary CPUs ...
smp: Brought up 1 node, 1 CPU
SMP: Total of 1 processors activated (2007.04 BogoMIPS).
CPU: All CPU(s) started in SVC mode.
devtmpfs: initialized
VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 0
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 1024 (order: 4, 65536 bytes, linear)
NET: Registered PF_NETLINK/PF_ROUTE protocol family
DMA: preallocated 256 KiB pool for atomic coherent allocations
cpuidle: using governor ladder
hw-breakpoint: debug architecture 0x4 unsupported.
Serial: AMBA PL011 UART driver
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
i2c 0-0039: Fixing up cyclic dependency with 1001f000.clcd
i2c 0-0039: Fixing up cyclic dependency with 10020000.clcd
pps_core: LinuxPPS API ver. 1 registered
pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
PTP clock support registered
Advanced Linux Sound Architecture Driver Initialized.
clocksource: Switched to clocksource arm,sp804
NET: Registered PF_INET protocol family
IP idents hash table entries: 8192 (order: 4, 65536 bytes, linear)
tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 4096 bytes, linear)
Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
TCP established hash table entries: 4096 (order: 2, 16384 bytes, linear)
TCP bind hash table entries: 4096 (order: 3, 32768 bytes, linear)
TCP: Hash tables configured (established 4096 bind 4096)
UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
NET: Registered PF_UNIX/PF_LOCAL protocol family
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
hw perfevents: enabled with armv7_cortex_a9 PMU driver, 5 counters available
workingset: timestamp_bits=30 max_order=17 bucket_order=0
squashfs: version 4.0 (2009/01/31) Phillip Lougher
jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
9p: Installing v9fs 9p2000 file system support
io scheduler mq-deadline registered
io scheduler kyber registered
OF: graph: no port node found in /bus@40000000/motherboard-bus@40000000/iofpga@7,00000000/i2c@16000/dvi-transmitter@60
sii902x 0-0060: supply iovcc not found, using dummy regulator
sii902x 0-0060: supply cvcc12 not found, using dummy regulator
physmap-flash 40000000.flash: physmap platform flash device: [mem 0x40000000-0x43ffffff]
40000000.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x000000
Intel/Sharp Extended Query Table at 0x0031
Using buffer write method
physmap-flash 40000000.flash: physmap platform flash device: [mem 0x44000000-0x47ffffff]
40000000.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x000000
Intel/Sharp Extended Query Table at 0x0031
Using buffer write method
Concatenating MTD devices:
(0): "40000000.flash"
(1): "40000000.flash"
into device "40000000.flash"
physmap-flash 48000000.psram: physmap platform flash device: [mem 0x48000000-0x49ffffff]
smsc911x 4e000000.ethernet eth0: MAC Address: 52:54:00:12:34:56
isp1760 4f000000.usb: isp1760 bus width: 32, oc: digital
isp1760 4f000000.usb: NXP ISP1760 USB Host Controller
isp1760 4f000000.usb: new USB bus registered, assigned bus number 1
isp1760 4f000000.usb: Scratch test failed. 0x00000000
isp1760 4f000000.usb: can't setup: -19
isp1760 4f000000.usb: USB bus 1 deregistered
usbcore: registered new interface driver usb-storage
rtc-pl031 10017000.rtc: registered as rtc0
rtc-pl031 10017000.rtc: setting system clock to 2022-10-14T13:58:27 UTC (1665755907)
mmci-pl18x 10005000.mmci: Got CD GPIO
mmci-pl18x 10005000.mmci: Got WP GPIO
mmci-pl18x 10005000.mmci: mmc0: PL181 manf 41 rev0 at 0x10005000 irq 35,36 (pio)
ledtrig-cpu: registered to indicate activity on CPUs
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
aaci-pl041 10004000.aaci: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 37
aaci-pl041 10004000.aaci: FIFO 512 entries
NET: Registered PF_PACKET protocol family
9pnet: Installing 9P2000 support
Registering SWP/SWPB emulation handler
10009000.uart: ttyAMA0 at MMIO 0x10009000 (irq = 38, base_baud = 0) is a PL011 rev1
printk: console [ttyAMA0] enabled
1000a000.uart: ttyAMA1 at MMIO 0x1000a000 (irq = 39, base_baud = 0) is a PL011 rev1
1000b000.uart: ttyAMA2 at MMIO 0x1000b000 (irq = 40, base_baud = 0) is a PL011 rev1
1000c000.uart: ttyAMA3 at MMIO 0x1000c000 (irq = 41, base_baud = 0) is a PL011 rev1
drm-clcd-pl111 1001f000.clcd: assigned reserved memory node vram@4c000000
drm-clcd-pl111 1001f000.clcd: using device-specific reserved memory
drm-clcd-pl111 1001f000.clcd: core tile graphics present
drm-clcd-pl111 1001f000.clcd: this device will be deactivated
drm-clcd-pl111 1001f000.clcd: Versatile Express init failed - -19
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
input: AT Raw Set 2 keyboard as /devices/platform/bus@40000000/bus@40000000:motherboard-bus@40000000/bus@40000000:motherboard-bus@40000000:iofpga@7,00000000/10006000.kmi/serio0/input/input0
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
ALSA device list:
#0: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 37
input: ImExPS/2 Generic Explorer Mouse as /devices/platform/bus@40000000/bus@40000000:motherboard-bus@40000000/bus@40000000:motherboard-bus@40000000:iofpga@7,00000000/10007000.kmi/serio1/input/input2
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
/dev/root: Can't open blockdev
VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
Please append a correct "root=" boot option; here are the available partitions:
1f00 131072 mtdblock0
(driver?)
1f01 32768 mtdblock1
(driver?)
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.0.1 #1
Hardware name: ARM-Versatile Express
unwind_backtrace from show_stack+0x10/0x14
show_stack from dump_stack_lvl+0x40/0x4c
dump_stack_lvl from panic+0x108/0x310
panic from mount_block_root+0x1c8/0x268
mount_block_root from prepare_namespace+0x150/0x18c
prepare_namespace from kernel_init+0x18/0x12c
kernel_init from ret_from_fork+0x14/0x2c
Exception stack(0xa0825fb0 to 0xa0825ff8)
5fa0: 00000000 00000000 00000000 00000000
5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
5fe0: 00000000 00000000 00000000 00000000 00000013 00000000
---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---

小结

  • 接下来,需要基于 busybox,制作根文件系统 rootfs
  • 让 qemu 运行 Linux shell,执行用户的程序