[Linux外设驱动详解]RK3588 U-Boot 启动命令实现机制详解

RK3588 U-Boot 启动命令实现机制详解

本文档详细分析 RK3588 平台 U-Boot 启动相关命令的实现机制,包括 bootd、bootm、bootz、booti、boot_android、bootrkp 等命令。


目录


一、概述

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) {
   
   
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JustaUncle

一杯咖啡,换我肝到天亮!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值