U-Boot构建启动Linux系统

 

编译 U-Boot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sudo apt install bison flex gcc-arm-linux-gnueabi
# git clone --depth 1 https://github.com/u-boot/u-boot.git
wget https://ftp.denx.de/pub/u-boot/u-boot-2025.01.tar.bz2
tar -xjvf u-boot-2025.01.tar.bz2 && cd u-boot-2025.01

# 使用 vexpress 的配置构建,配置文件都在 u-boot-2025.01/configs/ 内,例如:qemu_arm_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=build vexpress_ca9x4_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=build -j$(nproc)

# 编译完成后 u-boot 源码根目录build下会生成 u-boot 与 u-boot.bin 文件,用法:-kernel u-boot 或 -bios u-boot.bin
leux@B650I:~/uboot/u-boot-2025.01/build$ file u-boot
u-boot: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), static-pie linked, with debug_info, not stripped
leux@B650I:~/uboot/u-boot-2025.01/build$ file u-boot.bin
u-boot.bin: DOS executable (COM), start instruction 0xb80000ea 14f09fe5

# 测试vexpress只能用 -kernel u-boot,而virt可用 -kernel u-boot 或 -bios u-boot.bin 加载,必须要加 -nographic 参数
qemu-system-arm -M vexpress-a9 -kernel u-boot -nographic

编译 Kernel

1
2
3
4
5
6
7
8
9
10
11
12
13
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.21.tar.xz
tar -xJvf linux-6.12.21.tar.xz && cd linux-6.12.21

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=build vexpress_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=build menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=build -j$(nproc)

# 内 核:linux-6.12.21/arch/arm/boot/zImage
# 设备树:linux-6.12.21/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb

# 可以不需要U-Boot使用QEMU直接启动内核,必须要加 -nographic 参数
qemu-system-arm -M vexpress-a9 -kernel zImage -dtb vexpress-v2p-ca9.dtb -nographic

创建 存储器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sudo dd if=/dev/zero of=rootfs.ext4 bs=1M count=64
sudo mkfs.ext4 rootfs.ext4
sudo mount -t ext4 rootfs.ext4 /mnt/boot/ -o loop

mkdir -p dev proc sys etc/init.d/ tmp boot lib var
sudo cp -r /home/leux/rootfs/* /mnt/boot/
cd /mnt/boot/
sudo cp ../linux-6.12.21/arch/arm/boot/zImage boot/
sudo cp ../linux-6.12.21/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb boot/
sudo umount /mnt/boot/

# 只有vexpress能用-sd命令模拟mmc设备,QEMU的VIRT可用virtio设备
qemu-system-arm -M vexpress-a9 -kernel zImage -dtb vexpress-v2p-ca9.dtb -nographic -append "init=/linuxrc root=/dev/mmcblk0 rw console=ttyAMA0" -sd rootfs.ext4 -net nic -net tap,ifname=tap0

引导 Kernel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 使用U-Boot加载MMC中的vexpress-a9内核启动
qemu-system-arm -M vexpress-a9 -kernel u-boot -nographic -sd rootfs.ext4

# 查看开发板的相关预设变量
=> printenv
arch=arm
cpu=armv7
board=vexpress
baudrate=38400
console=ttyAMA0,38400n8
loadaddr=0x60100000
fdt_addr_r=0x60000000
kernel_addr_r=0x60100000
boot_targets=mmc1 mmc0 pxe dhcp

# 查看预设的加载地址
=> printenv kernel_addr_r ramdisk_addr_r fdt_addr_r
kernel_addr_r=0x60100000
## Error: "ramdisk_addr_r" not defined
fdt_addr_r=0x60000000

# 从MMC中加载内核到KERNEL地址
=> load mmc 0:0 0x60100000 /boot/zImage
5903056 bytes read in 2376 ms (2.4 MiB/s)

# 从MMC中加载设备树到FDT地址
=> load mmc 0:0 0x60000000 /boot/vexpress-v2p-ca9.dtb
14329 bytes read in 17 ms (822.3 KiB/s)

# 设置内核启动参数,不设置也可启动内核,但找不到根文件系统会panic
=> setenv bootargs 'root=/dev/mmcblk0 rw'

# 用命令 bootz kernel_addr_r ramdisk_addr_r fdt_addr_r 加载内核启动,没有的用 - 占位
=> bootz 0x60100000 - 0x60000000
Kernel image @ 0x60100000 [ 0x000000 - 0x5a12d0 ]
## Flattened Device Tree blob at 60000000
Booting using the fdt blob at 0x60000000
Working FDT set to 60000000
Loading Device Tree to 66b13000, end 66b197f8 ... OK
Working FDT set to 66b13000

Starting kernel ...

# booti 用于引导 ARM64 内核镜像Image,bootefi 用于引导 ARM64 压缩内核镜像Image.gz
# bootz 用于引导 ARM 内核镜像zImage,bootm 用于引导u-boot自定义的内核镜像uImage

使用 U-Boot

  1. 使用MMC设备
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
=> mmc list					# 查看设备有几个 EMMC 设备
mmci@5000: 0 (SD)

=> mmc info # 查看 EMMC 0 信息
Device: mmci@5000
Manufacturer ID: aa
OEM: 5859
Name: QEMU!
Bus Speed: 12000000
Mode: MMC legacy
Rd Block Len: 512
SD version 3.0
High Capacity: No
Capacity: 64 MiB
Bus Width: 1-bit
Erase Group Size: 512 Bytes

=> mmc dev 0 # 切换到 EMMC 0
switch to partitions #0, OK
mmc0 is current device
=> mmc part
## Unknown partition table type 0
=> ls mmc 0:0
./
../
boot/
bin/
dev/
etc/
proc/
sbin/
sys/
tmp/
usr/
var/
<SYM> linuxrc
18 .ash_history

2 file(s), 12 dir(s)

=> load mmc 0:0 0x60100000 /boot/zImage
5903056 bytes read in 2350 ms (2.4 MiB/s)

=> bootz 0x60100000 - 0x60000000

  1. U-Boot查看文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
qemu-system-aarch64 -machine virt -cpu cortex-a57 -bios u-boot.bin -hda sd_card.img -nographic -nic tap,ifname=tap0,model=e1000

=> pci
BusDevFun VendorId DeviceId Device Class Sub-Class
_____________________________________________________________
00.00.00 0x1b36 0x0008 Bridge device 0x00
00.01.00 0x8086 0x100e Network controller 0x00
00.02.00 0x1af4 0x1001 Mass storage controller 0x00
=> virtio scan
=> virtio info
Device 0: 1af4 VirtIO Block Device
Type: Hard Disk
Capacity: 1024.0 MB = 1.0 GB (2097152 x 512)

=> ls virtio 0:1
11666200 uInitrd-6.1.99

1 file(s), 0 dir(s)

=> ls virtio 0:2
./
../
boot/
lib/
usr/

0 file(s), 5 dir(s)

=> ls virtio 0:2 boot
./
../
dtb-6.1.99/
7437936 System.map-6.1.99
11666200 uInitrd-6.1.99
247267 config-6.1.99
40229376 vmlinuz-6.1.99
11666136 initrd.img-6.1.99

5 file(s), 3 dir(s)

=>