3.9. 分区配置
本章节描述不同存储介质的默认分区方案,这里只关心启动相关的分区,应用相关的分区不同的方案会有不同的选择, 这里不做详细描述。
ZX 的方案中,分区表在 env.txt 配置,配置内容包括各分区在存储介质中的位置和大小。分区中要烧录的内容在
各项目对应的 image_cfg.json 中设置。
env.txt 通常位于 target/<ic>/common/
。
3.9.1. MMC 分区配置
MMC 包括 SD Card 和 eMMC。对于 eMMC,ZX 方案中不支持从 Boot Partition 启动, 只支持从 UDA(User Data Area) 启动,因此具体的分区方式与 SD Card 一致,统一采用 GPT 分区。
目标平台上的 GPT 分区
具体的分区在项目的 image_cfg.json 中配置,mk_image.py 生成镜像过程中,相关分区信息会被添加到 env.bin,
以 GPT=
格式存储在环境变量中:
GPT=size1@offset1(partition name1),size2@offset2(partition name2),-(last partition)
其中 size 是分区的大小,offset 是分区的开始位置(相对 UDA 的开始位置,单位为字节)。
如果是最后一个分区,可以不设置 size@offset
,使用 -
代替,表示剩余的所有空间都分配给该分区。
例如:
image_cfg.json 中的分区配置:
"mmc": { // Media type
"size": "8G", // Size of SD/eMMC
"partitions": { // Partition table apply to device
"spl_1": { "offset": "0x4400", "size": "128k" },
"spl_2": { "size": "367k" },
"uboot": { "size": "1m" },
"env": { "size": "512k" },
"kernel": { "size": "16m" },
"rootfs": { "size": "64m" },
"user": { "size": "-" },
},
},
环境变量中保存的格式:
GPT=128k@0x4400(spl_1),367k(spl_2),1m(uboot),512k(env),16m(kernel),64m(rootfs),-(user)
也可以不设置 offset,表示各分区相连,程序自动计算该分区的开始位置。
例如:
GPT=128k(spl_1),367k(spl_2),1m(uboot),512k(env),512k(bootui),512k(dtb),
16m(kernel),64m(rootfs),-(user)
注意
特别处理
UDA 的前面34个 block 被用作 GPT Header,无论第一个分区是否设置 offset,程序在做分区时都会预留34个 block 给 GPT Header。
即:128k@0x4400(spl_1) 和 128k(spl_1) 是一样的。
下列为基本分区:
分区 |
大小 |
备注 |
|
---|---|---|---|
spl_1 |
128KB |
RAW |
分区开始位置固定,从0x4400开始,大小固定 |
spl_2 |
>= 128KB |
RAW |
分区开始位置固定,镜像备份,可不要 |
uboot |
. |
RAW |
大小根据实际项目需要配置 |
env |
>= 16KB |
RAW |
保存环境变量 |
dtb |
. |
RAW |
保存 kernel dtb,大小根据实际情况分配 |
kernel |
. |
RAW |
大小根据实际项目需要配置 |
rootfs |
. |
Ext4 |
大小根据实际项目需要配置 |
user |
. |
Ext4 |
大小根据实际项目需要配置 |
如果 Kernel 使用 FIT Image 格式,上述分区中的 dtb 可以省略。 user 分区以及是否有更多的应用分区,由具体项目决定。
SD 量产卡的 GPT 分区
量产卡用在工厂生产过程中,通过运行量产卡中的升级程序,对目标平台进行量产升级。
具体的分区设置在 env.txt 中的 burn_mmc=
配置。例如:
burn_mmc=128k@0x4400(spl_1),367k(spl_2),1m(uboot),512k(env),512k(bootui),-(image)
分区格式基本固定:
分区 |
大小 |
备注 |
|
---|---|---|---|
spl_1 |
128KB |
RAW |
用于升级的 SPL |
spl_2 |
>= 128KB |
RAW |
用于升级的 SPL 备份 |
uboot |
. |
RAW |
用于升级的 U-Boot |
env |
>= 16KB |
RAW |
保存环境变量 |
data |
. |
RAW |
保存用于烧录固件镜像文件 |
目标平台在启动到 U-Boot 时,进入量产模式。U-Boot 量产程序从 data
分区读取固件数据,并且烧录到目标存储介质。
SPL 分区的特别说明
MMC GPT 分区时,BROM 启动过程中,固定从两个地方读取 SPL 程序的备份。 首先尝试读取 SPL 备份1,如果验证失败,再尝试读取 SPL 备份2。其中备份2是可选的。
分区 |
大小/位置 |
备注 |
---|---|---|
GPT HEADER |
17KB(LBA0~LBA33) |
预留给 GPT Header |
备份1 |
128KB(LBA34~LBA289) |
必须 |
备份2 |
128KB(LBA290~LBA545) |
可选 |
3.9.2. SPI NAND 分区配置
具体的分区在项目的 image_cfg.json 中配置,mk_image.py 生成镜像过程中,相关分区信息会被添加到 env.bin,
以 MTD=
和 UBI=
格式存储在环境变量中:
MTD=size1@offset1(partition name1),size2@offset2(partition name2),-(last partition)
其中 size 是分区的大小,offset 是分区的开始位置(相对 UDA 的开始位置,单位为字节)。
如果是最后一个分区,可以不设置 size@offset
,使用 -
代替,表示剩余的所有空间都分配给该分区。
例如:
image_cfg.json 中的分区配置:
"spi-nand": { // Device, The name should be the same with string in image:info:media:type
"size": "128m", // Size of SPI NAND
"partitions": {
"spl": { "size": "1m" },
"uboot": { "size": "1m" },
"env": { "size": "256k" },
"kernel": { "size": "12m" },
"ubiroot": {
"size": "32m",
"ubi": { // Volume in UBI device
"rootfs": { "size": "-" },
},
},
"ubisystem": {
"size": "-",
"ubi": { // Volume in UBI device
"user": { "size": "-" },
},
},
}
},
生成的环境变量内容:
MTD=spi1.0:1m(spl),1m(uboot),256k(env),12m(kernel),32m(ubiroot),-(ubisystem)
UBI=ubiroot:-(rootfs);ubisystem:-(user)
前面 MTD=
描述 MTD 分区的配置,后面 UBI=
描述被用作 UBI 的 MTD 分区的 UBI 卷分配。
备注
mtdids 与使用的 spi 接口有关系。当使用 spi0 接口时,为 spi0.0;当使用 spi1 接口时,为 spi1.0
Boot 阶段相关的几个分区有两种备选方案。
方案一: MTD 分区
分区 |
大小 |
备注 |
|
---|---|---|---|
spl |
1MB |
RAW |
保存 SPL 备份的区域 |
uboot |
2MB |
RAW |
保存 U-Boot,需要预留空闲备用块 |
env |
1 Block |
RAW |
保存环境变量 |
envbak |
1 Block |
RAW |
保存环境变量备份,可不用 |
dtb |
1 Block |
RAW |
保存 kernel dtb |
kernel |
. |
RAW |
保存 kernel,需要预留空闲备用块 |
rootfs |
. |
UBIFS |
|
user |
. |
UBIFS |
方案二: UBI 分区
分区 |
大小 |
备注 |
|
---|---|---|---|
spl |
1MB |
RAW |
保存 SPL 备份的区域 |
uboot |
2MB |
RAW |
保存 U-Boot,需要预留空闲备用块 |
env |
1 Block |
RAW |
保存环境变量 |
envbak |
1 Block |
RAW |
保存环境变量备份,可不用 |
dtb |
1 Block |
UBI |
保存 kernel dtb |
kernel |
. |
UBI |
保存 kernel |
rootfs |
. |
UBIFS |
|
user |
. |
UBIFS |
上述两个方案中,差别在于 dtb/kernel 部分是否使用 UBI 分区。由于使用 UBI 分区在启动速度上比使用 MTD 分区稍微慢一点,因此后续如果没有其他原因, 优先使用方案一的分区方式,即启动阶段读取的数据统一使用 MTD 分区保存。
SPL 分区的特别说明
由于 NAND 可能会有坏块,为了尽可能的支持有坏块的 NAND 器件,ZX 平台对 SPL 备份的存储方案做了一些特殊处理。
首先在 NAND 存储设备中,烧录时 SPL 会保存4个备份,每个备份占用一个物理擦除块(PEB)。 因此在 NAND 中,共有4个 PEB 用来保存 SPL。
保存 SPL 的 PEB 是从一个固定的候选 PEB 列表中选取的,具体可参考 表 3.11 。 因此可能分布在 NAND 器件的不同位置。 由于 NAND 厂商保证前面几个块在出厂时不是坏块,因此大概率前面几个块会被选作 SPL 存储块。 因此 ZX 默认将前面 1MB 分为 SPL 分区。
PEB 中保存的 SPL 格式,不是原始的 SPL 数据。在烧录时,SPL 数据被分切为固定 2KB 大小的数据切片, 按照页(Page)进行保存,并且使用 Page Table 对这些数据切片进行管理。
被选中用于保存 SPL 的 PEB,会被标记为保留块(坏块)。因此在烧录 SPL 之后, NAND 上会出现几个被标记了的坏块,这是正常现象。
优先顺序 |
Block ID |
说明 |
---|---|---|
1 |
0 |
启动分区内,优先使用 |
2 |
1 |
启动分区内,优先使用 |
3 |
2 |
启动分区内,优先使用 |
4 |
3 |
启动分区内,优先使用 |
5 |
202 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
6 |
32 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
7 |
312 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
8 |
296 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
9 |
142 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
10 |
136 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
11 |
392 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
12 |
526 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
13 |
452 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
14 |
708 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
15 |
810 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
16 |
552 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
17 |
906 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
18 |
674 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
3.9.3. SPI NOR 分区配置
具体的分区在项目的 image_cfg.json 中配置,mk_image.py 生成镜像过程中,相关分区信息会被添加到 env.bin,
以 MTD=
格式存储在环境变量中:
MTD=size1@offset1(partition name1),size2@offset2(partition name2),-(last partition)
其中 size 是分区的大小,offset 是分区的开始位置(相对 UDA 的开始位置,单位为字节)。
如果是最后一个分区,可以不设置 size@offset
,使用 -
代替,表示剩余的所有空间都分配给该分区。
例如:
MTD=spi0.0:128k(spl),512k(uboot),64k(env),64k(envbak),128k(bootui),128k(dtb),
5m(kernel),8m(rootfs),-(user)
备注
mtdids 与使用的 spi 接口有关系。当使用 spi0 接口时,为 spi0.0;当使用 spi1 接口时,为 spi1.0
SPL 分区的特别说明
NOR 分区时,BROM 启动过程中,固定从两个地方读取 SPL 程序的备份。 首先尝试读取 SPL 备份1,如果验证失败,再尝试读取 SPL 备份2。其中备份2是可选的。
分区 |
大小/位置 |
备注 |
---|---|---|
备份1 |
128KB(0~128KB) |
必须 |
备份2 |
128KB(128KB~256KB) |
可选 |