SigmaStar Android分区说明
1. 概述¶
本文介绍了SigmaStar Android使用的分区格式和新、删、改分区的方法。
2. 分区格式¶
SigmaStar Android平台使用的是GPT(GUID Partition Table)格式的分区表,和MBR(master boot record)分区表都是记录存储介质分区信息的格式。
更多的GPT相关介绍请参考维基百科:https://en.wikipedia.org/wiki/GUID_Partition_Table
2.1. GPT分区表格式简单介绍¶
对于使用了GPT分区表的存储设备layout大致如下图:
LBA0在GPT格式分区表中没有任何GPT相关的数据,因为MBR格式的分区表会用LBA0开始记录分区信息,为了防止下载GPT分区表把原有的MBR信息覆盖,GPT从LBA1开始记录分区信息。
GPT的分区表会分别存放在LBA1和LBA(-1)起始,位于LBA(-1)的分区表起到备份作用。
GPT分区表分为分区表头和分区表项:
分区表头结构:
相对字节偏移量 (十六进制) | 字节数 | 说明[整数皆以little endian方式表示] |
---|---|---|
00~07 | 8 | GPT头签名“45 46 49 20 50 41 52 54”(ASCII码为“EFI PART”) |
08~0B | 4 | 版本号,目前是1.0版,其值是“00 00 01 00” |
0C~0F | 4 | GPT头的大小(字节数),通常为“5C 00 00 00”(0x5C),也就是92字节。 |
10~13 | 4 | GPT头CRC校验和(计算时把这个字段本身看做零值) |
14~17 | 4 | 保留,必须为“00 00 00 00” |
18~1F | 8 | EFI信息区(GPT头)的起始扇区号,通常为“01 00 00 00 00 00 00 00”,也就是LBA1。 |
20~27 | 8 | EFI信息区(GPT头)备份位置的扇区号,也就是EFI区域结束扇区号。通常是整个磁盘最末一个扇区。 |
28~2F | 8 | GPT分区区域的起始扇区号,通常为“22 00 00 00 00 00 00 00”(0x22),也即是LBA34。 |
30~37 | 8 | GPT分区区域的结束扇区号,通常是倒数第34扇区。 |
38~47 | 16 | 磁盘GUID(全球唯一标识符,与UUID是同义词) |
48~4F | 8 | 分区表起始扇区号,通常为“02 00 00 00 00 00 00 00”(0x02),也就是LBA2。 |
50~53 | 4 | 分区表总项数,通常限定为“80 00 00 00”(0x80),也就是128个。 |
54~57 | 4 | 每个分区表项占用字节数,通常限定为“80 00 00 00”(0x80),也就是128字节。 |
58~5B | 4 | 分区表CRC校验和 |
5C~* | * | 保留,通常是全零填充 |
分区表项结构:
相对字节偏移量 (十六进制) | 字节数 | 说明[整数皆以little endian方式表示] |
---|---|---|
00~0F | 16 | 用GUID表示的分区类型 |
10~1F | 16 | 用GUID表示的分区唯一标示符 |
20~27 | 8 | 该分区的起始扇区,用LBA值表示。 |
28~2F | 8 | 该分区的结束扇区(包含),用LBA值表示,通常是奇数。 |
30~37 | 8 | 该分区的属性标志 |
38~7F | 72 | UTF-16LE编码的人类可读的分区名称,最大32个字符。 |
3. AOSP中的分区配置方法¶
3.1. 配置文件所在位置¶
目前在SigmaStar Android平台编译环境中,分区设定的相关配置文件统一放到了路径:
<AOSP>/device/sigmastar/common/partition
当前只有8G的分区设定:
其中:
.json文件用于配置生成partition_table.img
.mk文件用于配置AOSP镜像的大小
需要注意的是:当我们在修改分区配置调整分区大小时,修改json代表了实际开发中的分区大小改变,而修改mk文件则代表实际生成的镜像大小改变,所以一般修改json和mk是一起调整的,以防止烧录或启动时发生错误。
3.2. 配置文件的选择¶
以当前lunch sstar_pioneer5_tv-userdebug为例,其device的配置目录在:
<AOSP>/device/sigmastar/pioneer5/pioneer5_sdp
其中<AOSP>/device/sigmastar/pioneer5/BoardConfig-common.mk
会根据当前的配置情况选择不同的mk和json组合,形如:
例如当前设定是:关闭动态分区、关闭AVB,则选择的是:
partition-table-8GB-nondynamic.mk与 partition-table-8GB-nondynamic-noavb.json
3.3. Json配置文件的格式¶
由3.1章已知,Json是用于配置生成分区表镜像partition-table.img,其格式形如:
1. { 2. # 分区表全局设定 3. "settings": { 4. "disk_alignment": 512, #eMMC的分区的对齐单位 5. "disk_size": "7.2 GB" #eMMC的总容量 6. }, 7. # 分区表项设定 8. "partitions": [ 9. { 10. "label": "bootloader", # 分区名 11. "size": 4194304, # 分区大小 12. "ignore": true, # 是否不生成该分区的分区表项(即使不生成表项,该分区也是存在) 13. "hw_part_name": "BOOT", # 该分区所在的硬件分区 14. "image_name": "bootloader.img", # 该分区对应的镜像名 15. "is_download": true # 在烧录时是否烧录该分区 16. }, 17. { 18. "ab": true, # 是否A/B分区 19. "label": "boot", 20. "size": 33554432, 21. "guid": "auto", # 唯一识别该分区的ID,一般自动生成 22. "type_guid": "brillo_boot", 23. "hw_part_name": "UDA", 24. "image_name": "boot.img", 25. "is_spare_image": false, # 是否时稀疏格式的镜像 26. "is_download": true 27. }, 28. { 29. ...... 30. } 31. ] 32. }
本例中的boot分区设定,是因为:
- boot.img最终要下到UDA硬件分区中的boot分区中
- boot.img镜像大小是32M
- 刷机时需要烧录该分区
3.3.1. 关于disk size¶
由于eMMC会自动回收掉坏块,随着eMMC使用时间的增加坏块数逐渐增加,eMMC的实际可用容量会逐渐变小,所以disk size要根据当前eMMC实际的容量来设置,一般8G大小的eMMC我们会将其disk size设置为7.2G。
3.3.2. 关于页表项size¶
需注意的是所有“UDA”页表项size的总和不能大于“settings”中的“disk size”。
3.3.3. 关于硬件分区¶
在eMMC中有BOOT、UDA(User Data Area)、RPMB等硬件分区,我们常说的分区其实是逻辑分区,partition-table.img实际上是被下载到了UDA用于对UDA硬件分区再分出软件逻辑分区,所以才会分区表项中才会有lable和hw_part_name两个属性需要设置。
3.3.4. 关于动态分区的设定¶
动态分区会将OTA可升级的分区都集合到一个super分区,并在super分区中动态为这些分区分配空间。在GPT分区表中并不需要记录super分区中是如何分配逻辑分区的(否则就不是所谓的动态分区了),这部分由系统运行起来动态去管理。所以开启动态分区的Json档会发现system、vendor、produc等分区表项被移除,取而代之的是super分区表项。
3.4. mk配置文件格式¶
由3.1章已知,mk是用于配置生成AOSP镜像,对于非动态分区其格式形如:
对于动态分区,其格式形如:
3.4.1 BOARD_<镜像名>_PARTITION_SIZE¶
使用BOARD_<镜像名>_PARTITION_SIZE
来设定分区大小,AOSP在编译时会根据其设定的分区大小在镜像尾端填充dummy数据,并添加AVB页脚(启用AVB时),例如boot.img即通过BOARD_BOOTIMAGE_PARTITION_SIZE
来设定其最终编译出来的镜像大小。一般地,mk设定的BOARD_<镜像名>_PARTITION_SIZE
需要跟Json中对应label分区表项中的size属性保持一致。
3.4.2 BOARD_<镜像名>_FILE_SYSTEM_TYPE¶
对于一些有文件系统的镜像格式,还可以通过BOARD_<镜像名>_FILE_SYSTEM_TYPE
来设定。目前AOSP支持ext4和f2fs两种格式。
3.4.3 SUPER分区相关的配置¶
设定方法形如:
1. # 设定super分区总大小 2. BOARD_SUPER_PARTITION_SIZE := <size-in-bytes> 3. # 指定分区组列表,假设当前只有一个分区组group_0 4. BOARD_SUPER_PARTITION_GROUPS := group_0 5. # 每个group可以再单独指定总大小,假设是1G 6. BOARD_GROUP_0_SIZE := 1073741824 7. # 指定group中有哪些分区 8. BOARD_GROUP_0_PARTITION_LIST := system vendor
由3.3.4章已知,动态分区实际上是用一个大的UDA中分区包含了一些其他分区,所以需要先用BOARD_SUPPER_PARTITION_SIZE
设定super分区的大小,编译时会根据设定生成一个包含super分区metadata的镜像,包含了super分区大小的信息。
super分区支持对其其中的逻辑分区分组,可以通过BOARD_SUPER_PARTITION_GROUPS
列出有哪些分区组,本例中创建了group_0
一个分区组。
分区组的大小是需要设定的,通过BOARD_<分区组名>_SIZE
设定。
因为设定的分区组大小代表的是一个slot
占用的大小,对于A/B设备,一个分区组在super所占的空间实际上是分区组大小*2,所以分区组大小总和有如下限制:
-
对于非A/B和虚拟A/B设备:
BOARD_SUPER_PARTITION_SIZE - overhead
-
对于A/B设备
BOARD_SUPER_PARTITION_SIZE/2 - overhead
overhead即动态分区元数据占的空间,一般4M属于比较合理的。