rflasher
一个用于读取、写入和擦除 SPI 闪存芯片的现代 Rust 实现。这是 flashprog 的一个松散移植版本。
⚠️ ALPHA 软件警告
rflasher 目前处于 alpha 阶段,不应在生产环境中依赖使用。对于关键的闪存编程任务,请使用原始的 flashprog。该项目正在积极开发中,可能包含可能损坏您的硬件或数据的错误。
特性
- 现代 Rust 架构:通过工作区组织实现关注点的清晰分离
- 双模式支持:从单一代码库支持同步 CLI 和异步 WASM/浏览器
- Web 界面:使用 egui 和 WebSerial API 的基于浏览器的 UI,用于直接在 Chrome/Edge 中编程闪存芯片
no_std兼容核心:核心闪存和选定的内部控制器逻辑可在固件/嵌入式环境中复用。- 基于 RON 的芯片数据库:具有构建时代码生成的人类可读芯片定义
- 基于 Trait 的编程器抽象:用于添加新编程器的可扩展设计
- 布局支持:Intel Flash Descriptor (IFD) 和 FMAP 解析,用于基于区域的操作
- 进度报告:使用
indicatif为所有操作提供实时进度条 - 安全特性:写保护检测、验证和基于区域的访问控制
- 实验性 REPL:基于 Steel Scheme 的 REPL,用于脚本化原始 SPI 命令(需要
--features repl)
支持的编程器
目前,rflasher 支持以下编程器:
基于 SPI 的编程器
- CH341A - USB SPI 编程器 (VID: 0x1A86, PID: 0x5512)
- CH347 - USB SPI 编程器 (VID: 0x1A86, PID: 0x55DB/0x55DE)
- Dediprog - 专业 USB SPI 编程器 (SF100, SF200, SF600, SF600PG2, SF700)
- Serprog - Serial Flasher Protocol (串口和 TCP/IP)
- FTDI - 基于 MPSSE 的编程器 (FT2232H, FT4232H, FT232H 及兼容设备)
- FT4222H - FTDI FT4222H USB 转 SPI 桥接器 (VID: 0x0403, PID: 0x601C)
- Raiden - Chrome OS 调试硬件 (SuzyQable, Servo V4, C2D2, uServo, Servo Micro)
- Internal - 内置芯片组 SPI 控制器 (Intel ICH7-500 Series, AMD FCH 790b)
- Linux SPI - 原生 Linux spidev 接口 (
/dev/spidevX.Y) - Linux GPIO - 通过 Linux 字符设备实现的 GPIO 位操作 SPI (
/dev/gpiochipN) - Dummy - 用于测试的内存闪存模拟器
不透明编程器
- Linux MTD - Linux 内存技术设备接口 (
/dev/mtdN),用于 NOR 闪存
支持的闪存芯片
目前包含来自以下厂商的 482 款闪存芯片:
- AMIC - A25L 和 A25LQ 系列(21 款芯片)
- Atmel - AT25DF 和 AT26DF 系列(31 款芯片)
- Boya - BY25Q 系列(10 款芯片)
- Eon - EN25F、EN25Q、EN25QH、EN25B、EN25P 和 EN25S 系列(47 款芯片)
- ESI - ES25P 系列(3 款芯片)
- ESMT - F25L 系列(7 款芯片)
- Fudan - FM25F 和 FM25Q 系列(12 款芯片)
- GigaDevice - GD25Q、GD25LQ、GD25WQ、GD25VQ、GD25B、GD25LB、GD25LE 和 GD25LR 系列(61 款芯片)
- Intel - 25F 系列(6 款芯片)
- ISSI - IS25LP 和 IS25WP 系列(10 款芯片)
- Macronix - MX25L、MX25U、MX25R 和 MX66 系列(53 款芯片)
- Micron/Numonyx - N25Q、MT25Q、MT25QL、MT25QU 和 M25P 系列(55 款芯片)
- Nantronics - N25S 系列(5 款芯片)
- PMC - Pm25L 系列(17 款芯片)
- Puya - P25Q 和 PY25Q/PY25F/PY25R 系列(30 款芯片)
- Sanyo - LE25FU 和 LE25FW 系列(12 款芯片)
- Spansion - S25FL 系列(27 款芯片)
- SST - SST25VF、SST25LF、SST25WF 和 SST26VF 系列(34 款芯片)
- Winbond - W25Q、W25X、W25P 和 W25R 系列(54 款芯片)
- XMC - XM25QH 和 XM25QU 系列(6 款芯片)
- XTX - XT25F 系列(11 款芯片)
- Zetta - ZD25D 和 ZD25LQ 系列(4 款芯片)
芯片定义以 RON 文件的形式存储在 crates/rflasher-chips/data/vendors/ 中,并且可以轻松扩展。有关示例,请参阅 芯片数据库结构。
安装
从源码构建
# Clone the repository
git clone https://github.com/user/rflasher
cd rflasher
# Build with default features (most common programmers)
cargo build --release
# Build with all programmers (includes FTDI, requires libftdi1-dev)
cargo build --release --features all-programmers
# Build with specific programmers only
cargo build --release --no-default-features --features ch341a,serprog
# Install to ~/.cargo/bin
cargo install --path .
系统要求
- Rust 工具链 1.70 或更高版本
- libftdi1(可选,用于 FTDI 编程器支持)
- Debian/Ubuntu:
sudo apt install libftdi1-dev - Fedora:
sudo dnf install libftdi-devel - Arch:
sudo pacman -S libftdi
- Debian/Ubuntu:
芯片数据库
闪存芯片数据库被打包到启用 static-chips 的构建中。CLI 还可以在运行时从以下默认搜索路径加载 RON 文件:
./crates/rflasher-chips/data/vendors/(仓库开发)./chips/vendors/(兼容的本地覆盖)/usr/share/rflasher/chips/(系统范围安装)/usr/local/share/rflasher/chips/(本地安装)
你还可以使用 --chip-db <path> 指定自定义路径。
USB 设备权限
对于 WebUSB 编程器,你可能需要设置 udev 规则。这包括 CH341A、CH347、FTDI、Dediprog 以及 Raiden Debug SPI / Cr50 设备。
# Copy udev rules (create this file based on your needs)
sudo cp 50-rflasher.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger
示例 udev 规则:
# CH341A USB programmer
SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="5512", MODE="0666"
# Raiden Debug SPI / Cr50 (Google debug hardware, VID:18d1; product ID varies)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0666"
手册页
man/ 目录中提供有手册页。要在本地查看:
man -l man/rflasher.1
要安装到系统范围:
sudo cp man/rflasher.1 /usr/local/share/man/man1/
sudo mandb
手册页是使用 clap_mangen 从 CLI 定义中自动生成的。要重新生成它:
cargo run --bin gen-manpage
快速入门
# List available programmers
rflasher list-programmers
# List supported chips
rflasher list-chips
# Probe for a flash chip using CH341A
rflasher probe -p ch341a
# Show detailed chip information
rflasher info -p ch341a
# Read flash to a file
rflasher read -p ch341a -o flash_backup.bin
# Write a file to flash (with automatic erase and verify)
rflasher write -p ch341a -i firmware.bin
# Erase entire chip
rflasher erase -p ch341a
使用示例
基本操作
# Read entire flash chip
rflasher read -p ch341a -o backup.bin
# Write and verify (default behavior)
rflasher write -p ch341a -i firmware.bin
# Write without verification (faster, but risky)
rflasher write -p ch341a -i firmware.bin --verify=false
# Verify flash contents against a file
rflasher verify -p ch341a -i firmware.bin
# Erase specific region (64 KiB starting at 0x10000)
rflasher erase -p ch341a --start 0x10000 --length 0x10000
程序员专用选项
# CH341A (USB)
rflasher probe -p ch341a
# Serprog via serial port
rflasher probe -p serprog:dev=/dev/ttyUSB0
# Serprog via serial with custom baud rate
rflasher probe -p serprog:dev=/dev/ttyUSB0:115200
# Serprog via TCP (e.g., ESP8266-based programmer)
rflasher probe -p serprog:ip=192.168.1.100:5000
# Dediprog SF600 with 12MHz SPI speed
rflasher probe -p dediprog:spispeed=12M
# Raiden Debug SPI (Chrome OS debug hardware)
rflasher probe -p raiden
# Internal chipset programmer (Intel/AMD; Linux userspace only)
rflasher probe -p internal
# FTDI with specific device type
rflasher probe -p ftdi:type=2232h
# FTDI on channel B with slower clock
rflasher probe -p ftdi:type=2232h,port=B,divisor=10
# FT4222H with custom speed and chip select
rflasher probe -p ft4222:spispeed=20000,cs=0
# Linux SPI with custom speed
rflasher probe -p linux_spi:dev=/dev/spidev0.0,spispeed=4000
# Linux GPIO bitbang SPI (e.g., Raspberry Pi)
rflasher probe -p linux_gpio_spi:gpiochip=0,cs=25,sck=11,mosi=10,miso=9
# Linux GPIO with custom speed
rflasher read -p linux_gpio_spi:dev=/dev/gpiochip0,cs=25,sck=11,mosi=10,miso=9,spispeed=500 -o flash.bin
# Linux MTD device
rflasher probe -p linux_mtd:dev=0
# Linux MTD - read from device 0
rflasher read -p linux_mtd:dev=0 -o flash_backup.bin
内部程序员与嵌入式复用
internal 程序员使用芯片组集成的 SPI 控制器。CLI 路径在 Linux 用户空间中可用,并使用 Linux PCI sysfs 以及 /dev/mem,因此通常需要 root 或等效的硬件访问权限。
低层 Intel ICH/PCH 和 AMD SPI100 控制器代码也针对固件复用进行了结构化设计,无需重复控制器逻辑。嵌入式调用者通过实现 rflasher_internal::HostAccess 来提供平台特定的访问层:
- 用于 PCI 配置读写的
PciConfigAccess方法。 - 用于控制器寄存器和可选闪存内存窗口的
map_mmio。 - 用于短控制器轮询延迟的
delay_us。
对于同步的 no_std 固件集成,请依赖不带默认特性的 crates:
rflasher-core = { version = "0.1", default-features = false, features = ["is_sync"] }
rflasher-internal = { version = "0.1", default-features = false, features = ["is_sync"] }
固件代码可以将自身的 PCI 扫描结果传递给 find_intel_chipset_in_devices / find_amd_chipset_in_devices,然后使用 IchSpiController::new_with_host(...) 或 AmdSpi100Info::create_controller_with_host(...) 构建控制器。
布局操作
Flash 布局允许您处理 flash 芯片的特定区域(例如,Intel 系统上的 BIOS、ME、GbE 区域)。
# Extract Intel Flash Descriptor from a flash image
rflasher layout ifd -i flash.bin -o layout.toml
# Extract FMAP from a Chromebook flash image
rflasher layout fmap -i chromebook.bin -o layout.toml
# Show layout from a file
rflasher layout show -f layout.toml
# Create a new layout template
rflasher layout create -o custom.toml --size "16 MiB"
# Read only the BIOS region (using IFD from chip)
rflasher read -p ch341a --ifd --region bios -o bios.bin
# Write to a specific region from a layout file
rflasher write -p ch341a --layout layout.toml --region bios -i bios_update.bin
# Erase multiple regions
rflasher erase -p ch341a --ifd --include bios,descriptor
写保护操作
rflasher 支持读取和修改闪存芯片的写保护设置:
# Show current write protection status
rflasher wp status -p ch341a
# List all available protection ranges for the chip
rflasher wp list -p ch341a
# Enable hardware write protection (WP# pin controlled)
rflasher wp enable -p ch341a
# Disable write protection
rflasher wp disable -p ch341a
# Set protection for a specific address range (start,length)
rflasher wp range -p ch341a 0,0x100000
# Set protection for a named region (requires layout)
rflasher wp region -p ch341a --ifd bios
# Make changes temporary (volatile, lost on power cycle)
rflasher wp enable -p ch341a --temporary
详细程度与调试
# Increase verbosity (shows debug messages)
rflasher -v probe -p ch341a
# Maximum verbosity (shows trace-level messages)
rflasher -vv read -p ch341a -o flash.bin
实验性:Scheme REPL
注意:REPL 是一项实验性功能,需要使用
--features repl进行构建。
rflasher 包含一个基于 Steel Scheme 的 REPL,用于编写原始 SPI 命令脚本。这对于需要执行自定义 SPI 序列、实验闪存命令或自动化测试的高级用户非常有用。
# Build with REPL support
cargo build --release --features repl
# Start REPL with serprog programmer
rflasher repl -p serprog:dev=/dev/ttyACM0
# Start REPL with CH341A
rflasher repl -p ch341a
示例 REPL 会话:
__ _ _
_ _ / _| |__ _ _____| |_ ___ _ _
| '_| _| / _` (_-< ' \/ -_) '_| Version 0.1.0
|_| |_| |_\__,_/__/_||_\___|_| :? for help
Type (rflasher-help) for available commands, (quit) or (exit) to exit.
λ > (read-jedec-id)
=> (239 16389)
λ > (read-status1)
=> 0
λ > (spi-read READ 0 16)
=> (255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255)
λ > (bytes->hex (spi-read READ 0 32))
=> "ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff"
λ > (define data (make-bytes 256 #xAA))
λ > (write-enable)
=> #t
λ > (spi-write PP #x1000 data)
=> #t
λ > (wait-ready)
=> #t
λ > (quit)
Goodbye!
可用函数包括:
- SPI 操作:
spi-transfer,spi-read,spi-write,read-jedec-id,read-status1/2/3,write-enable,write-disable,is-busy?,wait-ready - 擦除操作:
chip-erase,sector-erase,block-erase-32k,block-erase-64k - 字节工具:
make-bytes,bytes-length,bytes-ref,bytes-set!,bytes->list,list->bytes,bytes->hex,hex->bytes,bytes-slice - SPI25 常量:
WREN,WRDI,RDSR,WRSR,READ,FAST_READ,PP,SE,BE_32K,BE_64K,CE,RDID等。
在 REPL 中输入 (rflasher-help) 以查看完整的命令列表。
Web 界面 (WASM)
rflasher 包含一个基于浏览器的 Web 界面,允许您使用 WebSerial API 直接从 Web 浏览器对闪存芯片进行编程。这在安装原生软件困难或需要便携式、跨平台解决方案的场景中非常有用。

功能特性
- 基于浏览器的 UI:完全在浏览器中运行的现代 egui 界面
- WebSerial 支持:通过 USB 串口连接 serprog 编程器
- 完整的 Flash 操作:读取、写入、擦除、验证和探测 Flash 芯片
- 进度报告:所有操作的实时进度更新
- 文件处理:直接在浏览器中加载固件文件和保存 Flash 转储
- 无需安装:直接在兼容的 Web 浏览器中运行
浏览器要求
Web 界面需要支持 WebSerial API 的浏览器:
- Chrome/Edge:版本 89+(完全支持)
- Opera:版本 75+(完全支持)
- Firefox:尚不支持(WebSerial 处于实验标志后)
- Safari:尚不支持
注意:WebSerial 仍然是一个实验性 API。请确保您的浏览器具有访问串口所需的权限。
构建 Web 界面
Web 界面使用 Trunk 构建,这是一个 WASM Web 应用程序打包器。
# Install trunk (if not already installed)
cargo install trunk
# Add the wasm32 target
rustup target add wasm32-unknown-unknown
# Build the web interface
cd crates/rflasher-wasm
trunk build --release
# The output will be in the dist/ directory
用于开发并支持自动重载:
cd crates/rflasher-wasm
trunk serve
# Open http://localhost:8080 in your browser
本地运行
构建完成后,你可以在本地提供 Web 界面:
# Using Python's built-in HTTP server
cd crates/rflasher-wasm/dist
python3 -m http.server 8080
# Using any other static file server
# cd crates/rflasher-wasm/dist
# npx serve
然后在兼容的浏览器中打开 http://localhost:8080。
部署到生产环境
要将 Web 界面部署到 Web 服务器:
-
构建发布版本:
cd crates/rflasher-wasm trunk build --release -
将
crates/rflasher-wasm/dist/的内容复制到您的 Web 服务器:rsync -av dist/ user@yourserver:/var/www/html/rflasher/ -
确保你的 Web 服务器已配置为:
- 将
index.html文件作为默认页面提供 - 为
.wasm文件设置适当的 MIME 类型 - 使用 HTTPS(WebSerial API 必需)
- 将
重要:WebSerial API 需要安全上下文(HTTPS)。在 localhost 上进行本地开发可以正常工作,但生产环境部署必须使用 HTTPS。
使用 Web 界面
- 在浏览器中打开 Web 界面
- 点击 "Connect" 从串口列表中选择你的 serprog 编程器
- 连接后,使用 Probe 按钮检测闪存芯片
- 选择一项操作:
- Read:下载当前闪存内容
- Write:上传并将固件文件写入闪存
- Erase:擦除整个闪存芯片
- Verify:根据文件验证闪存内容
- 在状态面板中监控进度
Nix 开发环境
如果你使用的是提供的 Nix flake,开发环境包含所有必要的工具:
# Enter the Nix development shell
nix develop
# The wasm32 target and trunk are already available
cd crates/rflasher-wasm
trunk serve
故障排除
“未找到串行端口”或“不支持 WebSerial”
- 确保您使用的是兼容的浏览器(Chrome/Edge 89+)
- 检查浏览器设置中是否已启用 WebSerial
- 尝试通过
chrome://flags访问,并启用“实验性 Web 平台功能”
“打开端口失败”
- 确保没有其他应用程序正在使用该串行端口
- 检查 USB 线缆和连接
- 验证 serprog 设备是否已正确配置
读取挂起或超时
- 这是一个正在调查中的已知问题(参见 transport.rs 中的 TODO)
- 尝试使用不同的 USB 线缆或端口
- 减少一次读取的数据量
架构
rflasher 采用工作区结构,具有清晰的关注点分离:
rflasher-chip-types- 共享的no_stdSPI NOR 芯片数据模型和提供者 traitrflasher-core-no_stdSPI 协议、探测和闪存操作(通过maybe-async同时支持同步和异步)rflasher-chips- 运行时 RON 加载和可选的编译芯片数据库提供者,包含芯片类型重新导出rflasher-chips-codegen- 用于编译芯片数据库的构建时代码生成器rflasher-programmers- 特性门控的外部编程器后端,以及原生高级注册表和FlashHandlerflasher-internal- 内部芯片组 SPI 控制器支持。它保持独立,以便 CrabEFI 等固件可以配合default-features = false和is_sync使用,而不需要stdrflasher-pci- 内部编程器使用的小型no_stdPCI 配置空间抽象rflasher-repl- 用于原生应用的 Steel Scheme 脚本支持rflasher-wasm- 基于浏览器的 Web 界面,在异步模式下使用 egui、WebSerial 和 WebUSB
rflasher-programmers crate 包含 CH341A、CH347、Dediprog、serprog、FTDI、FT4222H、Raiden、sunxi FEL、Linux SPI/GPIO/MTD 以及 dummy 后端的模块。Cargo 特性选择编译哪些模块和可选依赖项。
异步/同步架构
核心库使用 maybe-async crate 从单一代码库同时支持同步(用于 CLI/原生应用)和异步(用于 WASM/浏览器应用)操作:
- 同步模式(CLI):通过
is_sync特性标志启用,编译为阻塞同步代码 - 异步模式(WASM):默认模式,使用 async/await 进行非阻塞浏览器操作
此设计允许相同的闪存操作、芯片数据库和编程器特性在原生 CLI 应用程序和基于浏览器的 WASM 环境中无缝运行,而无需代码重复。
安全警告
⚠️ 重要安全信息
如果操作不当,闪存芯片编程可能会永久损坏您的硬件:
- 电压不匹配:确保您的编程器电压与闪存芯片匹配(现代 SPI 闪存通常为 3.3V)
- 错误芯片:向错误的芯片写入数据可能导致设备变砖
- Intel ME 区域:在 Intel 系统上,损坏 Management Engine 区域可能导致主板变砖
- 写保护:在写入之前,始终检查写保护状态
- 先备份:在进行任何更改之前,始终读取并备份您的闪存芯片
本软件不提供任何保修。使用风险自负。
贡献
欢迎贡献!以下是一些您可以提供帮助的方式:
添加新的闪存芯片
闪存芯片在 crates/rflasher-chips/data/vendors/ 下的 RON 文件中定义。要添加新芯片:
- 找到您芯片的数据手册
- 创建或更新供应商文件(例如,
crates/rflasher-chips/data/vendors/winbond.ron) - 添加芯片定义,包括 JEDEC ID、大小、擦除块和功能
- 提交一个拉取请求
示例芯片定义:
(
name: "W25Q128.V",
device_id: 0x4018,
total_size: MiB(16),
features: (
wrsr_wren: true,
fast_read: true,
quad_io: true,
),
voltage: (min: 2700, max: 3600),
erase_blocks: [
(opcode: 0x20, size: KiB(4)),
(opcode: 0xD8, size: KiB(64)),
(opcode: 0xC7, size: MiB(16)),
],
tested: (probe: Ok, read: Ok, erase: Ok, write: Ok, wp: Ok),
)
添加新的编程器
要添加一个新的 SPI 编程器:
- 在
crates/rflasher-programmers/src/backends/下添加一个模块 - 实现
rflasher-core中的SpiMaster或OpaqueMastertrait - 在
crates/rflasher-programmers/Cargo.toml中添加一个 feature 和可选依赖 - 在
rflasher-programmers/src/registry.rs中注册原生同步编程器 - 酌情更新 CLI/WASM feature 转发和文档
将面向固件的 no_std 芯片组控制器代码保留在 rflasher-internal 中,而不是在那里添加主机或浏览器依赖。
TODO
以下功能计划在未来开发中实现:
- 移植更多闪存芯片 - 已从 flashprog 移植 482 个约 495 个 SPI 闪存芯片(97% 覆盖率)
- 添加更多 SPI 编程器 - 从 flashprog 移植剩余的 SPI 编程器
- Intel/AMD 内部编程器 - 支持通过芯片组 SPI 控制器进行读写
- 最优擦除算法 - 通过使用尽可能大的擦除块来最小化擦除操作
许可证
本项目采用 GNU 通用公共许可证 v2.0 或更高版本 (GPL-2.0-or-later) 授权,与 flashprog 相同。
请参阅 LICENSE 获取完整的许可证文本。
致谢
本项目是 flashprog 的松散移植,而 flashprog 本身是 flashrom 的一个分支。感谢这些项目的所有贡献者在闪存芯片支持和编程器实现方面所做的广泛工作。
相关项目
- flashprog - https://github.com/SourceArcade/flashprog - 上游 C 语言实现
- flashrom - https://www.flashrom.org/ - 原始的闪存芯片编程器
注意:rflasher 目前仅专注于 SPI 闪存芯片。并行闪存及其他协议目前不在范围内,尽管该架构支持未来针对此类设备的 OpaqueMaster 实现。