Linux eMMC信息读取

某一天,领导安排一个任务,要画一份某个项目的eMMC的layout,将分区信息表示出来,哪个分区的起始地址和结束地址,占用了多大等等信息。在此,整理了相关的内容,通过这几个常用的命令可以大致了解这块eMMC的分区情况。


mount查看分区挂载情况

执行mount命令,可以查看分区挂载的情况。

1
2
3
4
5
6
7
8
@xxx:/ # mount
rootfs on / type rootfs (ro,size=1272540k,nr_inodes=318135)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
tmpfs on /dev type tmpfs (rw,relatime,mode=755)
/dev/block/mmcblk0p1 on /system type ext4 (ro,relatime,journal_checksum,data=ordered)
tmpfs on /tmp type tmpfs (rw,relatime)
/dev/block/mmcblk0p2 on /data type ext4 (rw,nosuid,nodev,noatime,nodelalloc,journal_checksum,data=ordered)

可以知道,mmcblk0p1挂载到/system分区,mmcblk0p2挂载到/data分区。


查看eMMC分区情况

/sys/class/block/ 目录下可以查看当前系统的分区情况:

1
2
3
4
5
6
7
8
9
10
11
12
total 0
lrwxrwxrwx 1 root root 0 1970-01-01 00:34 loop0 -> ../../devices/virtual/block/loop0
lrwxrwxrwx 1 root root 0 1970-01-01 00:34 loop1 -> ../../devices/virtual/block/loop1
lrwxrwxrwx 1 root root 0 1970-01-01 00:34 loop2 -> ../../devices/virtual/block/loop2
lrwxrwxrwx 1 root root 0 1970-01-01 00:34 loop3 -> ../../devices/virtual/block/loop3
lrwxrwxrwx 1 root root 0 1970-01-01 00:34 loop4 -> ../../devices/virtual/block/loop4
lrwxrwxrwx 1 root root 0 1970-01-01 00:34 mmcblk0 -> ../../devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001/block/mmcblk0
lrwxrwxrwx 1 root root 0 1970-01-01 00:34 mmcblk0boot0 -> ../../devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0boot0
lrwxrwxrwx 1 root root 0 1970-01-01 00:34 mmcblk0boot1 -> ../../devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0boot1
lrwxrwxrwx 1 root root 0 1970-01-01 00:34 mmcblk0p1 -> ../../devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p1
lrwxrwxrwx 1 root root 0 1970-01-01 00:34 mmcblk0p2 -> ../../devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p2
lrwxrwxrwx 1 root root 0 1970-01-01 00:34 mmcblk0rpmb -> ../../devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0rpmb

从上面的信息可以知道:

  • 这个eMMC上总共共有5个分区,boot0/boot1/p1/p2/rpmb分区;
  • 这个eMMC用到的控制器为6b030000.esdhc;
  • 我们可以到../../devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001/block/mmcblk0/目录下查看更具体的信息;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    @xxx:/sys/devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001/block/mmcblk0 # ll
    total 0
    -r--r--r-- 1 root root 4096 1970-01-01 00:35 alignment_offset
    -rw-r--r-- 1 root root 4096 1970-01-01 00:35 badblocks
    lrwxrwxrwx 1 root root 0 1970-01-01 00:35 bdi -> ../../../../../../../virtual/bdi/179:0
    -r--r--r-- 1 root root 4096 1970-01-01 00:35 capability
    -r--r--r-- 1 root root 4096 1970-01-01 00:35 dev
    lrwxrwxrwx 1 root root 0 1970-01-01 00:35 device -> ../../../mmc0:0001
    -r--r--r-- 1 root root 4096 1970-01-01 00:35 discard_alignment
    -r--r--r-- 1 root root 4096 1970-01-01 00:35 ext_range
    -rw-r--r-- 1 root root 4096 1970-01-01 00:35 force_ro
    drwxr-xr-x 2 root root 0 1970-01-01 00:00 holders
    -r--r--r-- 1 root root 4096 1970-01-01 00:35 inflight
    drwxr-xr-x 2 root root 0 1970-01-01 00:00 integrity
    drwxr-xr-x 7 root root 0 1970-01-01 00:00 mmcblk0boot0
    drwxr-xr-x 7 root root 0 1970-01-01 00:00 mmcblk0boot1
    drwxr-xr-x 4 root root 0 1970-01-01 00:00 mmcblk0p1
    drwxr-xr-x 4 root root 0 1970-01-01 00:00 mmcblk0p2
    drwxr-xr-x 7 root root 0 1970-01-01 00:00 mmcblk0rpmb
    drwxr-xr-x 2 root root 0 1970-01-01 00:00 power
    drwxr-xr-x 3 root root 0 1970-01-01 00:00 queue
    -r--r--r-- 1 root root 4096 1970-01-01 00:35 range
    -r--r--r-- 1 root root 4096 1970-01-01 00:35 removable
    -r--r--r-- 1 root root 4096 1970-01-01 00:35 ro
    -r--r--r-- 1 root root 4096 1970-01-01 00:35 size
    drwxr-xr-x 2 root root 0 1970-01-01 00:00 slaves
    -r--r--r-- 1 root root 4096 1970-01-01 00:35 stat
    lrwxrwxrwx 1 root root 0 1970-01-01 00:35 subsystem -> ../../../../../../../../class/block
    -rw-r--r-- 1 root root 4096 1970-01-01 00:00 uevent
    @xxx:/sys/devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001/block/mmcblk0 #

关于这些参数的意义,可以参照:
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block
https://www.kernel.org/doc/Documentation/block/stat.txt


查看各个分区的大小

/sys/devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001/block/目录下,有几个以mmcblk0开头的目录名,这里面包含了分区的起始和结束的block地址。比如说,mmcblk0p2挂载出来的/data分区。

  • 获取分区的大小:
    1
    2
    # cat mmcblk0p2/size
    524288

读取到分区的size为524288 block大小,1个block为512字节,那么这个/data分区的大小为:524288 block * 512Bytes/block = 268435456Bytes = 256MB

  • 获取到分区的起始地址:
    1
    2
    # cat mmcblk0p2/start
    1423360

读取eMMC控制器的相关寄存器

eMMC控制器厂商会提供一个寄存器概要信息,比如说美光家的eMMC的spec,详见:http://www.chinaflashmarket.com/Uploads/file/2015/12/25/Micron_emmc_v50.pdf
如果想要更进一步了解每个寄存器各个bit的详细信息,需要参考JEDEC提供的JESD84-B50-1文档。

/sys/devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001/目录下可以读取到cidcsddsrocr、寄存器的值,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@xxx:/sys/devices/platform/6b030000.esdhc/mmc_host/mmc0/mmc0:0001 # ll
total 0
drwxr-xr-x 3 root root 0 1970-01-01 00:00 block
-r--r--r-- 1 root root 4096 1970-01-01 01:49 cid
-r--r--r-- 1 root root 4096 1970-01-01 01:49 cmdq_en
-r--r--r-- 1 root root 4096 1970-01-01 01:49 csd
-r--r--r-- 1 root root 4096 1970-01-01 01:49 date
lrwxrwxrwx 1 root root 0 1970-01-01 01:49 driver -> ../../../../../../bus/mmc/drivers/mmcblk
-r--r--r-- 1 root root 4096 1970-01-01 01:49 dsr
-r--r--r-- 1 root root 4096 1970-01-01 01:49 enhanced_area_offset
-r--r--r-- 1 root root 4096 1970-01-01 01:49 enhanced_area_size
-r--r--r-- 1 root root 4096 1970-01-01 01:49 erase_size
-r--r--r-- 1 root root 4096 1970-01-01 01:49 ffu_capable
-r--r--r-- 1 root root 4096 1970-01-01 01:49 fwrev
-r--r--r-- 1 root root 4096 1970-01-01 01:49 hwrev
-r--r--r-- 1 root root 4096 1970-01-01 01:49 life_time
-r--r--r-- 1 root root 4096 1970-01-01 01:49 manfid
-r--r--r-- 1 root root 4096 1970-01-01 01:49 name
-r--r--r-- 1 root root 4096 1970-01-01 01:49 ocr
-r--r--r-- 1 root root 4096 1970-01-01 01:49 oemid
drwxr-xr-x 2 root root 0 1970-01-01 00:00 power
-r--r--r-- 1 root root 4096 1970-01-01 01:49 pre_eol_info
-r--r--r-- 1 root root 4096 1970-01-01 01:49 preferred_erase_size
-r--r--r-- 1 root root 4096 1970-01-01 01:49 prv
-r--r--r-- 1 root root 4096 1970-01-01 01:49 raw_rpmb_size_mult
-r--r--r-- 1 root root 4096 1970-01-01 01:49 rel_sectors
-r--r--r-- 1 root root 4096 1970-01-01 01:49 serial
lrwxrwxrwx 1 root root 0 1970-01-01 01:49 subsystem -> ../../../../../../bus/mmc
-r--r--r-- 1 root root 4096 1970-01-01 01:49 type
-rw-r--r-- 1 root root 4096 1970-01-01 00:00 uevent


读取ext_csd寄存器

这个寄存器属于csd扩展出来的,需要将debugfs挂载出来才能读取到。首先执行:mount -t debugfs none /sys/kernel/debug/
/sys/kernel/debug/mmc0目录下,cat ios可以查看这个eMMC控制器的工作频率和位宽基本信息。

1
2
3
4
5
6
7
8
9
10
11
@xxx:/sys/kernel/debug/mmc0 # cat ios
clock: 52000000 Hz
actual clock: 41666666 Hz
vdd: 21 (3.3 ~ 3.4 V)
bus mode: 2 (push-pull)
chip select: 0 (don't care)
power mode: 2 (on)
bus width: 3 (8 bits)
timing spec: 8 (mmc DDR52)
signal voltage: 1 (1.80 V)
driver type: 0 (driver type B)

然后在/sys/kernel/debug/mmc0/mmc0\:0001/目录下就可以看到ext_csd寄存器了。

1
2
3
4
5
@xxx:/sys/kernel/debug/mmc0/mmc0:0001 # ll
total 0
-r-------- 1 root root 0 1970-01-01 00:00 ext_csd
-r-------- 1 root root 0 1970-01-01 00:00 state
-r-------- 1 root root 0 1970-01-01 00:00 status

cat ext_csd可以得到一个512字节大小的数据,如下

1
2
@xxx:/sys/kernel/debug/mmc0/mmc0:0001 # cat ext_csd
00000000000000000000000000000000390300c0470700c04707000000000000000101000000000000000000000000000000000000000000000000000a000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000900e00070100000000151f20000000000000000000000000000000010100090000000008000200571f0a0aeeee8888001e0f460f78140100c0470710140a0a090201320808400007fdfb550100640aeeeeee99011e0200000000320a00100000ee01000000000000000000012020010100000000000000000000000000000000000000000000000000000000000000000000000000001f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ffffffff00000103007f0003013f3f01010100000000000000

当然这样看很难看,无法很快的确认寄存器中某些位的值。因此,网上就有个小哥写了个python脚本来解析这512字节的数据,以常人可以理解的格式进行解析。详见:https://blog.kylemanna.com/linux/parse-emmc-extended-csd-ecsd-registers-with-python/
输出的格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
victor @victor-HP:~/ work2/cal_time$ python analysis_ext_csd.py 
0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0016: 39 03 00 c0 47 07 00 c0 47 07 00 00 00 00 00 00
0032: 00 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00
0048: 00 00 00 00 00 00 00 00 00 00 00 00 0a 00 00 01
0064: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0096: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0112: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0128: 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00
0144: 00 00 00 00 00 00 00 00 00 00 00 00 00 90 0e 00
0160: 07 01 00 00 00 00 15 1f 20 00 00 00 00 00 00 00
0176: 00 00 00 00 00 00 00 00 01 01 00 09 00 00 00 00
0192: 08 00 02 00 57 1f 0a 0a ee ee 88 88 00 1e 0f 46
0208: 0f 78 14 01 00 c0 47 07 10 14 0a 0a 09 02 01 32
0224: 08 08 40 00 07 fd fb 55 01 00 64 0a ee ee ee 99
0240: 01 1e 02 00 00 00 00 32 0a 00 10 00 00 ee 01 00
0256: 00 00 00 00 00 00 00 00 01 20 20 01 01 00 00 00
0272: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0288: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0304: 00 00 00 1f 01 00 00 00 00 00 00 00 00 00 00 00
0320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0336: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0352: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0368: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0384: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0416: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0432: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0448: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0464: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0480: 00 00 00 00 00 00 01 ff ff ff ff 00 00 01 03 00
0496: 7f 00 03 01 3f 3f 01 01 01 00 00 00 00 00 00 00
BOOT_SIZE_MULTI[226] = 0x20

Python的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env python
"""
Author: Kyle Manna <kyle@kylemanna.com>
Blog: https://blog.kylemanna.com
"""
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 = '00000000000000000000000000000000390300c0470700c04707000000000000000101000000000000000000000000000000000000000000000000000a000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000900e00070100000000151f20000000000000000000000000000000010100090000000008000200571f0a0aeeee8888001e0f460f78140100c0470710140a0a090201320808400007fdfb550100640aeeeeee99011e0200000000320a00100000ee01000000000000000000012020010100000000000000000000000000000000000000000000000000000000000000000000000000001f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ffffffff00000103007f0003013f3f01010100000000000000'
#ecsd_str = '320100'
ecsd = str2bytearray(ecsd_str)
csd_len = len(ecsd)

line_len = 16
i = 0
while i < len(ecsd):
sys.stdout.write("{0:04d}:\t".format(i))
for j in range(line_len):
if (i < csd_len):
sys.stdout.write("{0:=02x}".format(ord(ecsd[csd_len-i-1])))
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 "BOOT_SIZE_MULTI[226] = 0x{:x}".format(ord(ecsd[csd_len-168-1]))

Title:Linux eMMC信息读取

Author:Victor Huang

Time:2019-03-17 / 16:03

Link:http://wowothink.com/33268c93/

License: Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)