linux emmc mbr 分区,eMMC烧录镜像分区信息剖析

eMMC和一般硬盘类似,分区信息位于 mmcblk0 的 0 扇区,内核不负责分区的创建,仅仅是读0扇区MBR及分区表即来获得分区信息。

这里讨论的是非GPT的分区问题

eMMC的镜像生成需要用到genimage工具,其需要改配置文件

具体可查阅官方 https://github.com/pengutronix/genimage

比如

genimage --rootpath "genimage/root" --tmppath "genimage/tmp" --inputpath "genimage/input" --outputpath "genimage/image" --config "genimage/gen.cfg"

它会根据gen.cfg中设置的分区信息来自动生成各分区镜像及总镜像

通过genimage生成了eMMC的镜像,再烧录到eMMC后,启动板子后却发现分区不对,分了8个区(包含一个扩展分区信息)加载后发现最后一个15G的分区识别不出来,

一开始感觉是是哪里出了BUG,导致不支持扩展分区上的逻辑分区大于3个,后面发现这个方向不对,因为用fdisk去看烧录的镜像,可以正确看到所有的分区都是在的

/sbin/fdisk -l ./sdcard.img

Disk ./sdcard.img:286 MiB,299895296 字节,585733 个扇区

单元:扇区 / 1 * 512 = 512 字节

扇区大小(逻辑/物理):512 字节 / 512 字节

I/O 大小(最小/最佳):512 字节 / 512 字节

磁盘标签类型:dos

磁盘标识符:0x00000000

设备          启动   起点     末尾     扇区  大小 Id 类型

./sdcard.img1 *         1    12288    12288    6M  c W95 FAT32 (LBA)

./sdcard.img2       12289   217088   204800  100M  0 空

./sdcard.img3 *    217089   237568    20480   10M  c W95 FAT32 (LBA)

./sdcard.img4      237569 33554431 33316863 15.9G  f W95 扩展 (LBA)

./sdcard.img5      237570   368641   131072   64M 83 Linux

./sdcard.img6      368643   380930    12288    6M  c W95 FAT32 (LBA)

./sdcard.img7      380932   585731   204800  100M  0 空

./sdcard.img8      585733 33554431 32968699 15.7G 83 Linux

总共16G的eMMC

可以看到第一行起点是1,代表扇区,0扇区就是MBR (一个扇区512字节)

第四行起点是237569,第五行起点是237570,代表第四行的分区占用了1个扇区,这一行是扩展分区,它接在三个主分区后面, 大小是15.9G

5~8这4个分区都是分在扩展分区里的逻辑分区, 且逻辑分区间会有1个扇区的间隔,不同于主分区无间隔,这1个扇区是逻辑分区的分区表信息

MBR

dd if=./sdcard.img of=mmc_mbr.bin bs=512 count=1

MBR可以看到三个主分区及扩展分区,逻辑分区则看不到的

/sbin/fdisk -l ./mmc_mbr.bin

读取扩展分区表失败(偏移=237569): 没有那个文件或目录

Disk ./mmc_mbr.bin:512 B,512 字节,1 个扇区

设备           启动   起点     末尾     扇区  大小 Id 类型

./mmc_mbr.bin1 *         1    12288    12288    6M  c W95 FAT32 (LBA)

./mmc_mbr.bin2       12289   217088   204800  100M  0 空

./mmc_mbr.bin3 *    217089   237568    20480   10M  c W95 FAT32 (LBA)

./mmc_mbr.bin4      237569 33554431 33316863 15.9G  f W95 扩展 (LBA)

扩展分区

每次能看到2个分区的信息

逻辑分区1,2

dd if=./sdcard.img of=partition.bin bs=512 count=1 skip=237569

/sbin/fdisk -l partition.bin

读取扩展分区表失败(偏移=131073): 没有那个文件或目录

设备           启动   起点   末尾   扇区 大小 Id 类型

partition.bin1           1 131072 131072  64M 83 Linux

partition.bin2      131073 143361  12289   6M  f W95 扩展 (LBA)

逻辑分区2,3

dd if=./sdcard.img of=partition2.bin bs=512 count=1 skip=368642

/sbin/fdisk -l partition2.bin

读取扩展分区表失败(偏移=143362): 没有那个文件或目录

设备            启动   起点   末尾   扇区  大小 Id 类型

partition2.bin1           1  12288  12288    6M  c W95 FAT32 (LBA)

partition2.bin2      143362 348162 204801  100M  f W95 扩展 (LBA)

逻辑分区3, 4

dd if=./sdcard.img of=partition3.bin bs=512 count=1 skip=380931

/sbin/fdisk -l partition3.bin

读取扩展分区表失败(偏移=348163): 没有那个文件或目录

Disk partition3.bin:512 B,512 字节,1 个扇区

设备            启动   起点     末尾     扇区  大小 Id 类型

partition3.bin1           1   204800   204800  100M  0 空

partition3.bin2      348163 33316862 32968700 15.7G  f W95 扩展 (LBA)

烧录后,在板子上查看分区表信息,如下最后一个分区活生生被吃了,只有1到7,少了8

/ # cat /proc/partitions

major minor  #blocks  name

1        0       8192 ram0

1        1       8192 ram1

31        0        512 mtdblock0

31        1        256 mtdblock1

31        2         64 mtdblock2

31        3        512 mtdblock3

31        4        640 mtdblock4

31        5         64 mtdblock5

179        0   15267840 mmcblk0

179        1       6144 mmcblk0p1

179        2     102400 mmcblk0p2

179        3      10240 mmcblk0p3

179        4          1 mmcblk0p4

179        5      65536 mmcblk0p5

179        6       6144 mmcblk0p6

179        7     102400 mmcblk0p7

179       24       4096 mmcblk0boot1

179       12       4096 mmcblk0boot0

/proc/partitions这个是由内核生成的,可以定位到是内核出了问题,只能从源码上着手分析了

eMMC kernel加载过程

mmc_blk_probe->block.c

mmc_add_disk->

add_disk->genhd.c

register_disk->

blkdev_get->block_dev.c

__blkdev_get->

rescan_partitions->partition-generic.c

check_partition

add_partition // 这里添加分区信息

//add_partition是由rescan_partition调用的

//block/partition-generic.c

int rescan_partitions(struct gendisk *disk, struct block_device *bdev)

{

/* add partitions */

for (p = 1; p < state->limit; p++) { // 注意这里state->limit限制了分区数

part = add_partition(disk, p, from, size,

state->parts[p].flags,

&state->parts[p].info);

}

}

// state->limit分区数限制是从哪里来的呢,是从下面这个disk_max_parts来的

static inline int disk_max_parts(struct gendisk *disk)

{

if (disk->flags & GENHD_FL_EXT_DEVT)

return DISK_MAX_PARTS;

return disk->minors; // 到这里就变成由minors限定了

}

// 这里会把disk_max_parts返回的值赋值给state->limit

//block/partitions/check.c

static struct parsed_partitions *allocate_partitions(struct gendisk *hd)

{

struct parsed_partitions *state;

int nr;

state = kzalloc(sizeof(*state), GFP_KERNEL);

if (!state)

return NULL;

nr = disk_max_parts(hd); // 获取最大分区数

state->parts = vzalloc(nr * sizeof(state->parts[0]));

if (!state->parts) {

kfree(state);

return NULL;

}

state->limit = nr; // 这里对数量做了限制

return state;

}

// limit由minors来的,那么minors又是从哪里赋值来的呢,看下面这个函数

//drivers/mmc/card/block.c

// 这里predev_minor从CONFIG_MMC_BLOCK_MINORS赋值来的,看到有CONFIG_XX就可以猜测是内核的配置中设置的

// 所以如果eMMC镜像写入后,kernel再加载出来分区数少了,很可能是这个CONFIG_MMC_BLOCK_MINORS的值设置小了

// 原因大致是定位到了,接下来是为了验证这个猜想, 看代码

static int perdev_minors = CONFIG_MMC_BLOCK_MINORS;

static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,

struct device *parent,

sector_t size,

bool default_ro,

const char *subname,

int area_type)

{

md->disk = alloc_disk(perdev_minors); // 在这里由perdev_minors赋值来的, alloc_disk的函数名就叫minors

}

// 这里看函数原型

//block/genhd.c

struct gendisk *alloc_disk(int minors)

{

return alloc_disk_node(minors, NUMA_NO_NODE);

}

EXPORT_SYMBOL(alloc_disk);

struct gendisk *alloc_disk_node(int minors, int node_id)

{

disk->minors = minors; // 这里就是minors的真正赋值的地方

}

修改kernel config中的 CONFIG_MMC_BLOCK_MINORS 为9后就正常了(只要大于8就行), 原始的配置就是8, 所以就少了一个分区

/ # cat /proc/partitions

major minor  #blocks  name

1        0       8192 ram0

1        1       8192 ram1

31        0        512 mtdblock0

31        1        256 mtdblock1

31        2         64 mtdblock2

31        3        512 mtdblock3

31        4        640 mtdblock4

31        5         64 mtdblock5

179        0   15267840 mmcblk0

179        1       6144 mmcblk0p1

179        2     102400 mmcblk0p2

179        3      10240 mmcblk0p3

179        4          1 mmcblk0p4

179        5      65536 mmcblk0p5

179        6       6144 mmcblk0p6

179        7     102400 mmcblk0p7

179        8   14974973 mmcblk0p8

179       24       4096 mmcblk0boot1

179       12       4096 mmcblk0boot0

正常

作者:帅得不敢出门

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux emmc分区表是指在Linux系统中,对emmc存储设备进行分区时所采用的分区表。emmc是一种内置式存储设备,类似于固态硬盘,常用于嵌入式系统和移动设备中。在Linux系统中,可以使用fdisk、parted等工具对emmc进行分区分区表包括主分区、扩展分区、逻辑分区等。通过分区表的设置,可以将emmc存储设备划分为多个逻辑分区,实现数据的存储和管理。 ### 回答2: eMMC是一种嵌入式多媒体卡,其功能类似于SD卡,但相比于SD卡来说更加小巧便携,能够被广泛应用在移动设备上。而在eMMC上进行分区也需要一个分区表来帮助系统管理内存空间的使用。 Linux系统中的eMMC分区表主要包括两部分:GPT(GUID Partition Table)和MBR(Master Boot Record)。GPT是一种基于GUID的分区表,支持更大的分区。而MBR是一种早期的分区表,只支持最多4个主分区。 在Linux系统上,可以使用fdisk和parted命令来管理eMMC分区表。fdisk是一个早期的分区工具,现在已经被parted命令所替代。使用parted命令可以更加灵活地进行分区操作,支持创建GPT和MBR两种分区表,同时还支持多种文件系统格式。 对于eMMC分区表,需要注意以下几点: 1. eMMC必须被分区才能使用,而且分区表的格式必须与eMMC本身的格式兼容。 2. 在分区的时候需要注意每个分区的大小和文件系统格式,以便于系统正确识别分区。 3. 对于移动设备来说,需要注意eMMC分区表和启动引导程序,以保证系统正常启动。 总之,eMMC分区表对于移动设备中应用程序、数据和系统的管理非常关键,需要仔细考虑分区安排以及分区表的格式选择。在Linux系统中,可以使用parted等命令来进行分区表的管理和设置。 ### 回答3: Linux系统中,eMMC分区表是管理embedded MultiMediaCard(eMMC)存储器中各个分区的工具。eMMC是一种嵌入式存储器,与SD卡类似,但eMMC集成在设备基板上,因此具有更高的可靠性和更快的数据传输速度。 eMMC分区表通常包括以下字段: 1. 名称:分区的名称,通常是一个简短的文本描述。 2. 大小:分区的大小,以MB或GB为单位。 3. 类型:分区的类型,例如Linux文件系统、EFI分区、交换分区等。 4. 起始地址:分区eMMC存储器中的起始地址。 5. 结束地址:分区eMMC存储器中的结束地址。 eMMC分区表通常被写入到eMMC存储器中的引导扇区,以便Linux系统可以正确识别和管理eMMC中的分区。用户可以使用Linux命令行工具(如fdisk或parted)创建、修改或删除eMMC分区表。 eMMC分区表的设计需要考虑设备的功能需求、数据安全性以及系统的效率等因素。例如,将EFI分区Linux交换分区放在较小的分区中,可以提高系统性能。 总之,eMMC分区表是Linux系统中管理eMMC存储器分区的重要工具,可以帮助用户有效管理存储器,提高设备性能和数据的安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值