自动启动失败怎么用手工把内核拽起来?——U-Boot手动引导完整步骤

2026.10.13 | 焜财商富 | 32772次围观

理解U‑Boot自动启动背后到底做了什么,最好的方法是在U‑Boot命令行中手动完成一次内核引导。当自动启动失败时,手动引导也是最重要的调试手段。本文以RK3576为例,展示从eMMC、SD卡和TFTP三种方式手动引导Linux内核的完整命令序列。

自动启动卡住或者进入shell后不知下一步做什么。此时最好的调试方法就是手动执行一遍引导步骤——每一步的输出都揭示了问题所在。加载内核失败?检查文件系统。启动后卡死?检查bootargs。本文整理了RK3576上最常用的三种手动引导方案,附带所有关键地址和命令。

一、手动引导概览

自动启动时,U‑Boot根据bootcmd环境变量中的命令序列执行引导。手动引导就是把这一系列命令逐一在命令行中执行,细致观察每个步骤的输出和结果。

wKgZO2qwaPWAdDHPAAH_hd8UyvU616.png

二、通用环境变量

在开始手动引导前,需要确认以下关键环境变量:

# 查看加载地址=> printenv kernel_addr_r fdt_addr_r ramdisk_addr_rkernel_addr_r=0x40400000fdt_addr_r=0x48300000ramdisk_addr_r=0x4a200000

这些地址必须:

1.在可用内存范围内

2.不与U‑Boot自身重叠

3.与内核Image的解压地址兼容

三、方式一:从eMMC引导

eMMC在RK3576上通常为mmc dev 0,根文件系统在第五分区。

完整命令序列

# ── 第1步:选择eMMC设备 ──=> mmc dev0switch to partitions#0, OKmmc0 is current device# ── 第2步:查看eMMC分区表 ──=> mmc partPartitionMapforMMCdevice0 -- PartitionType:EFIPart StartLBA EndLBA Name Attributes TypeGUID PartitionGUID1 0x00008000 0x0000a000 "boot"2 0x0000a000 0x0000c000 "trust"3 0x0000c000 0x0000f000 "misc"4 0x0000f000 0x0005f000 "resource"5 0x0005f000 0x00200000 "rootfs"# ── 第3步:加载内核Image ──# 如果rootfs分区是ext4格式:=> ext4load mmc0:5${kernel_addr_r} /boot/Image18667520bytes readin789ms (22.6MiB/s)# ── 第4步:加载DTB ──=> ext4load mmc0:5${fdt_addr_r} /boot/rk3576‑evb.dtb65241bytes readin21ms (2.9MiB/s)# ── 第5步:设置bootargs ──=> setenv bootargs console=ttyS2,1500000root=/dev/mmcblk0p5 rootfstype=ext4 rw# ── 第6步:引导内核 ──=> booti${kernel_addr_r} -${fdt_addr_r}## Loading kernel from Image at 0x40400000 ... Imagename:Linux5.10.160 Imagetype:AArch64LinuxKernelImage## Flattened Device Tree blob at 0x48300000 Bootingusing the fdt blob at0x48300000## bootargs: console=ttyS2,1500000 root=/dev/mmcblk0p5 rootfstype=ext4 rw LoadingDeviceTreeto 00000000af5e0000,end00000000af5fefff ...OKStartingkernel ...

参数说明

命令

含义

mmc dev 0

选择eMMC设备(设备0)

ext4load mmc 0:5

从eMMC设备0的分区5(ext4)加载文件

${kernel_addr_r}

内核加载地址,通常为0x40400000

${fdt_addr_r}

DTB加载地址,通常为0x48300000

booti ${kernel_addr_r} - ${fdt_addr_r}

引导Image内核,‑表示无ramdisk

四、方式二:从SD卡引导

SD卡在RK3576上通常为mmc dev 1,分区格式可能是FAT或ext4。

FAT格式SD卡

# ── 第1步:选择SD卡设备 ──=> mmc dev1switch to partitions#0, OKmmc1 is current device# ── 第2步:加载内核 ──=> fatload mmc1:1${kernel_addr_r}Image18667520bytes readin801ms (22.2MiB/s)# ── 第3步:加载DTB ──=> fatload mmc1:1${fdt_addr_r} rk3576‑evb.dtb65241bytes readin22ms (2.8MiB/s)# ── 第4步:设置bootargs ──# 注意root设备是mmcblk1而非mmcblk0=> setenv bootargs console=ttyS2,1500000root=/dev/mmcblk1p5 rootfstype=ext4 rw# ── 第5步:引导 ──=> booti${kernel_addr_r} -${fdt_addr_r}

ext4格式SD卡

=> mmc dev1=> ext4load mmc1:1${kernel_addr_r} /boot/Image=> ext4load mmc1:1${fdt_addr_r} /boot/rk3576‑evb.dtb=> setenv bootargs console=ttyS2,1500000root=/dev/mmcblk1p5 rootfstype=ext4 rw=> booti${kernel_addr_r} -${fdt_addr_r}

注意:从SD卡引导时,root=参数中mmcblk1对应SD卡,mmcblk0对应eMMC。混用将导致内核尝试从错误的设备挂载根文件系统。

五、方式三:从TFTP网络引导

网络引导在开发阶段非常有用,可以避免反复烧录存储介质。

前提条件

‑ U‑Boot已通过ethaddr环境变量配置了MAC地址

‑网络中有DHCP服务器提供IP分配

‑ TFTP服务器上放置了内核Image和DTB

完整命令序列

# ── 第1步:初始化网络(DHCP获取IP) ──=> dhcpBOOTPbroadcast1DHCPclient bound to address192.168.1.100***Warning: no boot file name; using'C0A80064.img'# ── 第2步:从TFTP加载内核Image ──=> tftp${kernel_addr_r}192.168.1.200:ImageUsingethernet@fe2c0000deviceTFTPfrom server192.168.1.200; ourIPaddress is192.168.1.100Filename'Image'.Loadaddress:0xa200000Loading:################################################ 18667520bytes loadedin2.3seconds (7.7MiB/s)# ── 第3步:加载DTB ──=> tftp${fdt_addr_r}192.168.1.200:rk3576‑evb.dtb65241bytes loadedin0.12seconds# ── 第4步:设置bootargs ──# NFS根文件系统(开发阶段常用)=> setenv bootargs console=ttyS2,1500000root=/dev/nfsrw  nfsroot=192.168.1.200:/srv/nfs/rootfs,v3 ip=dhcp# ── 第5步:引导 ──=> booti${kernel_addr_r} -${fdt_addr_r}

六、三种方式的对比

维度

eMMC

SD卡

TFTP

速度

最快(~30MB/s)

中等(~20MB/s)

依赖网络(~8MB/s)

持久性

断电保留

断电保留

不保留

方便迭代

需要烧录

需要插拔卡

最方便(仅需编译+上传)

依赖硬件

无

SD卡槽

网线+ DHCP+TFTP服务器

适用场景

量产/最终产品

早期调试

开发阶段调试

七、调试技巧

7.1检查内核镜像Magic

在跳转前,确认加载的内核Image是有效的:

=> md${kernel_addr_r}440400000:38400000000000040000000000020000 .8@.............# 偏移0x38处检查magic=> md${kernel_addr_r}0x38140400038: 644d5241 ARMd

7.2验证DTB完整性

=> fdt addr${fdt_addr_r}=> fdt list / # 检查根节点=> fdt list /chosen # 检查bootargs=> fdt list /memory # 检查内存信息

7.3保存常用命令序列

对于经常使用的手动引导步骤,可以保存为环境变量宏:

=> setenv my_boot_cmd'mmc dev 0; ext4load mmc 0:5 ${kernel_addr_r} /boot/Image;  ext4load mmc 0:5 ${fdt_addr_r} /boot/rk3576‑evb.dtb;  setenv bootargs console=ttyS2,1500000 root=/dev/mmcblk0p5 rw;  booti ${kernel_addr_r} - ${fdt_addr_r}'=> saveenv# 之后只需运行:=> run my_boot_cmd

八、小结

‑手动引导是理解U‑Boot到内核启动流程的最佳实践方法

‑ eMMC、SD卡、TFTP三种方式各有适用场景,TFTP最适合开发调试

‑关键步骤为:选择设备/初始化网络→加载内核→加载DTB →设置bootargs → booti引导

‑从SD卡引导时注意root=参数中的设备号应为mmcblk1而非mmcblk0

‑网络引导需要DHCP + TFTP服务器支持,但免去了反复烧录的麻烦

‑善用fdt命令和md命令,可以在跳转前验证镜像和DTB的完整性

‑常用命令序列可以保存为环境变量宏,实现"半自动"引导