Skip to content

Instantly share code, notes, and snippets.

@llccd
Created July 22, 2023 07:48
Show Gist options
  • Save llccd/86a225f57700cd54d4d1676bd29eed5a to your computer and use it in GitHub Desktop.
Save llccd/86a225f57700cd54d4d1676bd29eed5a to your computer and use it in GitHub Desktop.
BCH ECC decoder for Qualcomm NAND controller
#!/usr/bin/env python3
# BCH ECC decoder for Qualcomm NAND controller
# This script assumes no bad block on flash
# Ref:
# https://elixir.bootlin.com/linux/latest/source/drivers/mtd/nand/raw/qcom_nandc.c
# https://github.com/ecsv/qcom-nandc-pagify
import bchlib
# 128MiB Flash, Page Size:2048+128
page_size = 2048
oob_size = 128
page_count = 128 * 1024 * 1024 // page_size
# 8-Bit BCH, 8x bus: 13 bytes ECC
bbm_size = 1
ecc_bits = 8
chunk_count = page_size // 512
chunk_size = 532 if ecc_bits == 8 else 528
data_size = 516
data1_size = page_size - (chunk_count - 1) * chunk_size
data2_size = data_size - data1_size
bch = bchlib.BCH(8219, ecc_bits)
f = open('nand-dump.bin', 'rb')
fo = open('decoded.bin', 'wb')
for page in range(page_count):
for chunk in range(chunk_count):
data = bytearray(f.read(data1_size))
f.read(bbm_size)
data += f.read(data2_size)
ecc = bytearray(f.read(bch.ecc_bytes))
bit_flip = bch.decode_inplace(data, ecc)
if (bit_flip > 0):
print('ecc corrected ' + bit_flip + 'bits on page ' + page + ' chunk ' + chunk)
elif (bit_flip < 0):
print('uncorrectable ecc at page ' + page + ' chunk ' + chunk)
if (chunk == chunk_count - 1):
fo.write(data[:-4 * chunk_count])
else:
fo.write(data)
f.read(chunk_size - data_size - bbm_size - bch.ecc_bytes)
f.read(page_size + oob_size - chunk_size * chunk_count)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment