- 固件
- 嵌入式
- 操作系统
- 驱动开发
【免费下载链接】coreboot
Read-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We don't handle Pull Requests.
导读
coreboot 在构建 MediaTek(MT8173/MT8183/MT8189/MT8196 等)平台的启动镜像时,需要把标准 coreboot 产物转换成 MediaTek 芯片专用的启动格式,并验证第三方 PI_IMG 固件的合法性。本文以仓库中的 util/mediatek/description.md 为线索,结合 gen-bl-img.py 与 check-pi-img.py 的完整源码,逐字段讲解 MediaTek bootloader 头的生成算法、PI_IMG 的 cookie 校验规则、构建系统集成方式及运行时消费链路,读完即可独立理解并正确使用这两个工具。
一、工具定位:MediaTek 平台固件构建链路的两个关键环节
MediaTek 的 ARM64 平台(如 MT8173、MT8183)采用与主流 x86 平台不同的启动镜像格式:芯片 BootROM 期望在存储介质(eMMC 或 SPI NOR)的起始位置读到带特定魔数(Magic)的 bootloader 头,随后按布局加载 coreboot 的 bootblock 代码。因此构建流程中需要:
- gen-bl-img.py:把 coreboot 编译出的
bootblock.raw.bin打包成带 MediaTek 专用头(GFH 信息块 + SHA-256 校验 + 设备引导头)的bootblock.bin; - check-pi-img.py:校验厂商提供的
PI_IMG固件(pi_img.img)内部 cookie 个数是否符合预期,防止把损坏或错误的固件烧进 CBFS。
两个脚本均为 Python 3 单文件实现,无第三方依赖,位于仓库 util/mediatek/ 目录下。
二、gen-bl-img.py:生成 MediaTek bootloader 头
2.1 命令行用法
./util/mediatek/gen-bl-img.py <chip> <flash_type> <input_file> <output_file>参数说明(与脚本内main()的提示一致):
| 参数 | 取值 | 含义 |
|---|---|---|
chip | mt8173/mt8183/mt8189/mt8196 | SoC 型号,决定 GFH 加载地址 |
flash_type | emmc/sf | 启动介质类型,决定设备头魔数(EMMC_BOOT或SF_BOOT) |
input_file | 任意路径 | 待封装的原始镜像(通常是bootblock.raw.bin) |
output_file | 任意路径 | 生成的带头的最终镜像 |
脚本内部仅对输入文件做读取与打包,不修改输入文件。注意脚本中main()打印的用法提示仅列出mt8173|mt8183,但gen_gfh_info()的条目表实际已支持四个芯片(见下节),这是脚本提示文本相对滞后于能力的一点,使用时以芯片条目表为准。
2.2 处理流水线
gen_preloader(chip_ver, flash_type, data)是整个工具的核心,其流程可概括为四步:
- 调用
gen_gfh_info()生成 176 字节的 GFH(Generic File Header)信息块; - 计算
sha256(gfh_info + data),得到 32 字节镜像哈希,追加在数据之后; - 将
gfh_info + data + hash整体以0xff填充对齐到 512 字节边界(align(..., 512, b'\xff')); - 调用
gen_emmc_header()/gen_sf_header()生成设备引导头,最终输出header + data。
其结构关系可概括为:
| 设备引导头 (512B ×3, 含 EMMC_BOOT/SF_BOOT + BRLYT 布局) | | GFH 信息块 (176B) | 原始数据 (bootblock.raw.bin) | SHA-256 (32B) | 0xff 填充对齐 |2.3 GFH 信息块字段解析
gen_gfh_info()用'<44I'(44 个小端 uint32,共 176 字节)打包一段固定结构:
- 前 4 个字包含魔数
0x014d4d4d(小端下对应 ASCII 片段MMM+0x01)、块大小0x00000038(56,对应首子块长度)、0x454c4946与0x464e495f(小端下对应 ASCII 串FILE与_INF,指示这是一个文件信息子块)、文件名长度0x0000004f、版本0x00000001、类型0x01050001; - 第 10 个字
load_addr由芯片条目表决定:entries[chip] - gfh_size,其中gfh_size = 176。各芯片的基准地址为:
| 芯片 | 基准地址entries[chip] | 实际 load_addr |
|---|---|---|
| mt8173 | 0x000C1000 | 0x000C0F50 |
| mt8183 | 0x00201000 | 0x00200F50 |
| mt8189 | 0x02001000 | 0x02000F50 |
| mt8196 | 0x02001000 | 0x02000F50 |
- 第 11 个字
load_size = gfh_size + len(data) + 32(GFH + 数据 + SHA-256 摘要长度),随后紧跟0x00020000、0x000000a8、0x00000020、0x000000B0等区块长度与偏移描述; - 尾部的
0x52000000、0x00006400、0x00001388等字段与 GFH 中各类子块的类型标识及属性相关,其余大量零字为保留字段。由于该结构属于 MediaTek 未公开的启动协议细节,脚本以固定常量形式写死,用户无需也无法改动。
2.4 设备引导头:EMMC_BOOT 与 SF_BOOT
gen_emmc_header()与gen_sf_header()结构完全对称,共 3 × 512 字节:
- 第 1 个 512 字节块:
struct.pack('<12sII', b'EMMC_BOOT', 1, 512)(或b'SF_BOOT'),即 12 字节魔数 + 版本号1+ 首块大小512,剩余部分以0xff填充到 512 字节; - 第 2 个 512 字节块:
BRLYT(Boot Rom Layout)布局描述,struct.pack('<8sIIIIIIII', ...)包含:- 魔数
BRLYT; - 版本
1; - 偏移
2048与大小2048 + len(data):指向下一段的起始位置与总大小; - 未知标识
0x42424242(ASCIIBBBB); - 类型字段:eMMC 为
0x00010005,SPI 为0x00010007——这是两个介质头的唯一实质差异; - 再次记录偏移与大小,以及条目数量
1; - 固定补 140 字节
0x00,再以0xff填充至 512 字节;
- 魔数
- 第 3 个 512 字节块:全部为
0x00(b'\0' * 1024补足)。
gen_dev_header字典把'emmc'/'sf'映射到上述两个函数,gen_preloader()据此选择头类型,因此传错flash_type会在头内留下错误的魔数与介质类型标识。
2.5 对齐与填充细节
- 数据区对齐用
0xff(Flash 编程常以0xff为擦除态),代码:align(data, size, pattern=b'\xff'); - 对齐公式为
(len(data) + (size - 1)) & ~(size - 1),即向上取整到 512 的整数倍; padding()在不足时用指定 pattern 补足,若数据恰好等长则原样返回(不做截断)。
三、check-pi-img.py:校验 PI_IMG 固件的 cookie 标记
3.1 命令行用法
./util/mediatek/check-pi-img.py <pi_img>3.2 校验逻辑
脚本逻辑非常简洁:从偏移0x200(HEADER_OFFSET)开始,以 4 字节为单位逐段读取整个文件,统计数值等于0x17C3A6B4(COOKIE)的次数;只有恰好检测到2 个cookie 才判定合法,否则抛出ValueError:
raise ValueError("Invalid PI_IMG {} (expected 2 cookies; found {})" .format(pi_img, cookie_count))该 cookie 是 MediaTek PI 镜像内部的标志魔数,用于在整包固件中定位关键描述符。文件被截断、字节序错误或混入其他固件都会导致计数不等于 2,从而被工具拒绝。脚本返回非零退出码,便于构建系统把校验失败当作构建失败处理。
3.3 在构建系统中的强制校验
在 src/soc/mediatek/mt8196/Makefile.mk 中,校验被做成独立的 phony 目标,并作为coreboot.pre的 order-only 前置依赖,确保每次构建正式产物前必然执行:
PI_IMG := $(MT8196_BLOB_DIR)/$(call strip_quotes,$(CONFIG_PI_IMG_FIRMWARE)) .PHONY: check_pi_img check_pi_img: $(PI_IMG) ./util/mediatek/check-pi-img.py $< # Make sure check_pi_img is always run. $(obj)/coreboot.pre: | check_pi_img其中$(CONFIG_PI_IMG_FIRMWARE)默认值为pi_img.img,位于3rdparty/blobs/soc/mediatek/mt8196/目录下。
四、构建系统集成:各 SoC 的调用方式
gen-bl-img.py 被各 MediaTek SoC 的 Makefile 以定制规则接入:bootblock 的最终产物由bootblock.raw.bin通过该脚本转换得到。
| SoC | Makefile 规则 | chip | flash_type |
|---|---|---|---|
| MT8173 | src/soc/mediatek/mt8173/Makefile.mk | mt8173 | sf |
| MT8183 | src/soc/mediatek/mt8183/Makefile.mk | mt8183 | emmc |
| MT8189 | src/soc/mediatek/mt8189/Makefile.mk | mt8189 | sf |
| MT8196 | src/soc/mediatek/mt8196/Makefile.mk | mt8196 | sf |
示例规则(MT8189/MT8196 相同):
$(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin ./util/mediatek/gen-bl-img.py mt8189 sf $< $@可见 MT8183 平台从 eMMC 启动(emmc头),而 MT8173、MT8189、MT8196 从 SPI NOR 启动(sf头)。日常构建无需手动调用该脚本,make会自动完成转换。
五、运行时消费链路:PI_IMG 进入 FSP 与 MCUPM
理解 check-pi-img.py 校验的对象,需要看 PI_IMG 在运行时的用途:
- 固件打包进 CBFS:在 MT8189/MT8196 的 Makefile 中,
pi_img.img与 DPM、MCUPM、SPM、SSPM 等固件一起以raw类型、LZ4压缩方式写入 CBFS(见 src/soc/mediatek/mt8189/Makefile.mk 的firmware-files列表); - 加载与传递:src/soc/mediatek/common/pi_image.c 中的
pi_image_load()通过mtk_init_mcu()从 CBFS 加载固件到dram_dma缓冲区,再由pi_image_add_mtk_fsp_params()以FSP_PARAM_TYPE_PI_IMG与FSP_PARAM_TYPE_PI_IMG_CSRAM两个参数注册进 MediaTek FSP 接口; - Kconfig 说明:在 src/soc/mediatek/mt8189/Kconfig 中,
PI_IMG_FIRMWARE的 help 明确写到:PI image 的主要用途是将各种频率与电压缩放参数和设置传递给 MCUPM; - 错误状态定义:src/soc/mediatek/common/include/soc/mtk_fsp_common.h 定义了
FSP_STATUS_INVALID_PI_IMG状态码,说明 FSP 侧同样会对 PI_IMG 的合法性做校验——check-pi-img.py 正是构建阶段的第一道防线。
通用固件加载逻辑在 src/soc/mediatek/common/mcu.c 的mtk_init_mcu()中:cbfs_load()从 CBFS 取固件,随后(若配置了run_address)拷贝到运行地址并做内存屏障,最后复位对应 MCU。因此check_pi_img构建目标实际守护的是这条"CBFS → FSP → MCUPM 频率电压缩放"链路的输入质量。
六、常见使用场景与命令速查
手动校验厂商提供的 PI 镜像:
python3 util/mediatek/check-pi-img.py 3rdparty/blobs/soc/mediatek/mt8196/pi_img.img # 校验通过则无输出;失败则报: # ValueError: Invalid PI_IMG ... (expected 2 cookies; found N)手动为 bootblock 打头(对应 MT8196 的 SPI 启动配置):
python3 util/mediatek/gen-bl-img.py mt8196 sf build/bootblock.raw.bin build/bootblock.bin结语
这两个看似只有一行的工具说明背后,是 MediaTek SoC 与 coreboot 构建系统深度绑定的产物:gen-bl-img.py负责把通用 coreboot 产物翻译成 BootROM 能识别的EMMC_BOOT/SF_BOOT+BRLYT+ GFH 格式,check-pi-img.py则通过双 cookie 规则在构建早期拦截异常的 PI_IMG 固件。理解它们的输入输出与集成方式,是排查 MediaTek 平台启动失败、或为新增 MediaTek SoC 接入 coreboot 构建链路的必要基础。
- 固件
- 嵌入式
- 操作系统
- 驱动开发
【免费下载链接】coreboot
Read-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We don't handle Pull Requests.
相关推荐
coreboot 固件镜像工具链 cbfstool 完全指南:CBFS、FMAP 与 IFWI 操作实战
coreboot 固件镜像工具链 cbfstool 完全指南:CBFS、FMAP 与 IFWI 操作实战 本篇指南围绕 coreboot 仓库 util/cbf
固件嵌入式操作系统驱动开发coreboot 工具链完全指南:util 目录下的构建、镜像处理与硬件调试实用工具
coreboot 工具链完全指南:util 目录下的构建、镜像处理与硬件调试实用工具 coreboot 的 util 目录是随项目源码一同发布的实用工具集合,涵
固件嵌入式操作系统驱动开发Raspberry Pi OS 镜像生成工具:pi-gen 项目推荐
Raspberry Pi OS 镜像生成工具:pi gen 项目推荐 项目基础介绍和主要编程语言 pi gen 是一个用于创建官方 Raspberry Pi O
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考