1 简介
任意块写保护(Individual Block Locks)简称IBL,可以实现flash 64KiB对齐单块写保护,其中首尾两个块可以做到4KiB对齐,使用起来更加灵活。
Flash 使用 IBL 保护方案,需要SR3 WPS=1 ,Flash 上电或复位时,整片 Flash 默认全片写保护;系统启动时需要解锁允许读写的分区,未解锁区域继续保持保护。被保护区域执行 Page Program, Erase时,flash会自动忽略这些指令。
2 使用前提
内核启用了 Ingenic SFC v2 NOR 驱动。
Flash 型号的 JEDEC ID 已加入驱动参数表。
Flash 支持以下命令:
0x36 Individual Block Lock 0x39 Individual Block Unlock 0x3d Read Block Lock Status 0x7e Global Block Lock 0x98 Global Block Unlock
Flash 的 WPS 位已按芯片手册要求打开。
Flash 的 WP# 硬件保护脚没有被拉低。
当前没有其它程序同时执行升级、写入或擦除
3 工具语法
./sfc_ioctl [-D device] [arguments]
地址、长度和寄存器值均使用十六进制,可以带或不带 `0x` 前缀。
3.1 读取状态寄存器
./sfc_ioctl -D /dev/ingenic_sfc0 read sr
示例输出:
sr1 = 0x00, sr2 = 0x00, sr3 = 0x00
3.2 配置 WPS
驱动默认SR3 bit2 作为 WPS 位,有些厂商配置特殊,需要根据厂商手册确认。应先读取原值,再只置位 bit2,
例如原值为:sr3 = 0x00,直接写0x04,置位WPS就开启IBL了。
./sfc_ioctl -D /dev/ingenic_sfc0 write sr3 0x04
3.3 锁定指定区域
例如锁定从 0x100000开始的 64 KiB:
./sfc_ioctl -D /dev/ingenic_sfc0 lock 0x100000 0x10000
保护范围为:[0x100000, 0x110000)
3.4 查询保护状态
./sfc_ioctl -D /dev/ingenic_sfc0 read lock_status 0x100000
通常返回值含义为:
1:已保护 0:未保护
3.5 解除指定区域保护
./sfc_ioctl -D /dev/ingenic_sfc0 unlock 0x100000 0x10000
解除后再次查询:
./sfc_ioctl -D /dev/ingenic_sfc0 read lock_status 0x100000
3.6 整片锁定或解锁
当len等于 Flash 总容量时,驱动会使用 Global Lock/Unlock。以 16 MiB Flash 为例:
# 整片锁定 ./sfc_ioctl -D /dev/ingenic_sfc0 lock 0x0 0x1000000 # 整片解锁 ./sfc_ioctl -D /dev/ingenic_sfc0 unlock 0x0 0x1000000
4 注意事项
SR2 WPS bit是Volatile/Non-Volatile Writable,掉电不丢失,当flash上电时WPS=1,就会默认开启全片写保护,需要在读写flash之前就把对应的区域解保护了,针对直接挂载可读写的文件系统分区时,驱动中有预留ingenic_sfc_nor_lock函数,可以在sfc驱动probe完成时调用解除相应区域的写保护,多个分区地址不连续的时候,可以调用多次
地址和长度限 64 KiB 对齐,同时要保证addr + len <= Flash 总容量,不要传入 `len=0`、超出 Flash 容量的范围,或可能导致地址加法溢出的超大数值。
# 正确示例 addr = 0x000000, len = 0x10000 addr = 0x200000, len = 0x20000
# 错误示例 addr = 0x1234, len = 0x10000 addr = 0x100000, len = 0x3000
5 常见问题
5.1 lock 返回失败
重点检查:
地址是否 64 KiB 对齐;
长度是否 64 KiB 对齐;
地址范围是否超过 Flash 容量;
Flash 是否支持 Individual Block Lock;
JEDEC ID 是否已加入驱动参数表;
WPS 是否已经打开;
WP# 是否处于硬件保护状态。
5.2 命令成功,但仍然可以写入
不要只看 ioctl 返回值,应同时执行:
./sfc_ioctl -D /dev/ingenic_sfc0 read lock_status
并实际执行一次写入或擦除测试。如果状态没有变化,通常是 WPS、Flash 命令集或状态寄存器定义不匹配。
5.3 写状态寄存器失败
可能原因包括:
WP# 引脚被拉低;
flash状态寄存器写保护了;
Flash 仍处于 Busy 状态;
芯片的状态寄存器写法与当前驱动不一致。
6 flash IBL区域分布图
