fastboot刷写与嵌入式Linux启动优化实战 - 第3节

3.1 分区表概念与嵌入式布局

在嵌入式 Linux 系统中,存储介质(eMMC / NAND / UFS)通常被划分为多个固定大小的区域,称为分区。分区表记录了每个分区的起始地址、大小、属性和用途。Fastboot 刷写的本质就是按照分区表将镜像写入对应的物理区域。

3.1.1 分区表的核心要素

要素 说明 典型值
分区名称 Fastboot 命令中使用的逻辑标识 boot、system、vendor
起始地址 分区在存储介质上的偏移量(LBA 或字节) 0x00008000
分区大小 分配给该分区的最大容量 64 MiB、2 GiB
分区类型 文件系统或裸数据标识 ext4、raw、gpt
属性标志 可引导、只读、隐藏等 bootable、read-only
实践要点:嵌入式设备通常使用 GPT(GUID Partition Table)或 MBR(Master Boot Record)两种分区表格式。GPT 支持更多分区(128+)和更大容量,是当前主流选择。

3.1.2 典型嵌入式分区布局

以下是一个基于 eMMC 的典型 Android / Linux 嵌入式分区布局示意:

嵌入式 eMMC 典型分区布局 xbl aboot boot system vendor userdata 启动引导 内核+ramdisk 系统镜像 硬件驱动/库 用户数据 分区表存储位置 • GPT 分区表:位于 LBA 1(第二个扇区),备份位于最后一个 LBA。 • MBR 分区表:位于 LBA 0(第一个扇区),最多支持 4 个主分区。 • Fastboot 通过 fastboot getvar partition-size:boot 查询分区信息。
常见陷阱:分区大小不匹配是刷写失败的首要原因。如果镜像文件大于目标分区,Fastboot 会报 FAILED (remote: 'size too large')。刷写前务必使用 fastboot getvar all 确认分区容量。

3.2 boot / system / vendor 分区刷写实战

这三个分区是嵌入式 Linux 启动的核心:boot 包含内核与 ramdisk,system 包含系统服务与框架,vendor 包含硬件抽象层(HAL)与专有库。刷写顺序和参数直接影响设备能否正常启动。

3.2.1 刷写命令与参数详解

分区 Fastboot 命令 镜像格式 关键参数
boot fastboot flash boot boot.img boot image (内核 + dtb + ramdisk) 必须包含 kernel 和 ramdisk
system fastboot flash system system.img ext4 / sparse image 支持 sparse 格式节省传输时间
vendor fastboot flash vendor vendor.img ext4 / sparse image 与 system 版本必须匹配

3.2.2 刷写流程与状态检查

  1. 进入 Fastboot 模式:设备上电时按住特定按键(如音量减 + 电源),或通过 adb reboot bootloader 进入。
  2. 确认连接:执行 fastboot devices,应返回设备序列号。
  3. 擦除旧分区(可选):fastboot erase boot 清除分区内容,避免残留数据干扰。
  4. 刷写 boot 分区:fastboot flash boot boot.img,等待 OKAY 状态。
  5. 刷写 system 分区:fastboot flash system system.img,大镜像可能需要数分钟。
  6. 刷写 vendor 分区:fastboot flash vendor vendor.img。
  7. 验证刷写:fastboot getvar all 检查分区版本哈希。
刷写状态码解读:
  • OKAY [0.123s] — 刷写成功,耗时 123 毫秒。
  • FAILED (remote: 'partition table doesn't exist') — 分区表未烧录或损坏。
  • FAILED (remote: 'flash write failure') — 存储介质写入错误,可能硬件故障。
Fastboot 刷写 boot/system/vendor 流程 进入 Fastboot 擦除分区 刷写 boot 刷写 system 刷写 vendor 验证重启

3.3 刷写脚本编写与自动化

手动逐条输入 Fastboot 命令效率低且容易出错。通过编写刷写脚本,可以将整个流程自动化,支持批量生产场景。以下分别给出 Windows(批处理)和 Linux(Shell)两种脚本示例。

3.3.1 Windows 批处理脚本(flash.bat)

@echo off
echo ========================================
echo   Fastboot 刷写脚本 - 嵌入式 Linux
echo ========================================

:: 检查 Fastboot 连接
fastboot devices >nul 2>&1
if %errorlevel% neq 0 (
    echo [ERROR] 未检测到 Fastboot 设备,请检查连接。
    pause
    exit /b 1
)

:: 擦除分区(可选)
echo [INFO] 正在擦除 boot/system/vendor 分区...
fastboot erase boot
fastboot erase system
fastboot erase vendor

:: 刷写分区
echo [INFO] 正在刷写 boot.img...
fastboot flash boot boot.img
if %errorlevel% neq 0 (
    echo [ERROR] boot 分区刷写失败!
    pause
    exit /b 1
)

echo [INFO] 正在刷写 system.img...
fastboot flash system system.img
if %errorlevel% neq 0 (
    echo [ERROR] system 分区刷写失败!
    pause
    exit /b 1
)

echo [INFO] 正在刷写 vendor.img...
fastboot flash vendor vendor.img
if %errorlevel% neq 0 (
    echo [ERROR] vendor 分区刷写失败!
    pause
    exit /b 1
)

:: 验证刷写
echo [INFO] 验证分区版本...
fastboot getvar all | findstr "partition-size"

echo [SUCCESS] 所有分区刷写完成!
pause

3.3.2 Linux Shell 脚本(flash.sh)

#!/bin/bash
# Fastboot 刷写脚本 - 嵌入式 Linux
# 用法: ./flash.sh [镜像目录路径]

set -e

IMAGE_DIR="${1:-.}"
echo "========================================"
echo "  Fastboot 刷写脚本 - 嵌入式 Linux"
echo "  镜像目录: $IMAGE_DIR"
echo "========================================"

# 检查 fastboot 命令
if ! command -v fastboot &> /dev/null; then
    echo "[ERROR] fastboot 命令未找到,请安装 Android SDK 平台工具。"
    exit 1
fi

# 检查设备
fastboot devices 2>&1 | grep -q "fastboot"
if [ $? -ne 0 ]; then
    echo "[ERROR] 未检测到 Fastboot 设备。"
    exit 1
fi

# 定义分区列表
PARTITIONS=("boot" "system" "vendor")

# 擦除并刷写
for part in "${PARTITIONS[@]}"; do
    img_file="${IMAGE_DIR}/${part}.img"
    if [ ! -f "$img_file" ]; then
        echo "[WARNING] 镜像文件 $img_file 不存在,跳过 $part 分区。"
        continue
    fi
    echo "[INFO] 正在擦除 $part 分区..."
    fastboot erase "$part" || true
    echo "[INFO] 正在刷写 $part 分区 ($img_file)..."
    fastboot flash "$part" "$img_file"
    echo "[INFO] $part 分区刷写完成。"
done

# 验证
echo "[INFO] 验证分区刷写结果..."
fastboot getvar all 2>&1 | grep -E "partition-size:|version"

echo "[SUCCESS] 所有分区刷写完成!"

3.3.3 脚本关键设计原则

原则 说明 脚本实现示例
幂等性 多次执行脚本结果一致,不会因重复刷写导致状态异常 每次刷写前先 erase 分区
错误处理 任一分区刷写失败时立即停止,避免部分更新导致设备变砖 Shell 脚本使用 set -e,批处理检查 %errorlevel%
可配置性 镜像路径、分区列表可通过参数或环境变量调整 Shell 脚本接受 $1 作为镜像目录
日志输出 清晰显示当前步骤、成功/失败状态,便于排查 使用 [INFO]、[ERROR] 前缀标记
生产环境建议:在批量烧录场景中,建议在脚本中加入 CRC 校验步骤:刷写完成后读取分区内容并计算哈希,与原始镜像对比,确保数据完整性。例如:fastboot get_staged boot.img 配合本地 sha256sum 比对。
刷写脚本自动化流程 检查环境 遍历分区列表 擦除+刷写 错误处理 验证完成 循环处理下一个分区

3.4 刷写常见问题与排错

  • 问题:FAILED (remote: 'not supported in locked device')
    原因:设备 bootloader 处于锁定状态。
    解决:执行 fastboot flashing unlock 解锁(注意:会清除用户数据)。
  • 问题:FAILED (remote: 'size too large')
    原因:镜像文件大于分区容量。
    解决:使用 fastboot getvar partition-size:boot 查看分区大小,重新编译或裁剪镜像。
  • 问题:刷写后设备卡在启动 logo
    原因:boot 分区内核与 system 分区版本不匹配,或 vendor 分区缺少关键驱动。
    解决:确保三个镜像来自同一构建版本,重新刷写全部三个分区。
  • 问题:fastboot devices 无输出
    原因:USB 驱动未安装或设备未进入 Fastboot 模式。
    解决:在 Linux 下检查 lsusb,Windows 下安装设备厂商驱动。
重要提醒:刷写操作具有高风险。在量产或开发板上操作前,务必确认拥有完整的原始固件备份。错误的刷写可能导致设备无法恢复,需要硬件烧录器才能修复。