RK3588 U-Boot 启动命令实现机制详解
本文档详细分析 RK3588 平台 U-Boot 启动相关命令的实现机制,包括 bootd、bootm、bootz、booti、boot_android、bootrkp 等命令。
目录
- 一、概述
- 二、U-Boot 启动架构
- 三、bootd 命令
- 四、bootm 命令
- 五、bootz 命令
- 六、booti 命令
- 七、boot_android 命令
- 八、bootrkp 命令
- 九、boot_fit 命令
- 十、内核跳转机制
- 十一、RK3588 硬件特性
一、概述
1.1 RK3588 平台特性
RK3588 是 Rockchip 推出的 ARM64 八核处理器,具有以下特性:
| 特性 | 说明 |
|---|---|
| 架构 | ARMv8-A, 4xCortex-A76 + 4xCortex-A55 |
| 内存 | 最高支持 32GB LPDDR4/LPDDR5 |
| 启动方式 | MMC/eMMC, SD卡, NAND, SPI NOR/NAND, NVMe, USB |
| 安全启动 | 支持 AVB (Android Verified Boot) |
| 多系统 | 支持 Android A/B 分区启动 |
1.2 启动命令源码位置
| 命令 | 源文件 |
|---|---|
| bootd | cmd/boot.c |
| bootm | cmd/bootm.c, common/bootm.c |
| bootz | cmd/bootz.c |
| booti | cmd/booti.c |
| boot_android | cmd/boot_android.c, common/android_bootloader.c |
| bootrkp | cmd/bootrkp.c, arch/arm/mach-rockchip/boot_rkimg.c |
| boot_fit | cmd/bootfit.c |
| ARM 启动 | arch/arm/lib/bootm.c |
二、U-Boot 启动架构
2.1 启动状态机
U-Boot 使用状态机管理启动过程,定义在 bootm.h:
#define BOOTM_STATE_START 0x00000001
#define BOOTM_STATE_FINDOS 0x00000002
#define BOOTM_STATE_FINDOTHER 0x00000004
#define BOOTM_STATE_LOADOS 0x00000008
#define BOOTM_STATE_RAMDISK 0x00000010
#define BOOTM_STATE_FDT 0x00000020
#define BOOTM_STATE_OS_CMDLINE 0x00000040
#define BOOTM_STATE_OS_BD_T 0x00000080
#define BOOTM_STATE_OS_PREP 0x00000100
#define BOOTM_STATE_OS_FAKE_GO 0x00000200
#define BOOTM_STATE_OS_GO 0x00000400
2.2 启动流程图
┌─────────────────────────────────────────────────────────────────┐
│ 启动命令入口 │
│ (bootd/bootm/bootz/booti/boot_android/bootrkp/boot_fit) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BOOTM_STATE_START │
│ - 初始化 bootm_headers_t 结构 │
│ - 初始化 LMB (Logical Memory Blocks) │
│ - 解析命令参数 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BOOTM_STATE_FINDOS │
│ - 检测镜像格式 (Legacy uImage/FIT/Android/zImage/Image) │
│ - 解析镜像头信息 │
│ - 获取 OS 类型、压缩方式、架构等 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BOOTM_STATE_FINDOTHER │
│ - 查找 ramdisk (initrd/initramfs) │
│ - 查找 FDT (设备树) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BOOTM_STATE_LOADOS │
│ - 解压缩内核镜像 (gzip/lzo/lzma) │
│ - 加载内核到指定地址 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BOOTM_STATE_RAMDISK │
│ - 重定位 ramdisk 到高地址 │
│ - 设置 initrd_start/initrd_end 环境变量 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BOOTM_STATE_FDT │
│ - 重定位设备树 │
│ - 修复设备树 (fdt_fixup) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BOOTM_STATE_OS_PREP │
│ - 准备启动参数 (bootargs/ATAGS/FDT) │
│ - ARM64: 无操作 │
│ - ARM32: 设置 ATAGS 参数 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BOOTM_STATE_OS_FAKE_GO │
│ - 用于调试,不实际跳转 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BOOTM_STATE_OS_GO │
│ - 禁用中断 │
│ - 清理设备 │
│ - 切换到 EL2 (ARM64) │
│ - 跳转到内核入口点 │
└─────────────────────────────────────────────────────────────────┘
2.3 镜像格式支持
U-Boot 支持三种主要的内核镜像格式:
┌─────────────────────────────────────────────────────────────────┐
│ Legacy uImage │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Header (64 bytes) │ │
│ │ - Image Magic: 0x27051956 │ │
│ │ - Header CRC │ │
│ │ - Timestamp │ │
│ │ - Size (Data + CRC) │ │
│ │ - Load Address │ │
│ │ - Entry Point │ │
│ │ - Data CRC │ │
│ │ - OS Type (Linux/VxWorks/etc) │ │
│ │ - Architecture (ARM/ARM64/x86/etc) │ │
│ │ - Compression Type (None/GZIP/LZO/LZMA) │ │
│ │ - Name (e.g., "Linux Kernel") │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ Image Data (may be compressed) │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ Data CRC │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ FIT Image (Flattened Image Tree) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ FDT format with multiple images │ │
│ │ / { │ │
│ │ images { │ │
│ │ kernel-1 { │ │
│ │ data = <...>; │ │
│ │ type = "kernel"; │ │
│ │ arch = "arm64"; │ │
│ │ os = "linux"; │ │
│ │ compression = "none"; │ │
│ │ load = <0x40080000>; │ │
│ │ entry = <0x40080000>; │ │
│ │ }; │ │
│ │ ramdisk-1 { │ │
│ │ data = <...>; │ │
│ │ type = "ramdisk"; │ │
│ │ arch = "arm64"; │ │
│ │ os = "linux"; │ │
│ │ }; │ │
│ │ fdt-1 { │ │
│ │ data = <...>; │ │
│ │ type = "flat_dt"; │ │
│ │ arch = "arm64"; │ │
│ │ }; │ │
│ │ }; │ │
│ │ configurations { │ │
│ │ default = "conf-1"; │ │
│ │ conf-1 { │ │
│ │ kernel = "kernel-1"; │ │
│ │ ramdisk = "ramdisk-1"; │ │
│ │ fdt = "fdt-1"; │ │
│ │ }; │ │
│ │ }; │ │
│ │ } │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Android Boot Image │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ bootimg header (page aligned, 2048 bytes) │ │
│ │ - magic: "ANDROID!" │ │
│ │ - kernel_size │ │
│ │ - kernel_addr (load address) │ │
│ │ - ramdisk_size │ │
│ │ - ramdisk_addr │ │
│ │ - second_size (optional) │ │
│ │ - second_addr │ │
│ │ - tags_addr │ │
│ │ - page_size: 2048 │ │
│ │ - dtb_size (since Android v1, DTB area) │ │
│ │ - dtb_addr │ │
│ │ - name (16 bytes) │ │
│ │ - cmdline (512 bytes) │ │
│ │ - id (32 bytes, SHA256 of kernel/ramdisk/second) │ │
│ │ - extra_cmdline (1024 bytes) │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ kernel (page aligned) │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ ramdisk (page aligned) │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ second stage (optional, page aligned) │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ recovery dtbo (since Android v1, page aligned) │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ dtb (since Android v1, page aligned) │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
三、bootd 命令
3.1 功能说明
bootd 是最简单的启动命令,它执行 bootcmd 环境变量中定义的命令序列。
3.2 实现机制
bootd 本身在标准 U-Boot 中是通过 run 命令实现的,而不是一个独立的命令。在 Rockchip U-Boot 中,run 命令定义在 cmd/boot.c:
/* run command 执行环境变量命令 */
static int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
/* 简化版本说明 */
if (argc < 2)
return CMD_RET_USAGE;
char *cmd = env_get(argv[1]);
if (cmd) {
return parse_string_outer(cmd, FLAG_PARSE_SEMICOLON);
}
return 1;
}
3.3 典型使用场景
# 设置 bootcmd 环境变量
setenv bootcmd "mmc read 0x00800000 0x4000 0x8000; bootm 0x00800000"
saveenv
# 执行 bootd,实际执行 bootcmd
bootd
# 等价于直接运行:
run bootcmd
3.4 Rockchip 特殊处理
Rockchip 平台在 boot_rkimg.c 中会检测启动模式并自动设置 bootcmd:
static void boot_devtype_init(void)
{
/* 1. 检查配置的启动设备 */
if (!param_parse_assign_bootdev(&devtype, &devnum)) {
if (!bootdev_init(devtype, devnum)) {
src = "assign";
goto finish;
}
}
/* 2. 检查 ATAGS 传递的启动设备 */
if (!param_parse_atags_bootdev(&devtype, &devnum)) {
if (!bootdev_init(devtype, devnum)) {
src = "atags";
goto finish;
}
}
/* 3. 扫描设备列表 */
ret = rk_board_scan_bootdev();
/* ... */
}
四、bootm 命令
4.1 功能说明
bootm 是 U-Boot 中最通用的启动命令,支持:
- Legacy uImage 格式
- FIT Image 格式
- Android boot.img 格式
- 多种压缩格式 (gzip, lzo, lzma)
4.2 实现架构
┌──────────────────────────────────────────────────────────────────┐
│ cmd/bootm.c: do_bootm() │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. 检查是否有子命令 │ │
│ │ 2. 调用 board_do_bootm() (Rockchip 扩展) │ │
│ │ 3. 调用 do_bootm_states() │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ common/bootm.c: do_bootm_states() │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. bootm_start() - 初始化 │ │
│ │ 2. bootm_find_os() - 查找 OS 镜像 │ │
│ │ 3. bootm_find_other() - 查找 ramdisk/fdt │ │
│ │ 4. bootm_load_os() - 加载 OS │ │
│ │ 5. boot_ramdisk_high() - 重定位 ramdisk │ │
│ │ 6. boot_fdt_add_mem_rsv_regions() - 保留内存 │ │
│ │ 7. image_setup_libfdt() / boot_prep_linux() - 准备参数 │ │
│ │ 8. boot_jump_linux() - 跳转到内核 │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ arch/arm/lib/bootm.c: do_bootm_linux() │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ARM64: boot_prep_linux() + boot_jump_linux() │ │
│ │ - boot_prep_linux(): 设置 FDT/ATAGS │ │
│ │ - boot_jump_linux(): EL 切换 + 跳转 │ │
│ │ │ │
│ │ ARM32: boot_prep_linux() + boot_jump_linux() │ │
│ │ - boot_prep_linux(): 设置 ATAGS/FDT │ │
│ │ - boot_jump_linux(): 非安全模式切换 + 跳转 │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
4.3 详细代码分析
4.3.1 入口: do_bootm()
源文件: cmd/bootm.c:92
int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
/* Rockchip 特殊处理: 给 board 层介入的机会 */
if (board_do_bootm(argc, argv))
return -EPERM;
/* 检查是否是子命令 (start, loados, ramdisk, fdt, etc.) */
argc--; argv++;
if (argc > 0) {
char *endp;
simple_strtoul(argv[0], &endp, 16);
/* 如果不是数字,也不是 FIT 格式的 '#' 或 ':' */
if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
return do_bootm_subcommand(cmdtp, flag, argc, argv);
}
/* 执行完整的 bootm 状态机 */
return do_bootm_states(cmdtp, flag, argc, argv,
BOOTM_STATE_START |
BOOTM_STATE_FINDOS |
BOOTM_STATE_FINDOTHER |
BOOTM_STATE_LOADOS |
BOOTM_STATE_RAMDISK |
BOOTM_STATE_OS_PREP |
BOOTM_STATE_OS_FAKE_GO |
BOOTM_STATE_OS_GO,
&images, 1);
}
4.3.2 核心状态机: do_bootm_states()
源文件: common/bootm.c
int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[], int states,
bootm_headers_t *images, int boot_progress)
{
/* BOOTM_STATE_START: 初始化 */
if (states & BOOTM_STATE_START) {
ret = bootm_start(cmdtp, flag, argc, argv);
if (ret)
return ret;
}
/* BOOTM_STATE_FINDOS: 查找并验证 OS 镜像 */
if (states & BOOTM_STATE_FINDOS) {
ret = bootm_find_os(cmdtp, flag, argc, argv);
if (ret)
return ret;
}
/* BOOTM_STATE_FINDOTHER: 查找 ramdisk 和 FDT */
if (states & BOOTM_STATE_FINDOTHER) {
ret = bootm_find_other(cmdtp, flag, argc, argv);
if (ret)
return ret;
}
/* BOOTM_STATE_LOADOS: 加载 OS */
if (states & BOOTM_STATE_LOADOS) {
ret = bootm_load_os(images, &load_end);
if (ret)
return ret;
}
/* BOOTM_STATE_RAMDISK: 重定位 ramdisk */
if (states & BOOTM_STATE_RAMDISK) {
ret = boot_ramdisk_high(&images->lmb, images->rd_start,
images->rd_end - images->rd_start,
&images->initrd_start,
&images->initrd_end);
if (ret)
return ret;
}
/* BOOTM_STATE_FDT: 处理设备树 */
if (states & BOOTM_STATE_FDT) {
ret = boot_fdt_add_mem_rsv_regions(&images->lmb,
images->ft_addr);
if (ret)
return ret;
}
/* BOOTM_STATE_OS_PREP: 准备 OS 参数 */
if (states & BOOTM_STATE_OS_PREP) {


6205

被折叠的 条评论
为什么被折叠?



