Use QEMU to simulate starting uboot

For related knowledge of uboot, you can refer to: Basic concepts of uboot.

1. Environment configuration

WSL: ubutu20.04
Analog development board: vexpress-a9
uboot version: u-boot-2023.10

2. Install QEMU

  • 2.1. Install
    sudo apt install qemu
    
  • 2.2. Check which development boards are supported
    qemu-system-arm -M help
    

    The results are as follows:

    Supported machines are:
    akita Sharp SL-C1000 (Akita) PDA (PXA270)
    ast2500-evb Aspeed AST2500 EVB (ARM1176)
    ast2600-evb Aspeed AST2600 EVB (Cortex A7)
    borzoi Sharp SL-C3100 (Borzoi) PDA (PXA270)
    canon-a1100 Canon PowerShot A1100 IS
    cheetah Palm Tungsten|E aka. Cheetah PDA (OMAP310)
    collie Sharp SL-5500 (Collie) PDA (SA-1110)
    connex Gumstix Connex (PXA255)
    cubieboard cubietech cubieboard (Cortex-A8)
    emcraft-sf2 SmartFusion2 SOM kit from Emcraft (M2S010)
    highbank Calxeda Highbank (ECX-1000)
    imx25-pdk ARM i.MX25 PDK board (ARM926)
    integratorcp ARM Integrator/CP (ARM926EJ-S)
    kzm ARM KZM Emulation Baseboard (ARM1136)
    lm3s6965evb Stellaris LM3S6965EVB
    lm3s811evb Stellaris LM3S811EVB
    mainstone Mainstone II (PXA27x)
    mcimx6ul-evk Freescale i.MX6UL Evaluation Kit (Cortex A7)
    mcimx7d-sabre Freescale i.MX7 DUAL SABER (Cortex A7)
    microbit BBC micro:bit
    midway Calxeda Midway (ECX-2000)
    mps2-an385 ARM MPS2 with AN385 FPGA image for Cortex-M3
    mps2-an505 ARM MPS2 with AN505 FPGA image for Cortex-M33
    mps2-an511 ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3
    mps2-an521 ARM MPS2 with AN521 FPGA image for dual Cortex-M33
    musca-a ARM Musca-A board (dual Cortex-M33)
    musca-b1 ARM Musca-B1 board (dual Cortex-M33)
    musicpal Marvell 88w8618 / MusicPal (ARM926EJ-S)
    n800 Nokia N800 tablet aka. RX-34 (OMAP2420)
    n810 Nokia N810 tablet aka. RX-44 (OMAP2420)
    netduino2 Netduino 2 Machine
    none empty machine
    nuri Samsung NURI board (Exynos4210)
    palmetto-bmc OpenPOWER Palmetto BMC (ARM926EJ-S)
    raspi2 Raspberry Pi 2
    realview-eb ARM RealView Emulation Baseboard (ARM926EJ-S)
    realview-eb-mpcore ARM RealView Emulation Baseboard (ARM11MPCore)
    realview-pb-a8 ARM RealView Platform Baseboard for Cortex-A8
    realview-pbx-a9 ARM RealView Platform Baseboard Explore for Cortex-A9
    romulus-bmc OpenPOWER Romulus BMC (ARM1176)
    sabrelite Freescale i.MX6 Quad SABER Lite Board (Cortex A9)
    smdkc210 Samsung SMDKC210 board (Exynos4210)
    spitz Sharp SL-C3000 (Spitz) PDA (PXA270)
    swift-bmc OpenPOWER Swift BMC (ARM1176)
    sx1 Siemens SX1 (OMAP310) V2
    sx1-v1 Siemens SX1 (OMAP310) V1
    Terrier Sharp SL-C3200 (Terrier) PDA (PXA270)
    tosa Sharp SL-6000 (Tosa) PDA (PXA255)
    verdex Gumstix Verdex (PXA270)
    versatileab ARM Versatile/AB (ARM926EJ-S)
    versatilepb ARM Versatile/PB (ARM926EJ-S)
    vexpress-a15 ARM Versatile Express for Cortex-A15
    vexpress-a9 ARM Versatile Express for Cortex-A9
    virt-2.10 QEMU 2.10 ARM Virtual Machine
    virt-2.11 QEMU 2.11 ARM Virtual Machine
    virt-2.12 QEMU 2.12 ARM Virtual Machine
    virt-2.6 QEMU 2.6 ARM Virtual Machine
    virt-2.7 QEMU 2.7 ARM Virtual Machine
    virt-2.8 QEMU 2.8 ARM Virtual Machine
    virt-2.9 QEMU 2.9 ARM Virtual Machine
    virt-3.0 QEMU 3.0 ARM Virtual Machine
    virt-3.1 QEMU 3.1 ARM Virtual Machine
    virt-4.0 QEMU 4.0 ARM Virtual Machine
    virt-4.1 QEMU 4.1 ARM Virtual Machine
    virt QEMU 4.2 ARM Virtual Machine (alias of virt-4.2)
    virt-4.2 QEMU 4.2 ARM Virtual Machine
    witherspoon-bmc OpenPOWER Witherspoon BMC (ARM1176)
    xilinx-zynq-a9 Xilinx Zynq Platform Baseboard for Cortex-A9
    z2 Zipit Z2 (PXA27x)
    

3. Install the cross-compilation chain

sudo apt install arm-linux-gnueabi-gcc

Note: This step is not necessary. You can also download it from the Arm GNU Toolchain, decompress it and add it to the environment variables.

4. Compile uboot

  • 4.1. Decompression
tar -vxjf u-boot-2023.10.tar.bz2
  • 4.2. Compilation
cd u-boot-2023.10/

make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf-vexpress_ca9x4_defconfig
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- -j`nproc`
  • 4.3. Generated u-boot.bin file

5. Use the qemu tool to run uboot

  • 5.1. Start uboot
qemu-system-arm -M vexpress-a9 -m 512M -kernel ./u-boot -nographic -no-reboot

The running results are as follows:

U-Boot 2023.10 (Nov 02 2023 - 10:17:15 + 0800)

DRAM: 512 MiB
WARNING: Caches not enabled
Core: 18 devices, 10 uclasses, devicetree: embed
Flash: 64 MiB
MMC: mmci@5000: 0
Loading Environment from Flash... *** Warning - bad CRC, using default environment

In: serial
Out: serial
Err: serial
Net: eth0: ethernet@3,02000000
Hit any key to stop autoboot: 0
MMC Device 1 not found
no mmc device at slot 1
Card did not respond to voltage select! : -110
smc911x: detected LAN9118 controller
smc911x: phy initialized
smc911x: MAC 52:54:00:12:34:56
BOOTP broadcast 1
DHCP client bound to address 10.0.2.15 (2 ms)
*** Warning: no boot file name; using '0A00020F.img'
Using ethernet@3,02000000 device
TFTP from server 10.0.2.2; our IP address is 10.0.2.15
Filename '0A00020F.img'.
Load address: 0x60100000
Loading: *
TFTP error: 'Access violation' (2)
Not retrying...
smc911x: MAC 52:54:00:12:34:56
missing environment variable: pxefile_addr_r
smc911x: detected LAN9118 controller
smc911x: phy initialized
smc911x: MAC 52:54:00:12:34:56
BOOTP broadcast 1
DHCP client bound to address 10.0.2.15 (0 ms)
Using ethernet@3,02000000 device
TFTP from server 10.0.2.2; our IP address is 10.0.2.15
Filename 'boot.scr.uimg'.
Load address: 0x60100000
Loading: *
TFTP error: 'Access violation' (2)
Not retrying...
smc911x: MAC 52:54:00:12:34:56
smc911x: detected LAN9118 controller
smc911x: phy initialized
smc911x: MAC 52:54:00:12:34:56
BOOTP broadcast 1
DHCP client bound to address 10.0.2.15 (0 ms)
Using ethernet@3,02000000 device
TFTP from server 10.0.2.2; our IP address is 10.0.2.15
Filename 'boot.scr.uimg'.
Load address: 0x60100000
Loading: *
TFTP error: 'Access violation' (2)
Not retrying...
smc911x: MAC 52:54:00:12:34:56
cp-memory copy

Usage:
cp [.b, .w, .l, .q] source target count
Wrong Image Format for bootm command
ERROR: can't get kernel image!
=>

It means that uboot has started successfully.

  • 5.2. Enter help in uboot to view the supported commands in uboot:
=>
=> help
? - alias for 'help'
base - print or set address offset
bdinfo - print Board Info structure
blkcache - block cache diagnostics and control
bootefi - Boots an EFI payload from memory
bootelf - Boot from an ELF image in memory
bootflow - Boot flows
bootm - boot application image from memory
bootp - boot image via network using BOOTP/TFTP protocol
bootvx - Boot vxWorks from an ELF image
bootz - boot Linux zImage image from memory
cmp-memory compare
cp-memory copy
crc32 - checksum calculation
dhcp - boot image via network using DHCP/TFTP protocol
echo - echo args to console
eficonfig - provide menu-driven UEFI variable maintenance interface
env - environment handling commands
erase - erase FLASH memory
exit-exit script
ext2load - load binary file from an Ext2 filesystem
ext2ls - list files in a directory (default /)
ext4load - load binary file from an Ext4 filesystem
ext4ls - list files in a directory (default /)
ext4size - determine a file's size
false - do nothing, unsuccessfully
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls - list files in a directory (default /)
fatmkdir - create a directory
fatrm-delete a file
fatsize - determine a file's size
fatwrite - write file into a dos filesystem
fdt - flattened device tree utility commands
flinfo - print FLASH memory information
fstype - Look up a filesystem type
fstypes - List supported filesystem types
go - start application at address 'addr'
help - print command description/usage
iminfo - print header information for application image
ln - Create a symbolic link
load - load binary file from a filesystem
loop - infinite loop on address range
ls - list files in a directory (default /)
md-memory display
mii - MII utility commands
mm - memory modify (auto-incrementing address)
mmc - MMC subsystem
mmcinfo - display MMC info
mw - memory write (fill)
net - NET sub-system
nm - memory modify (constant address)
panic - Panic with optional message
part-disk partition related commands
ping - send ICMP ECHO_REQUEST to network host
printenv - print environment variables
protect - enable or disable FLASH write protection
pxe - commands to get and boot from pxe files
To use IPv6 add -ipv6 parameter
random - fill memory with random pattern
reset - Perform RESET of the CPU
run - run commands in an environment variable
save - save file to a filesystem
saveenv - save environment variables to persistent storage
setenv - set environment variables
showvar - print local hushshell variables
size - determine a file's size
source-run script from memory
sysboot - command to get and boot from syslinux files
test - minimal test like /bin/sh
tftpboot - load file via network using TFTP protocol
true - do nothing, successfully
ubi - ubi commands
ubifsload - load file from an UBIFS filesystem
ubifsls - list files in a directory
ubifsmount-mount UBIFS volume
ubifsumount- unmount UBIFS volume
version - print monitor, compiler and linker version
=>

6. Use gdb to debug uboot

  • 6.1. Enter the following startup command:
qemu-system-arm -M vexpress-a9 -m 512M -kernel ./u-boot -nographic -no-reboot -S -s

in:
-S means that the QEMU virtual machine will freeze the CPU until the remote GDB inputs the corresponding control command.
-s means receiving GDB debugging connections on port 1234.

  • 6.2. gdb debugging
    Reopen a terminal, enter the directory of the u-boot file, and enter the following command to start gdb debugging:
cd u-boot-2023.10
gdb-multiarch --tui u-boot

as follows:

  • 6.3. Start debugging
    Enter the following command in gdb to start debugging:
(gdb) set architecture arm
(gdb) target remote localhost:1234

Above, set the architecture to arm architecture and connect to the QEMU virtual machine through remote port 1234. As shown below:

The picture above shows that the _start program entry in the vectors.S file has been entered.
Next, you can perform single-step tracking and debugging: