前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Android] 查看MTD,EMMC,MMC三种设备的分区

[Android] 查看MTD,EMMC,MMC三种设备的分区

作者头像
wOw
发布2020-01-20 16:48:22
5.5K0
发布2020-01-20 16:48:22
举报
文章被收录于专栏:wOw的Android小站wOw的Android小站

Begining

因为在做系统升级,AOSP的recovery下有一个flash_image工具,这个工具可以在开机状态下刷写系统分区。源码位置在/bootable/recovery/mtdutils/flash_image.c。

但在实际操作中,发现flash_image会报错:

代码语言:javascript
复制
error scanning partitions: No such file or directory

说找不到分区。调查源码发现

代码语言:javascript
复制
// flash_image.c
if (mtd_scan_partitions() <= 0) die("error scanning partitions");

// mtdutils.c  mtd_scan_partitions()
/* Parse the contents of the file, which looks like:
 *
 *     # cat /proc/mtd
 *     dev:    size   erasesize  name
 *     mtd0: 00080000 00020000 "bootloader"
 *     mtd1: 00400000 00020000 "mfg_and_gsm"
 *     mtd2: 00400000 00020000 "0000000c"
 *     mtd3: 00200000 00020000 "0000000d"
 *     mtd4: 04000000 00020000 "system"
 *     mtd5: 03280000 00020000 "userdata"
 */

大概就是会通过/proc/mtd这个文件查找分区信息,然后进行刷写。然后我去找这个文件,结果发现设备里面并没有这个文件。于是开始查找这个mtd相关信息。

Android设备有多个分区存储不同的数据,通常的分区有recovery,boot,system,data和cache分区。几乎每个设备都有它自己的分区设计,这个和生产商有关,但常见的有MTD,EMMC和MMC设备。

MTD

Memory Technology Device,内存技术设备,是用于访问memory设备(ROM、flash)的Linux子系统。MTD的主要目的是为了使新的memory设备的驱动更加简单,为此它在硬件和上层之间提供了一个抽象的接口,并进行了一个层次划分,层次从上到下大致为:设备文件、MTD设备层、MTD原始设备层、硬件驱动层。MTD的所有源代码在/drivers/mtd子目录下。

更详细的MTD设备分析见https://opensourceforu.com/2012/01/working-with-mtd-devices/

MTD设备文件

代码语言:javascript
复制
~ $ ls /dev/mtd* -l
crw-rw----    1 root     root      90,   0 Jan  1 00:00 /dev/mtd0
crw-rw----    1 root     root      90,   1 Jan  1 00:00 /dev/mtd0ro
crw-rw----    1 root     root      90,   2 Jan  1 00:00 /dev/mtd1
crw-rw----    1 root     root      90,   3 Jan  1 00:00 /dev/mtd1ro
crw-rw----    1 root     root      90,   4 Jan  1 00:00 /dev/mtd2
crw-rw----    1 root     root      90,   5 Jan  1 00:00 /dev/mtd2ro
crw-rw----    1 root     root      90,   6 Jan  1 00:00 /dev/mtd3
crw-rw----    1 root     root      90,   7 Jan  1 00:00 /dev/mtd3ro
brw-rw----    1 root     root      31,   0 Jan  1 00:00 /dev/mtdblock0
brw-rw----    1 root     root      31,   1 Jan  1 00:00 /dev/mtdblock1
brw-rw----    1 root     root      31,   2 Jan  1 00:00 /dev/mtdblock2
brw-rw----    1 root     root      31,   3 Jan  1 00:00 /dev/mtdblock3

/dev/mtd:
crw-rw-rw-    1 root     root      90,   0 Jan  1 00:00 0
cr--r--r--    1 root     root      90,   1 Jan  1 00:00 0ro
crw-rw-rw-    1 root     root      90,   2 Jan  1 00:00 1
cr--r--r--    1 root     root      90,   3 Jan  1 00:00 1ro
crw-rw-rw-    1 root     root      90,   4 Jan  1 00:00 2
cr--r--r--    1 root     root      90,   5 Jan  1 00:00 2ro
crw-rw-rw-    1 root     root      90,   6 Jan  1 00:00 3
cr--r--r--    1 root     root      90,   7 Jan  1 00:00 3ro

/dev/mtdblock:
brw-------    1 root     root      31,   0 Jan  1 00:00 0
brw-------    1 root     root      31,   1 Jan  1 00:00 1
brw-------    1 root     root      31,   2 Jan  1 00:00 2
brw-------    1 root     root      31,   3 Jan  1 00:00 3

可以看到有mtdN和对应的/dev/mtd/N、mtdblockN和对应的/dev/mtdblock/N两类MTD设备,分别是字符设备,主设备号90和块设备,主设备号31。其中/dev/mtd0和/dev/mtd/0是完全等价的,/dev/mtdblock0和/dev/mtdblock/0是完全等价的,而/dev/mtd0和/dev/mtdblock0则是同一个MTD分区的两种不同应用描述,操作上是有区别的。

/dev/mtdN设备

/dev/mtdN 是MTD架构中实现的mtd分区所对应的字符设备(将mtd设备分成多个区,每个区就为一个字符设备),其里面添加了一些ioctl,支持很多命令,如MEMGETINFO,MEMERASE等。

mtd-utils中的flash_eraseall等工具,就是以这些ioctl为基础而实现的工具,实现一些关于Flash的操作。比如,mtd 工具中 flash_eraseall中:

代码语言:javascript
复制
if (ioctl(fd, MEMGETINFO, &meminfo) != 0) 
{
   fprintf(stderr, "%s: %s: unable to get MTD device info\n",exe_name, mtd_device);
   return 1;
}

MEMGETINFO是Linux MTD中的drivers/mtd/mtdchar.c中的ioctl命令,使用mtd字符设备需要加载mtdchar内核模块。该代码解释了上面的第一个现象。

/dev/mtdblockN设备

/dev/mtdblockN,是Flash驱动中用add_mtd_partitions()添加MTD设备分区,而生成的对应的块设备。MTD块设备驱动程序可以让flash器件伪装成块设备,实际上它通过把整块的erase block放到ram里面进行访问,然后再更新到flash,用户可以在这个块设备上创建通常的文件系统。

而对于MTD块设备,MTD设备层是不提供ioctl的实现方法的,也就不会有对应的MEMGETINFO命令之类,因此不能使用nandwrite,flash_eraseall,flash_erase等工具去对/dev/mtdblockN去进行操作,否则就会出现上面的现象一,同时也解释了现象3——用mtd2擦除分区后,在用mtdblock2进行umount就会造成混乱。

mtd块设备的大小可以通过proc文件系统进行查看:

代码语言:javascript
复制
~ $ cat /proc/partitions
major minor  #blocks  name

  31     0        512 mtdblock0
  31     1       1024 mtdblock1
  31     2       5632 mtdblock2
  31     3       9216 mtdblock3
 254     0   30760960 mmcblk0    
 254     1   30756864 mmcblk0p1

后面的两个是SD块设备的分区大小。每个block的大小是1KB。

MTD设备分区

通过proc文件系统查看mtd设备的分区情况:

代码语言:javascript
复制
~ $ cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00080000 00020000 "boot"
mtd1: 00100000 00020000 "kernel"
mtd2: 00580000 00020000 "roofs70"
mtd3: 00900000 00020000 "app"

可以发现,实际上mtdN和mtdblockN描述的是同一个MTD分区,对应同一个硬件分区,两者的大小是一样的,只不过是MTD设备层提供给上层的视图不一样,给上层提供了字符和块设备两种操作视图——为了上层使用的便利和需要,比如mount命令的需求,你只能挂载块设备(有文件系统),而不能对字符设备进行挂载,否则会出现上面的现象2:无效参数。

这里对于mtd和mtdblock设备的使用场景进行简单总结:

  1. mtd-utils工具只能应用与/dev/mtdN的MTD字符设备
  2. mount、umount命令只对/dev/mtdblockN的MTD块设备有效
  3. /dev/mtdN和/dev/mtdblockN是同一个MTD设备的同一个分区(N一样)

EMMC

Embedded MultiMedia Card

分区信息可以从/proc/emmc

代码语言:javascript
复制
cat /proc/emmc
dev:        size     erasesize name
mmcblk0p17: 00040000 00000200 "misc"
mmcblk0p21: 0087f400 00000200 "recovery"
mmcblk0p22: 00400000 00000200 "boot"
mmcblk0p25: 22dffe00 00000200 "system"
mmcblk0p29: 002ffc00 00000200 "local"
mmcblk0p27: 090ffe00 00000200 "cache"
mmcblk0p26: 496ffe00 00000200 "userdata"
mmcblk0p30: 014bfe00 00000200 "devlog"
mmcblk0p31: 00040000 00000200 "pdata"
mmcblk0p28: 09800000 00000200 "lib"

来获取。

MMC

MultiMedia Card

它的分区信息只能从/proc/partitions获得:

代码语言:javascript
复制
cat /proc/partitions
major minor  #blocks  name
 254        0     524288 zram0
 179        0   15388672 mmcblk0
 179        1      86016 mmcblk0p1
 179        2          1 mmcblk0p2
 179        3          8 mmcblk0p3
 179        4        512 mmcblk0p4
 179        5        512 mmcblk0p5
 179        6        512 mmcblk0p6
 179        7        512 mmcblk0p7
 179        8       2048 mmcblk0p8
 179        9       2048 mmcblk0p9
 179       10        256 mmcblk0p10
 179       11        256 mmcblk0p11
 179       12      16384 mmcblk0p12
 179       13       1536 mmcblk0p13
 179       14       1536 mmcblk0p14
 179       15         32 mmcblk0p15
 179       16       1536 mmcblk0p16
 179       17         16 mmcblk0p17
 179       18      33792 mmcblk0p18
 179       19       1024 mmcblk0p19
 179       20       1024 mmcblk0p20
 179       21      65536 mmcblk0p21
 179       22      65536 mmcblk0p22
 179       23       1024 mmcblk0p23
 179       24    2883584 mmcblk0p24
 179       25     262144 mmcblk0p25
 179       26      32768 mmcblk0p26
 179       27       1024 mmcblk0p27
 179       28        512 mmcblk0p28
 179       29         32 mmcblk0p29
 179       30     524288 mmcblk0p30
 179       31         32 mmcblk0p31
 259        0        512 mmcblk0p32
 259        1       1024 mmcblk0p33
 259        2      32768 mmcblk0p34
 259        3        512 mmcblk0p35
 259        4       4096 mmcblk0p36
 259        5        256 mmcblk0p37
 259        6        256 mmcblk0p38
 259        7        256 mmcblk0p39
 259        8        256 mmcblk0p40
 259        9        256 mmcblk0p41
 259       10        256 mmcblk0p42
 259       11        256 mmcblk0p43
 259       12        256 mmcblk0p44
 259       13          8 mmcblk0p45
 259       14      65536 mmcblk0p46
 259       15        512 mmcblk0p47
 259       16        512 mmcblk0p48
 259       17   10670063 mmcblk0p49
 179       32       4096 mmcblk0rpmb
 179       64   30375936 mmcblk1
 179       65   30371840 mmcblk1p1
 253        0   10670047 dm-0

但这里显示的一堆盘符并不直观,所以还需要通过name表找到盘符对应分区关系:

代码语言:javascript
复制
msm8937_32:/ # ls -l /dev/block/platform/soc/7824900.sdhci/by-name/
total 0
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 DDR -> /dev/block/mmcblk0p15
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 aboot -> /dev/block/mmcblk0p19
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 abootbak -> /dev/block/mmcblk0p20
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 apdp -> /dev/block/mmcblk0p43
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 boot -> /dev/block/mmcblk0p21
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 cache -> /dev/block/mmcblk0p25
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 cmnlib -> /dev/block/mmcblk0p37
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 cmnlib64 -> /dev/block/mmcblk0p39
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 cmnlib64bak -> /dev/block/mmcblk0p40
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 cmnlibbak -> /dev/block/mmcblk0p38
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 config -> /dev/block/mmcblk0p29
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 devcfg -> /dev/block/mmcblk0p10
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 devcfgbak -> /dev/block/mmcblk0p11
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 devinfo -> /dev/block/mmcblk0p23
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 dip -> /dev/block/mmcblk0p33
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 dpo -> /dev/block/mmcblk0p45
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 dsp -> /dev/block/mmcblk0p12
lrwxrwxrwx 1 root root 20 1970-01-01 09:07 fsc -> /dev/block/mmcblk0p2
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 fsg -> /dev/block/mmcblk0p16
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 keymaster -> /dev/block/mmcblk0p41
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 keymasterbak -> /dev/block/mmcblk0p42
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 keystore -> /dev/block/mmcblk0p28
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 limits -> /dev/block/mmcblk0p31
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 logdump -> /dev/block/mmcblk0p46
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 mcfg -> /dev/block/mmcblk0p36
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 mdtp -> /dev/block/mmcblk0p34
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 misc -> /dev/block/mmcblk0p27
lrwxrwxrwx 1 root root 20 1970-01-01 09:07 modem -> /dev/block/mmcblk0p1
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 modemst1 -> /dev/block/mmcblk0p13
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 modemst2 -> /dev/block/mmcblk0p14
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 mota -> /dev/block/mmcblk0p32
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 msadp -> /dev/block/mmcblk0p44
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 odm -> /dev/block/mmcblk0p47
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 oem -> /dev/block/mmcblk0p30
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 persist -> /dev/block/mmcblk0p26
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 recovery -> /dev/block/mmcblk0p22
lrwxrwxrwx 1 root root 20 1970-01-01 09:07 rpm -> /dev/block/mmcblk0p6
lrwxrwxrwx 1 root root 20 1970-01-01 09:07 rpmbak -> /dev/block/mmcblk0p7
lrwxrwxrwx 1 root root 20 1970-01-01 09:07 sbl1 -> /dev/block/mmcblk0p4
lrwxrwxrwx 1 root root 20 1970-01-01 09:07 sbl1bak -> /dev/block/mmcblk0p5
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 sec -> /dev/block/mmcblk0p17
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 splash -> /dev/block/mmcblk0p18
lrwxrwxrwx 1 root root 20 1970-01-01 09:07 ssd -> /dev/block/mmcblk0p3
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 ssign -> /dev/block/mmcblk0p48
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 syscfg -> /dev/block/mmcblk0p35
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 system -> /dev/block/mmcblk0p24
lrwxrwxrwx 1 root root 20 1970-01-01 09:07 tz -> /dev/block/mmcblk0p8
lrwxrwxrwx 1 root root 20 1970-01-01 09:07 tzbak -> /dev/block/mmcblk0p9
lrwxrwxrwx 1 root root 21 1970-01-01 09:07 userdata -> /dev/block/mmcblk0p49

这样结合两个表就可以找到对应的盘符了。

比如,system分区对应着mmcblk0p24

如果设备里有parted工具,就可以看更多信息

parted 工具

从上面的cat /proc/partitions看到mmcblk0是储存所有分区信息的主block,如果设备root过,就可以通过parted获取上面的信息:

代码语言:javascript
复制
parted /dev/block/mmcblk0

使用参数p(rint)打印信息

上面打印出来的大小单位都不统一,所以可以改成用unit b将单位统一成bytes,这样看起来会更加方便。

help查看可用参数

更多parted操作见https://iwf1.com/how-to-re-partition-your-android-tablet-or-smartphone-all-options-included-change-size-fs-type-etc/2

Reference

https://my.oschina.net/shelllife/blog/123482

https://www.cnblogs.com/shangdawei/p/4514128.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-11-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Begining
  • MTD
    • MTD设备文件
      • /dev/mtdN设备
      • /dev/mtdblockN设备
    • MTD设备分区
    • EMMC
    • MMC
      • parted 工具
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档