coreboot 中的 Flashmap 与 FMD 布局描述语言:固件分区格式与工程实践

发布时间:2026/10/14 5:25:52

coreboot 中的 Flashmap 与 FMD 布局描述语言:固件分区格式与工程实践 固件嵌入式操作系统驱动开发【免费下载链接】corebootRead-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We dont handle Pull Requests.项目地址https://gitcode.com/gh_mirrors/co/coreboot点击查看免费下载导读coreboot 的固件镜像coreboot.rom不再只是一个被 CBFS 打包的大文件而是可以通过 FlashmapFMAP将整个 flash 芯片划分为若干边界清晰的独立分区。本文以 Documentation/lib/flashmap.md 为主体结合仓库内struct fmap的二进制定义、FMD 语言编译器Lex/Yacc 实现与fmaptool工具源码系统讲解 FMAP 的二进制格式、FMD 描述语言的完整语法与工程约束并给出从.fmd文件到最终镜像的完整工具链与运行时查询 API帮助你理解并编写自己的 flash 布局。FlashmapFMAP为什么 coreboot 需要它Flashmap 是一种用于描述 flash 芯片内分区的二进制格式。它最初是为了满足 ChromiumOS 固件的需求而引入 coreboot 的之后也被用于其他需要精确放置数据、或需要在运行时写入数据的场景——因为对这些场景而言CBFS 被认为过于脆弱CBFS 以文件为单位组织内容文件的位置与边界由构建工具动态决定无法满足某段数据必须位于某固定地址这类硬性要求。Flashmap 将镜像划分为清晰界定的小节section其中部分小节可以是 CBFS——能够容纳任意长度文件至少有一个默认 CBFS通常命名为COREBOOT。工程上的通用准则是有严格布局要求的内容例如必须对齐到擦除块、或必须位于固定地址的数据应拥有独立的 Flashmap 分区其余一切内容通常都应该放进 CBFS。如今 coreboot 内部的 Flashmap 实现已成为事实上的标准实现。FMAP 二进制格式头部与分区描述整个 Flashmap 由一个头部struct fmap和紧随其后的一组分区描述struct fmap_area组成所有字段均为**小端little endian**格式。该结构在仓库中的精确定义位于 src/commonlib/bsd/include/commonlib/bsd/fmap_serialized.h。头部struct fmap字段类型/长度含义signature8 字符固定为__FMAP__十六进制0x5F5F464D41505F5Fver_major1 字节主版本号目前仅为 1ver_minor1 字节次版本号当前值为 1base64 位整数固件二进制镜像的地址size32 位整数固件二进制镜像的大小字节name32 字符固件二进制镜像的名称nareas16 位整数紧随头部之后的分区area定义数量源码中通过FMAP_STRLEN32含终止符约束字符串长度FMAP_VER_MAJOR/FMAP_VER_MINOR均为 1与文档描述一致。分区定义struct fmap_area字段类型/长度含义offset32 位整数分区起始位置相对于头部中的basesize32 位整数分区大小字节name32 字符分区描述性名称在同一 Flashmap 内应唯一flags16 位整数分区的属性标志见下在 fmap_serialized.h 中enum fmap_flags定义了四个标志位标志值说明FMAP_AREA_STATIC1 0目前并未真正使用FMAP_AREA_COMPRESSED1 1目前并未真正使用FMAP_AREA_RO1 2目前并未真正使用FMAP_AREA_PRESERVE1 3建议在固件更新时保留该分区通常用于存放序列号、MAC 地址、校准数据或缓存数据等产品数据也就是说当前真正有实际语义的标志只有PRESERVE其余三个标志在格式中预留但未投入使用。FMAP 分区的存放位置与 COREBOOT 分区FMAP section整个 Flashmapstruct fmap头部 struct fmap_area列表应存放在一个独立的、名为FMAP的分区中并且这个FMAP分区自身也要通过一个struct fmap_area被 Flashmap 描述出来。对于FMAP分区位于何处、多大格式本身没有硬性限制但由于通常需要在整个固件镜像上进行线性或二分查找来定位 Flashmap因此选择一个对齐良好的地址会更有利。在 coreboot 的 FMD 工具链中FMAP分区名由常量SECTION_NAME_FMAP定义见 util/cbfstool/cbfs_sections.h并且fmaptool会强制要求描述文件中必须存在名为FMAP的分区否则直接报错退出FMAPTOOL_EXIT_MISSING_FMAP_SECTION。COREBOOT sectioncoreboot 固件镜像coreboot.rom应当至少有一个保留给 CBFS 的 Flashmap 分区通常命名为COREBOOT。在工具层面cbfs_sections.h中定义了主 CBFS 分区名SECTION_NAME_PRIMARY_CBFS COREBOOT并规定必须存在一个标注了(CBFS)的COREBOOT分区cbfs_sections_primary_cbfs_accounted_for()否则fmaptool同样会拒绝生成FMAPTOOL_EXIT_MISSING_PRIMARY_CBFS。此外还预定义了COREBOOT_B次 CBFS、BOOTBLOCK、BOOTBLOCK_B等常用分区名约定。Flashmap DescriptorFMD描述 flash 布局的纯文本语言由于 coreboot 开始使用 Flashmap 的分区概念来描述 flash 芯片布局无论是运行时还是刷写新镜像时项目需要一个在源码树中表达能力足够强的纯文本格式来表示这些分区。于是产生了 Flashmap DescriptorFMD——位于 corebootutil/cbfstool目录下的一个语言及其编译器可用它生成符合 Flashmap 格式的最终固件镜像即coreboot.rom。FMD 的实现由三部分组成fmd.h数据结构与解析前端 APIfmd_scanner.lLex 词法规则同时有生成的fmd_scanner.c_shippedfmd_parser.yYacc 语法规则同时有生成的fmd_parser.c_shipped。文档中给出的非正式语法如下# line comment image name[memory-mapped address] image size { section name[(flags)][offset from start of image] [section size] [{ subsection name[offset from start of parent section] [subsection size] [{ # Sections can be nested as deeply as desired subsubsection name[(flags)][...] [...] [{...}] }] [subsection name[(flags)][...] [...] [{...}]] # There can be many subsections at each level of nesting: they will be inserted # sequentially, and although gaps are allowed, any provided offsets are always # relative to the closest parent nodes and must be strictly increasing with neither # overlapping nor degenerate-size sections. }] }需要特别强调的是上述示例中带有.*尖括号的部分属于元语法在真实文件中并不存在[.*]表示该部分可以整体省略。各参数的实际规则如下名称是无引号、无其他定界符的单个单词不含空白的字符串由除、{、}之外的所有符号组成数值非负整数可用十进制或十六进制书写两种写法后都可以无空白地追加K、M或G作为倍率后缀注释以#开始直到本行行末的所有内容均为注释。可选字段与标志的规则[.*]表示文件中的某一部分可以整体省略但可选并不意味着任何情况下都可省是否可省取决于其他信息是否给出标志flags为给定分区指定属性或类型。最重要的标志是CBFS表示该分区将包含 CBFS 结构。在 fmd.h 中union flashmap_flags定义了三种标志位cbfs包含 CBFS 区域、preserve更新前保留该分区、ext分区存在扩展区仅可用于 CBFS 分区对应解析器中的FLAG_CBFS、FLAG_PRESERVE、FLAG_EXT三个 tokenCBFS 标志只能放在叶子分区上一旦给某分区添加了子分区就不能再在其父分区上放置 CBFS 标志。这些标志只用于决定在哪里创建 CBFS 的空文件头不会在最终 FMAP 分区中存储任何额外元数据这一点在 fmd_parser.y 中体现为CBFS 标志会触发fmd_process_flag_cbfs()回调来通知并校验客户端在 fmd_parser.y 的parse_descriptor()中还有两条硬性约束分区名不能以ECBFS_开头该前缀被保留给 CBFS 扩展区且非 CBFS 分区不能带ext标志。整个文件的整体属性除逐条语法外FMD 语言还有以下整体性质除字符串和数字内部外空白一律被忽略分区名必须全局唯一但允许其中一个非强制与镜像名相同以0开头的非零数字是语法错误——语言有意不引入八进制镜像的内存映射地址后的值只能出现在内存映射型芯片的布局文件中所有分区偏移都仅相对于直接父节点不存在从 flash 起始处的绝对偏移。因此只要改动不会导致位置和大小重叠或出现零大小在某一嵌套层级内重排分区顺序是安全的省略偏移的分区默认从其父节点内尽可能低的位置开始不考虑对齐省略大小的分区默认填充到下一个兄弟分区之前或父分区末尾只要在兄弟分区和父分区大小的语境下位置和大小仍然无歧义任意分区都可以省略偏移、大小或两者都省略。但注意推断时不会利用某分区的子分区信息也不会利用其祖父的兄弟分区信息分区不要求必须有子分区但整个 flash 芯片必须至少有一个分区无子分区的分区可以省略花括号但一旦写了花括号里面就必须至少有一个子分区。从 .fmd 到 .romfmaptool 与 FMDFILE 集成fmaptool 命令行用法将.fmd描述文件编译为 FMAP 二进制块的入口是 util/cbfstool/fmaptool.c。其完整用法如下fmaptool [-h header output file] [-R region output file] fmd input file binary output file参数说明fmd input file输入描述文件传入-表示从标准输入读取binary output file输出的 FMAP 二进制文件必须为普通文件-h header output file同时生成一个 C 头文件其中定义FMAP_OFFSETFMAP 分区的 flash 偏移见 fmaptool.c-R region output file同时生成一个文本文件逐行列出包含 CBFS 的分区名逗号分隔。成功运行时fmaptool 会向标准错误输出工作摘要并向标准输出打印所有包含 CBFS 的分区名逗号分隔、主分区COREBOOT在前若描述文件缺少FMAP分区或缺少带(CBFS)标注的主 CBFS 分区工具会以非零退出码终止并打印FATAL错误。生成的 C 头文件除了FMAP_OFFSET和FMAP_SIZE外还会为描述树中的每个分区生成FMAP_SECTION_NAME_START绝对 flash 偏移与FMAP_SECTION_NAME_SIZE宏以及一个FMAP_TERMINAL_SECTIONS字符串宏列出所有无子分区的叶子分区名见 fmaptool.c。构建系统中的 FMDFILE在 coreboot 构建系统中主板的 flash 布局文件通过FMDFILEKconfig 选项接入fmaptool将$(FMDFILE)编译成 FMAP 段再与 CBFS 一起打包进最终的coreboot.rom。例如 src/mainboard/emulation/qemu-q35/Kconfig 中会根据 vboot 的VBOOT_SLOTS_RW_A/VBOOT_SLOTS_RW_AB配置分别选用vboot-rwa-8M.fmd或vboot-rwab-8M.fmd。真实布局示例解读以 src/mainboard/51nb/x210/board.fmd 为例该文件是一个手写 FMD目的是在 BIOS 区域底部为 EC 预留空间FLASH 8M { BIOS0x200000 0x600000 { EC0x0 0x10000 RW_MRC_CACHE0x10000 0x10000 SMMSTORE0x20000 0x40000 CONSOLE0x60000 0x20000 FMAP0x80000 0x200 COREBOOT(CBFS) } }逐行解读FLASH 8M整个 flash 镜像名为FLASH、大小8M8 MiB即8 * 1024 * 1024字节M倍率在此生效BIOS0x200000 0x600000一级分区BIOS从 flash 起始偏移0x200000处开始、大小0x600000此处的偏移相对其父节点flash 根内层五个子分区均为叶子分区EC0x064KiB、RW_MRC_CACHE0x1000064KiB、SMMSTORE0x20000256KiB、CONSOLE0x60000128KiB、FMAP0x80000512B所有偏移都相对父分区BIOS的起始处COREBOOT(CBFS)主 CBFS 分区省略了偏移和大小——它将自动填充到BIOS分区内剩余的全部空间并带(CBFS)标志表明内部为 CBFS 结构。注意FMAP0x80000 0x200自身也被列入描述中这正符合FMAP 分区也必须是 Flashmap 所描述分区之一的要求。运行时如何利用 FMAPfmap.c 的查询 API 与缓存机制FMAP 不只是构建期的布局工具固件运行时同样依赖它来定位各个分区。核心实现位于 src/lib/fmap.c对外提供的主要 API 包括fmap_locate_area(name, region)按分区名查找返回其在 flash 中的偏移与大小fmap.cfmap_locate_area_as_rdev()/fmap_locate_area_as_rdev_rw()以只读/读写region_device形式返回分区fmap_find_region_name()反向操作给定区域查其名称fmap_read_area()/fmap_overwrite_area()直接对命名分区做整段读取或擦除重写。这些 API 的底层流程值得注意find_fmap_directory()会优先使用 FMAP 缓存pre-RAM 阶段将 flash 上的 FMAP 拷贝进_fmap_cache区域见 fmap.c并且verify_fmap()会校验__FMAP__签名若开启了CBFS_VERIFICATION在初始阶段还会对 FMAP 做元数据哈希校验失败则直接die()以防止 TOCTOU 攻击。ramstage 之后FMAP 还会被复制进 CBMEMCBMEM_ID_FMAP并通过CBMEM_READY_HOOK注册缓存供后续阶段乃至 OS 使用。分区的名称匹配与偏移换算都是按小端序从二进制区逐一扫描完成的与 fmap_serialized.h 中的结构定义严格对应。正是通过这套构建期 fmaptool 生成 运行期 fmap.c 查询的组合coreboot 才能可靠地把 MRC 缓存、SMMSTORE、串口日志CONSOLE等需要运行时读写的区域精确安置在 flash 的固定位置同时让普通文件继续使用灵活、动态的 CBFS。编写 FMD 的常见约束小结综合文档语法与工具源码的校验逻辑编写自己的.fmd布局文件时需要特别注意描述树中必须有名为FMAP的分区且必须有一个标注(CBFS)的分区名为COREBOOTcbfs_sections.hCBFS、PRESERVE标志只能写在叶子分区上非 CBFS 分区不能带ext标志分区名不得以ECBFS_开头分区名长度不能超过FMAP_STRLEN - 131 字符镜像名同理否则fmap_from_fmd()会拒绝生成见 fmap_from_fmd.c非零数字不能以0开头避免八进制歧义大小与偏移可用十进制/十六进制 K/M/G后缀同一层级内的分区其偏移无论显式还是推断必须严格递增且不得重叠、不得为零大小省略大小即填充剩余空间省略偏移即尽可能靠前只有内存映射型芯片的布局才应在镜像名后写地址。遵循这些规则你就可以为任意主板编写一份可编译、可被fmaptool与运行时代码共同消费的 flash 布局描述精确掌控固件镜像中每一字节的去向。赞分享固件嵌入式操作系统驱动开发【免费下载链接】corebootRead-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We dont handle Pull Requests.项目地址https://gitcode.com/gh_mirrors/co/coreboot点击查看免费下载相关推荐veryl现代硬件描述语言的探索与实践veryl现代硬件描述语言的探索与实践 项目介绍 veryl 是一种现代硬件描述语言基于 SystemVerilog 设计旨在为硬件设计师提供一种更加高效编译器/解释器硬件开发开发工具coreboot SoundWire 实现指南基于 MIPI DisCo 规范的固件拓扑描述与 ACPI 生成coreboot SoundWire 实现指南基于 MIPI DisCo 规范的固件拓扑描述与 ACPI 生成 SoundWire 是 MIPI 联盟推出的低固件嵌入式操作系统驱动开发Amaranth硬件描述语言指南从基础到实践Amaranth硬件描述语言指南从基础到实践 前言 Amaranth是一种基于Python的硬件描述语言 HDL 它允许开发者使用Python语法来描述数字硬件开发嵌入式上一篇GIST-Embedding-v0-openmind未来路线图即将推出的新功能与改进下一篇Webpack Bundle Analyzer 常见问题解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/14 5:25:52

AnyPS5:一个PS5跨机型游戏数据管理工具箱的架构与实践

“AnyPS5”这个名字,是我给一个工具项目起的代号。它不是一台新的游戏主机,也不是什么“全兼容”外设,而是一个围绕PS5日常使用场景的跨机型管理工具箱。简单说,它解决的是这样一个问题:当你有不止一台主机、不止一个账…

2026/10/14 5:25:52

数据中台建设常见的三个认知误区及对应落地建议

企业数字化转型进入深水区,不少组织都面临跨系统数据不通、口径不统一的问题。很多团队启动数据中台建设时,由于缺乏成熟的参考经验,容易走入各类认知误区,导致项目超支、进度拖延,最终建成的平台沦为闲置摆设。下面梳…

2026/10/14 6:21:19

OpenClaw API配置实战:从入门到自动化工作流搭建

最近不少朋友在问,网上说的那个开源工具 OpenClaw 到底怎么配置 API 才能免费跑起来。我一开始也以为这东西和那些需要折腾很久才能用的服务一样,结果实际看了一下,发现它的配置思路其实很清晰,门槛比想象中低不少。这篇就把我自己…

2026/10/14 6:21:19

IDEA创建Spring Boot项目:五种方式详解与选型指南

用 IntelliJ IDEA 创建 Spring Boot 项目,看起来是件小事,但我在带新人的时候发现,恰恰是这一步,能把入门者分岔成两类:一类顺利跑起了项目,另一类卡在“怎么生成骨架”上大半天。严格说,IDEA 里…

2026/10/14 6:21:19

Claude Skills 从零构建指南:按需加载机制与实战技巧

1. 从零理解 Claude Skills 到底是什么1.1 一个被名字耽误的能力扩展机制第一次看到 Claude Skills 这个词,很多人会以为它又是一个新的模型版本或者某个付费功能。其实不是。Claude Skills 本质上是一套让模型学会“按需加载专业知识包”的机制。你可以把它想象成给…

2026/10/14 6:21:19

NAT实战指南:原理、四种转换类型与配置排错

搞网络的人,迟早都会撞上NAT这个词。不管是刚入门的学生,还是在机房摸爬滚打多年的老手,只要你的网络需要上网、需要对外开放服务、需要做地址规划,就一定绕不开网络地址转换这个基础技术。数据通信课程里NAT通常作为核心章节出现…

2026/10/14 6:21:19

深入理解反序列化:从JSON到对象的底层机制与Jackson实践

1. 从一次线上事故说起:反序列化不是“new 一个对象”那么简单两年前我接手过一个内部订单系统的维护,系统本身不大,但有一个接口隔三差五地报错。报错信息长这样:com.fasterxml.jackson.databind.exc.InvalidDefinitionException…

2026/10/14 6:16:18

软件配置管理实战:从版本混乱到基线可控,保障发布可靠

你有没有经历过这样的项目:白天一切正常,夜里一上线就崩,查了一整晚,最后发现只是某个配置文件被改来改去,谁都不知道哪个才是该上线的版本。如果有,那说明你们缺的不是代码质量门禁,而是软件配…

2026/10/13 5:19:27

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/13 17:09:18

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/14 2:32:55

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/14 0:00:33

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:33

macOS/iOS高精度计时:mach_absolute_time原理与实战

1. 项目概述:为什么mach_absolute_time是 macOS/iOS 时间测量的“黄金标准”在 macOS 和 iOS 开发中,我见过太多人用CFAbsoluteTimeGetCurrent()或NSDate.timeIntervalSinceReferenceDate做性能打点,结果在高精度场景下被系统时钟跳变、NTP 同…

2026/10/14 0:00:33

SCORM课件演示与测试全解析:从API通信到自动化验证

简介:这是一套遵循SCORM标准的交互式课件演示与测试资源,面向E-Learning课程开发者、LMS平台测试人员及在线教学从业者,用于验证课件在不同学习管理系统中的识别、传递与跟踪能力。压缩包共28个文件,约12.07MB,以swf动…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑