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属于比较合理的。