ECC 如何与 mtd-utils 中的 nandwrite/nanddump 一起工作?

逆向工程 闪光
2021-06-18 11:01:15

我正在研究具有 TSOP48 NAND 闪存芯片的设备,SK Hynix H27U1G8F2BTR(1Gbit/128Mbyte,2048byte(+ 64byte 备用)页面,128K 块)。

我已经拆焊了芯片并将内容转储到一个文件中。该文件还包含 OOB(带外)数据,从而生成一个 138412032 字节的文件。

我使用以下方法创建了一个新的模拟 NAND MTD 设备:

modprobe nandsim first_id_byte=0xad second_id_byte=0xf1 third_id_byte=0x00 fourth_id_byte=0x1d

这会导致设备具有正确的参数:

$mtdinfo /dev/mtd0
mtd0
Name:                           NAND simulator partition 0
Type:                           nand
Eraseblock size:                131072 bytes, 128.0 KiB
Amount of eraseblocks:          1024 (134217728 bytes, 128.0 MiB)
Minimum input/output unit size: 2048 bytes
Sub-page size:                  512 bytes
OOB size:                       64 bytes
Character device major/minor:   90:0
Bad blocks are allowed:         true
Device is writable:             true

我现在可以使用 将我的图像写入 mtd nandwrite,并-o选择指示转储包含 OOB 信息:

nandwrite -o /dev/mtd0 with_oob.bin

然后我可以使用nanddump以下方法转储图像

nanddump /dev/mtd0 -f without_oob.bin

这会产生一个没有 OOB 数据的 134217728 字节的文件。这个文件是合理的(例如,包含我可以挂载的文件系统)。

有几次,在玩的时候,我在运行时看到 ECC 错误nanddump

nandsim,nandwrite和 的这种组合如何nandddump决定使用哪种 ECC 方案?flash来自TI AM335系统,据我所知,ECC方案是由处理器和操作系统的组合决定的。这些实用程序如何知道要做什么?

1个回答

首先,所使用的 ECC 方案不一定要适用于所有闪存擦除块。通常使用 3 种不同类型的闪存分区,对于每种类型,指定使用的 ECC 代码的方法不同:

  1. 由 ROM 引导代码访问的那个
  2. 引导加载程序(通常是 u-boot)访问的那些
  3. 操作系统访问的那些(假设您使用的是 Linux)

通常,特定 ECC 方法的使用受到闪存的 OOB 大小的限制。AM335x_U-Boot_User's_Guide(由于声誉原因无法在此处发布链接)在BCH Flash OOB 布局部分中对其进行了解释,并且示例与您正在使用的闪存芯片匹配。每 2k 页 64 字节有效地将可用的 ECC 算法限制为 BCH8、BCH4 或 HAMMING 代码。

BCH Flash OOB 布局

对于任何 ECC 方案,我们都需要在写入时添加一些额外的数据,以便检测和纠正(如果可能)由 NAND 部分引入的错误。在 BCH 方案的情况下,需要一些字节来存储 ECC 相关信息。

存储 ECC 数据等附加信息的 NAND 存储器部分称为带外或 OOB 部分。

前 2 个字节用于坏块标记 – 0xFFFF => 好块

接下来的“N”个字节用于 BCH 字节

N = B * 页中 512 字节的扇区数

B = BCH4 中每 512 字节扇区 8 字节 B = BCH8 中每 512 字节扇区 14 字节 B = BCH16 中每 512 字节扇区 26 字节

因此,对于 64 字节 OOB 大小的 2k 页大小的 NAND 闪存,我们将使用 BCH8。这将消耗 2 + (14*4) = 64 个可用字节中的 58 个字节。

ROM 引导代码使用的 ECC

AM335x 处理器的 ROM 引导代码根据 AM335x 技术参考手册第 26.1.7.4 章 NAND 中解释的机制决定用于 NAND 闪存的 ECC 方案

ECC 校正 应用的默认 ECC 校正是使用 GPMC 和 ELM 硬件的 BCH 8b/扇区。对于设备 ID 代码 D3h、C3h、D5h、C5h、D7h、C7h、DEh、CEh,当制造商代码(第一个 ID 字节)为 98h 时,在 ID 数据的第 4 个字节中检查单元类型信息。如果它等于 10b,则应用的 ECC 校正是 BCH 16b/扇区。此外,由 ROM 完成的 ECC 计算可以通过使用 SYSBOOT[9] 完全关闭。这在与内置 ECC 引擎的 NAND 设备接口时特别有用。

其他控制 ECC 行为的方法是 ONFI 或 I2C EEPROM,但 H27U1G8F2BTR 数据表没有提到 ONFI,所以我猜它不受闪存芯片的支持。

所以基本上 BCH8 或 BCH16 或没有 ECC 机制用于 ROM 引导加载程序从 NAND 闪存读取的前 128K。

引导加载程序使用的 ECC

引导加载程序自行决定。例如,对于 U-boot,此信息也被编译到 u-boot 和第一级引导加载程序 (SPL/MLO) 中。该信息由在编译时设置的 U-Boot 配置设置控制。最新版本的 U-boot 可以使用 nandec 命令在运行时切换 ecc。

操作系统使用的 ECC

该选择完全特定于操作系统。对于使用 AM335x 处理器的 Linux 嵌入式系统,我知道使用设备树将此信息传递到内核中。

nandsim 使用哪种 ECC 方法

有一个名为bch的参数可以传递给 nandsim 模块来选择一个 ecc 代码。从代码我猜它被初始化为零,所以它不会使用任何 ECC 代码。所以看起来nandsim可以使用BCH8和BCH16,但是模拟的整个flash只能使用一个。

modprobe nandsim bch=8 first_id_byte=0xad second_id_byte=0xf1 third_id_byte=0x00 fourth_id_byte=0x1d

nanddump/nandwrite 使用哪种 ECC 方法

同样,这取决于您用来转储闪存的操作系统/Linux。类似于 nandsim 模块,真正的 mtd 驱动程序可以指定使用的 ECC 方案(内核参数、设备树)。但是您也可以指示 nanddump 忽略 ECC 信息。

参考