Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 40 additions & 82 deletions dumpflash/ecc.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def calc(self, body):
p4 = 0
p4_ = 0
for i in range(0, len(body), 1):
ch = ord(body[i])
ch = body[i]
bit0 = ch & 0x1
bit1 = (ch >> 1) & 0x1
bit2 = (ch >> 2) & 0x1
Expand Down Expand Up @@ -115,90 +115,48 @@ def calc(self, body):

def calc2(self, body):
par = 0
rp0 = 0
rp1 = 0
rp2 = 0
rp3 = 0
rp4 = 0
rp5 = 0
rp6 = 0
rp7 = 0
rp8 = 0
rp9 = 0
rp10 = 0
rp11 = 0
rp12 = 0
rp13 = 0
rp14 = 0
rp15 = 0
rp = [0] * 18

for i in range(0, len(body), 1):
cur = ord(body[i])
cur = body[i]
par ^= cur

if i & 0x01:
rp1 ^= cur
else:
rp0 ^= cur
if i & 0x02:
rp3 ^= cur
else:
rp2 ^= cur
if i & 0x04:
rp5 ^= cur
else:
rp4 ^= cur
if i & 0x08:
rp7 ^= cur
else:
rp6 ^= cur
if i & 0x10:
rp9 ^= cur
else:
rp8 ^= cur
if i & 0x20:
rp11 ^= cur
else:
rp10 ^= cur
if i & 0x40:
rp13 ^= cur
else:
rp12 ^= cur
if i & 0x80:
rp15 ^= cur
else:
rp14 ^= cur

code0 = \
(self.Parity[rp7] << 7)| \
(self.Parity[rp6] << 6)| \
(self.Parity[rp5] << 5)| \
(self.Parity[rp4] << 4)| \
(self.Parity[rp3] << 3)| \
(self.Parity[rp2] << 2)| \
(self.Parity[rp1] << 1)| \
(self.Parity[rp0] << 0)

code1 = \
(self.Parity[rp15] << 7)| \
(self.Parity[rp14] << 6)| \
(self.Parity[rp13] << 5)| \
(self.Parity[rp12] << 4)| \
(self.Parity[rp11] << 3)| \
(self.Parity[rp10] << 2)| \
(self.Parity[rp9] << 1)| \
(self.Parity[rp8] << 0)

code2 = \
(self.Parity[par & 0xf0] << 7) | \
(self.Parity[par & 0x0f] << 6) | \
(self.Parity[par & 0xcc] << 5) | \
(self.Parity[par & 0x33] << 4) | \
(self.Parity[par & 0xaa] << 3) | \
(self.Parity[par & 0x55] << 2)

code0 = ~code0
code1 = ~code1
code2 = ~code2
# compute the row parities by testing
# the r^th bit of the address i
for r in range(0,9):
if (i >> r) & 1:
rp[2*r + 1] ^= cur
else:
rp[2*r + 0] ^= cur

code0 = 0
code1 = 0

for i in range(0,8):
code0 |= self.Parity[rp[i+0]] << i
code1 |= self.Parity[rp[i+8]] << i

# column parities
cp5 = par & 0b11110000
cp4 = par & 0b00001111
cp3 = par & 0b11001100
cp2 = par & 0b00110011
cp1 = par & 0b10101010
cp0 = par & 0b01010101

# 512-byte blocks squeeze the extra row parities into code2
code2 = 0 \
| (self.Parity[cp5] << 7) \
| (self.Parity[cp4] << 6) \
| (self.Parity[cp3] << 5) \
| (self.Parity[cp2] << 4) \
| (self.Parity[cp1] << 3) \
| (self.Parity[cp0] << 2) \
| (self.Parity[rp[17]] << 1) \
| (self.Parity[rp[16]] << 0)

code0 ^= 0xFF
code1 ^= 0xFF
code2 ^= 0xFF

return (code0, code1, code2)
126 changes: 99 additions & 27 deletions dumpflash/flashimage.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,89 @@ def set_use_ansi(self, use_ansi):
self.UseAnsi = use_ansi
self.SrcImage.set_use_ansi(use_ansi)

def bitcount(self, x):
count = 0
while x != 0:
count += x & 1
x >>= 1
return count

def check_ecc_page_512(self, page, subpage, body, oob_ecc0, oob_ecc1, oob_ecc2):
if (oob_ecc0 == 0xff and oob_ecc1 == 0xff and oob_ecc2 == 0xff) \
or (oob_ecc0 == 0x00 and oob_ecc1 == 0x00 and oob_ecc2 == 0x00):
return True

(ecc0, ecc1, ecc2) = ecc.Calculator().calc2(body)

ecc0_xor = ecc0 ^ oob_ecc0
ecc1_xor = ecc1 ^ oob_ecc1
ecc2_xor = ecc2 ^ oob_ecc2

if ecc0_xor == 0 and ecc1_xor == 0 and ecc2_xor == 0:
return True

bits = self.bitcount(ecc0_xor) + self.bitcount(ecc1_xor) + self.bitcount(ecc2_xor)
bad_byte = -1
bad_bit = 0
corrected = "Error"

if bits == 12:
# column parity bits 5, 3, and 1 determine which bit is bad
cp5 = (ecc2_xor >> 7) & 1
cp3 = (ecc2_xor >> 5) & 1
cp1 = (ecc2_xor >> 3) & 1
bad_bit = 0 \
| cp5 << 2 \
| cp3 << 1 \
| cp1 << 0

# row parities bits 17, 15, 13, ... 1 determine which byte is bad
rp17 = (ecc2_xor >> 1) & 1
rp15 = (ecc1_xor >> 7) & 1
rp13 = (ecc1_xor >> 5) & 1
rp11 = (ecc1_xor >> 3) & 1
rp9 = (ecc1_xor >> 1) & 1
rp7 = (ecc0_xor >> 7) & 1
rp5 = (ecc0_xor >> 5) & 1
rp3 = (ecc0_xor >> 3) & 1
rp1 = (ecc0_xor >> 1) & 1
bad_byte = 0 \
| rp17 << 8 \
| rp15 << 7 \
| rp13 << 6 \
| rp11 << 5 \
| rp9 << 4 \
| rp7 << 3 \
| rp5 << 2 \
| rp3 << 1 \
| rp1 << 0

# try flipping that bit and re-computing
new_body = bytearray(body)
new_body[bad_byte] ^= 1 << bad_bit
(ecc0_new, ecc1_new, ecc2_new) = ecc.Calculator().calc2(new_body)

ecc0_xor2 = ecc0_new ^ oob_ecc0
ecc1_xor2 = ecc1_new ^ oob_ecc1
ecc2_xor2 = ecc2_new ^ oob_ecc2

if ecc0_xor2 == 0 and ecc1_xor2 == 0 and ecc2_xor2 == 0:
corrected = "Corrected"

# page_in_block = page%self.SrcImage.PagePerBlock

offset = self.SrcImage.get_page_offset(page)
block = page/self.SrcImage.PagePerBlock

#print('ECC Error (Block: %3d Page: %3d Data Offset: 0x%x OOB Offset: 0x%x)' % (block, page, offset, offset+self.SrcImage.PageSize))
print('ECC %s (Block: %3d Page: %3d.%d Data Offset: 0x%x)' % (corrected, block, page, subpage, offset))
print(' OOB: 0x%.2x 0x%.2x 0x%.2x' % (oob_ecc0, oob_ecc1, oob_ecc2))
print(' Calc: 0x%.2x 0x%.2x 0x%.2x' % (ecc0, ecc1, ecc2))
print(' XOR: 0x%.2x 0x%.2x 0x%.2x bitcount %d byte %x.%d' % (ecc0_xor, ecc1_xor, ecc2_xor, bits, bad_byte, bad_bit))
print('')

return False

def check_ecc(self, start_page = 0, end_page = -1):
block = 0
count = 0
Expand All @@ -43,7 +126,6 @@ def check_ecc(self, start_page = 0, end_page = -1):
if end_page%self.SrcImage.PagePerBlock > 0:
end_block += 1

ecc_calculator = ecc.Calculator()
start = time.time()
for page in range(0, self.SrcImage.PageCount, 1):
block = page/self.SrcImage.PagePerBlock
Expand All @@ -69,32 +151,22 @@ def check_ecc(self, start_page = 0, end_page = -1):
break

count += 1
body = data[0:self.SrcImage.PageSize]
oob_ecc0 = ord(data[self.SrcImage.PageSize])
oob_ecc1 = ord(data[self.SrcImage.PageSize+1])
oob_ecc2 = ord(data[self.SrcImage.PageSize+2])

if (oob_ecc0 == 0xff and oob_ecc1 == 0xff and oob_ecc2 == 0xff) or (oob_ecc0 == 0x00 and oob_ecc1 == 0x00 and oob_ecc2 == 0x00):
continue

(ecc0, ecc1, ecc2) = ecc_calculator.calc(body)

ecc0_xor = ecc0 ^ oob_ecc0
ecc1_xor = ecc1 ^ oob_ecc1
ecc2_xor = ecc2 ^ oob_ecc2

if ecc0_xor != 0 or ecc1_xor != 0 or ecc2_xor != 0:
error_count += 1

# page_in_block = page%self.SrcImage.PagePerBlock

offset = self.SrcImage.get_page_offset(page)
print('ECC Error (Block: %3d Page: %3d Data Offset: 0x%x OOB Offset: 0x%x)' % (block, page, offset, offset+self.SrcImage.PageSize))
print(' OOB: 0x%.2x 0x%.2x 0x%.2x' % (oob_ecc0, oob_ecc1, oob_ecc2))
print(' Calc: 0x%.2x 0x%.2x 0x%.2x' % (ecc0, ecc1, ecc2))
print(' XOR: 0x%.2x 0x%.2x 0x%.2x' % (ecc0 ^ oob_ecc0, ecc1 ^ oob_ecc1, ecc2 ^ oob_ecc2))
print('')

#body = data[0:self.SrcImage.PageSize]

if self.SrcImage.PageSize == 512:
if not self.check_ecc_page_512(page, 0, data[0:512], data[512+0], data[512+1], data[512+2]):
error_count += 1
elif self.SrcImage.PageSize == 2048:
# four 512 byte sub pages
for i in range(0,3):
if not self.check_ecc_page_512(
page, i,
data[i*512:i*512 + 512],
data[2048 + i*16 + 8],
data[2048 + i*16 + 9],
data[2048 + i*16 + 10],
):
error_count += 1
print('Checked %d ECC record and found %d errors' % (count, error_count))

def check_bad_block_page(self, oob):
Expand Down