eMMC and Extended CSD Registers
The other day I needed to read of the data from the Extended CSD (aka ECSD) registers of a eMMC chip I was having a disagreement with. Linux makes this kind of easy with a kernal that has debugfs support enabled:
$ mount -t debugfs debugfs /d
$ cat /d/mmc0/mmc0:0001/ext_csd
0000000000000001030100000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000002
000000087a000000000000000006150203070010060801010108080010000072800000080808
0808080000000000010200070002000500000000000001000200000000000000000000000000
000100050000000000030001ca00000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000
Making sense of the 512 bytes string is another issue all together.
Parse Extended CSD Data with Python
$ ./parse-ext-csd.py
0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
16: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
32: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
48: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
64: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
96: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
112: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
128: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
144: 00 00 00 00 00 00 00 00 00 00 00 00 00 ca 01 00
160: 03 00 00 00 00 00 05 00 01 00 00 00 00 00 00 00
176: 00 00 00 00 00 00 00 02 00 01 00 00 00 00 00 00
192: 05 00 02 00 07 00 02 01 00 00 00 00 00 08 08 08
208: 08 08 08 00 00 80 72 00 00 10 00 08 08 01 01 01
224: 08 06 10 00 07 03 02 15 06 00 00 00 00 00 00 00
240: 00 7a 08 00 00 00 02 00 00 00 00 00 00 00 00 00
256: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
272: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
288: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
304: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
336: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
352: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
368: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
384: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
416: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
432: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
448: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
464: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
496: 00 00 00 00 00 00 01 03 01 00 00 00 00 00 00 00
SEC_BAD_BLK_MGMNT[134] = 0x0
FW_CONFIG[169] = 0x0
ERASE_GROUP_DEF[175] = 0x0
EXT_CSD_REV[192] = 0x5
CSD_STRUCTURE[194] = 0x2
CARD_TYPE[196] = 0x7
ERASE_TIMEOUT_MULT[223] = 0x1
HC_ERASE_GRP_SIZE[224] = 0x8
BOOT_INFO[228] = 0x7
SEC_TRIM_MULT[229] = 0x3
SEC_ERASE_MULT[230] = 0x2
SEC_FEATURE_SUPPORT[231] = 0x15
Python Code Snippet
Copy your ext_csd
file contents to the ecsd_str
of this script. Someday I might spend 5 minutes to make it read stdin
, until then you have to manually copy it.
#!/usr/bin/env python
"""
Author: Kyle Manna <[email protected]>
Blog: https://blog.kylemanna.com
cat /d/mmc0/mmc0:0001/ext_csd
0000000000000001030100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000087a0000000000000000061502030700100608010101080800100000728000000808080808080000000000010200070002000500000000000001000200000000000000000000000000000100050000000000030001ca00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
"""
import binascii
import re
import sys
def str2bytearray(s):
if len(s) % 2:
s = '0' + s
reorder = True
if reorder:
r = []
i = 1
while i <= len(s):
r.append(s[len(s) - i - 1])
r.append(s[len(s) - i])
i += 2
s = ''.join(r)
out = binascii.unhexlify(s)
return out
if __name__ == '__main__':
ecsd_str = '0000000000000001030100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000087a0000000000000000061502030700100608010101080800100000728000000808080808080000000000010200070002000500000000000001000200000000000000000000000000000100050000000000030001ca00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
#ecsd_str = '320100'
ecsd = str2bytearray(ecsd_str)
line_len = 16
i = 0
while i < len(ecsd):
sys.stdout.write("{0:04x}:\t".format(i))
for j in range(line_len):
if (i < len(ecsd)):
sys.stdout.write("{0:=02x}".format(ord(ecsd[i])))
i = i + 1
else:
break
if (j == (line_len - 1)): pass
elif (i % 4): sys.stdout.write(" ")
else: sys.stdout.write(" ")
sys.stdout.write("\n")
print "SLC_DEVICE_HEALTH_STATUS[87] = 0x{:x}".format(ord(ecsd[87]))
print "MLC_DEVICE_HEALTH_STATUS[94] = 0x{:x}".format(ord(ecsd[94]))
print "SEC_BAD_BLK_MGMNT[134] = 0x{:x}".format(ord(ecsd[134]))
print "FW_CONFIG[169] = 0x{:x}".format(ord(ecsd[169]))
print "ERASE_GROUP_DEF[175] = 0x{:x}".format(ord(ecsd[175]))
print "EXT_CSD_REV[192] = 0x{:x}".format(ord(ecsd[192]))
print "CSD_STRUCTURE[194] = 0x{:x}".format(ord(ecsd[194]))
print "CARD_TYPE[196] = 0x{:x}".format(ord(ecsd[196]))
print "ERASE_TIMEOUT_MULT[223] = 0x{:x}".format(ord(ecsd[223]))
print "HC_ERASE_GRP_SIZE[224] = 0x{:x}".format(ord(ecsd[224]))
print "BOOT_INFO[228] = 0x{:x}".format(ord(ecsd[228]))
print "SEC_TRIM_MULT[229] = 0x{:x}".format(ord(ecsd[229]))
print "SEC_ERASE_MULT[230] = 0x{:x}".format(ord(ecsd[230]))
print "SEC_FEATURE_SUPPORT[231] = 0x{:x}".format(ord(ecsd[231]))
The code also lives in a Github Gist.
Comments