SSU_分区介绍


1. 前言

本文用于介绍Sigmastar平台在ALKAID打包环境中的系统分区,包含分区介绍、分区配置、打包烧录等内容


2. 分区介绍

2.1. Flash分区基本介绍

分区表保存在编译输出的partition_layout.txt中,如下图所示,下图的分区配置在不同的软件版本上可能会有差异,请以当前编译的代码为准:

spinand flash分区表信息:

spinor flash分区表信息:

各分区的含义如下:

分区名 描述
CIS 存放flash参数信息以及分区配置信息,spinand flash保存在flash的block0地址的位置,spinor flash则保存在IPL分区之后
IPL/IPL_CUST 存放IPL/IPL_CUST的二进制文件
UBOOT uboot的二进制文件存放分区
ENV uboot的环境变量存放分区,若支持双ENV分区,则还有 ENV1
KERNEL/RECOVERY 存放kernel的二进制文件,RECOVERY是作为kernel的备份分区
rootfs 存放根文件系统的二进制文件
MISC 主要存放开机和升级时的logo图片,该分区使用的是基于littlefs改造的firmawarefs(fwfs)文件系统,可同时支持rtos/uboot/linux
miservice 主要存放mi各模块的ko/so文件,以及一些配置文件和bin档
customer 用户扩展分区
ubia 使用ubifs文件系统的分区,内含miservice、customer的ubi卷

uboot下可用 mtdparts 指令查看分区的layout及各分区的offset和size:

spinand flash spinor flash

linux下可用 cat /proc/mtd 指令查看分区的layout及各分区的size:

spinand flash spinor flash

2.2. CIS分区介绍

CIS分区在flash上的存储结构如下:

存储示例:
flash.nri/flash.sni、partinfo.pni都小于1个page_size,故各占1个page的空间

flash_list.nri/flash_list.sni由于保存了所有支持的Flash信息,它会追加到PAGE1的后面

PAGE的大小由所用的分区配置文件中的 FLASH_PG_SIZE 进行设定,请注意spinand flash和spinor flash的PAGE大小不一定是2k或者4K,由具体所用flash的SPEC决定,需查看对应flash的SPEC

该分区对应的cis.bin文件为打包时由脚本动态拼接而成,由project/image/image.mk中的 cis_nofsimage 负责执行

2.2.1. flash.nri/flash.sni

包含通用的flash参数信息,以便rom code可以从flash上读取IPL,并加载到内存中运行IPL,在ALKAID中的存放路径:

spinand flash project/board/$(CHIP)/boot/spinand/partition/flash.sni
spinor flash project/board/$(CHIP)/boot/nor/partition/flash.nri

2.2.2 partinfo.pni

包含flash的分区信息,注意其仅供IPL/IPL_CUST/uboot使用,而linux则是会解析uboot的mtdparts,按linux原生的语法操作

打包时,由pnigenerator工具根据分区配置信息动态生成partinfo.pni,并存于project/image/output/images/boot/partinfo.pni

pnigenerator工具的源码路径:

project/image/makefiletools/src/pnigenerator/pnigenerator.c

利用服务器上的gcc编译:

gcc pnigenerator.c -Wall –o pnigenerator

使用举例:

pnigenerator -c 1024 -s 0x20000 -a "0x140000(CIS),0x60000(IPL),0x60000(IPL_CUST),0xC0000(UBOOT)"
-b "0x60000(IPL),0x60000(IPL_CUST),0xC0000(UBOOT)" -t "0x60000(ENV),0x20000(KEY_CUST),0x500000(KERNEL),0x500000(RECOVERY),0x600000(rootfs),0x60000(MISC),-(UBI)" -o ${path}/project/image/output/images/boot/partinfo.pni

参数定义:

-r: 读取partinfo.pni文件中的分区并打印。

-c: 所有分区所占FLASH的BLOCK的总和。

-s: FLASH一个BLOCK的data size,单位为byte。

-a: BOOT0 PART分区的集合,表示成mtdparts的语法格式

-b: BOOT1 PART分区的集合,表示成mtdparts的语法格式

-t: SYS PART分区的集合,表示成mtdparts的语法格式

-o: 输出文件的路径及文件名

2.2.3. flash_list.nri/flash_list.sni

包含所有支持的flash的参数信息,在ALKAID中的存放路径:

spinand flash project/board/$(CHIP)/boot/spinand/partition/flash_list.sni
spinor flash project/board/$(CHIP)/boot/nor/partition/flash_list.nri

2.3. IPL/IPL_CUST分区介绍

CPU上电后,首先会运行固化在芯片内的一段code,即rom code,rom code会去加载并运行IPL,然后再由IPL加载并运行IPL_CUST,至此则完成芯片上电的初始化工作

IPL主要是做一些基础硬件的初始化,如设定DDR参数等

IPL_CUST会根据启动模式去加载uboot或kernel

2.4. miservice分区介绍

该分区将会被mount到根目录/config/下面,其主要存放mi各模块的ko/so文件,以及一些配置文件和bin档

└── config
        ├── dla             --> 存放IPU相关的资源文件
        ├── iqfile          --> 存放sensor相关的iq资源文件
        ├── lib             --> 存放mi相关的so库文件
        ├── modparam.json   --> mi模块的配置文件
        ├── modules         --> 存放mi相关的ko文件
        └── venc_fw         --> 存放编解码相关的资源文件

3. 分区配置文件

flash的存储空间分配是由分区配置文件来决定的

分区配置文件是由project/configs/current.configs(该文件由对应的config文件make后自动生成)中的 IMAGE_CONFIG 参数指定,文件位于project/image/configs/general目录下,公版默认使用的分区配置文件如下:

spinand flash project/image/configs/general/spinand.squashfs.partition.config
spinor flash project/image/configs/general/nor.squashfs.partition.config

3.1. 参数介绍

分区配置文件中包含有image info、flash info、ext info以及part info四部分内容:

  • image info:设定需要打包的bin档

  • flash info:设定flash的基本信息,如flash类型、容量信息等

  • ext info:目前主要用于配置uboot的ENV分区

  • part info:设定具体的分区信息

下面介绍常用的参数,未列出的请勿随意修改

3.1.1. image info

image info相关的参数含义:

参数名 含义
IMAGE_LIST 需要生成bin档的分区列表
BOOT_IMAGE_LIST boot.bin包含的分区列表,请勿修改
OTA_IMAGE_LIST OTA升级涉及的分区
USR_MOUNT_BLOCKS 系统启动后需自动挂载的分区

3.1.2. flash info

flash info相关的参数含义:

参数名 含义
FLASH_TYPE 用于指明所适用的flash类型,目前可选值有“spinand”和“nor”
FLASH_BLK_SIZE 1个block的size,单位byte
FLASH_BLK_CNT flash有多少个block
FLASH_PG_SIZE 1个page的size,单位byte
FLASH_SPARE_SIZE spinand flash的spare的size,单位byte,仅spinand flash适用
FLASH_PLANE_CNT spinand flash的plane数,默认为1,仅spinand flash适用
MTDPARTS 符合mtdparts语法的分区信息

3.1.3. ext info

ext info相关的参数含义:

参数名 含义
ENV_CFG 设置到板端的/etc/fw_env.config,以便fw_printenv/fw_setenv能够在linux下正常读写uboot的ENV

3.1.4. part info

part info相关的参数含义:

参数名 含义
RESOURCE 该分区对应的资源文件的存放路径
PATSIZE 配置的分区大小,单位byte
BOOTTAB0 BOOT0 PART分区的集合,表示成mtdparts的语法格式,仅cis可用
BOOTTAB1 BOOT1 PART分区的集合,表示成mtdparts的语法格式,仅cis可用
SYSTAB SYS PART分区的集合,表示成mtdparts的语法格式,仅cis可用
MTDPART 满足mtdparts语法要求的分区大小信息
DATASIZE 制作bin档时,用于设置dd指令的bs参数
COPIES 拷贝次数,即实际将多出COPIES-1个,仅spinand flash的IPL、IPL_CUST、UBOOT支持
OTABLK OTA升级时要操作的设备节点
PATNAME 分区名
BOOTENV 设置uboot的bootargs参数
BOOTCMD 设置uboot的bootcmd参数
BOOTREC 设置uboot的bootcmd参数
BLKENV 设置uboot的环境变量
FSTYPE 文件系统类型
OPTIONS 传递参数给打包脚本
MOUNTTG mount的挂载目录
MOUNTPT mount的挂载源
UBIVOLID ubi设备的卷id

3.2. 分区修改

flash上的分区分为两大类:一类是不建议改动的boot(即 cis$(BOOTTAB0)cis$(BOOTTAB1) 指定的),一类是可以变动的sys(即 cis$(SYSTAB) 指定的),本节介绍的修改是在sys这部分上进行的

3.2.1. 修改分区

3.2.1.1. 修改分区大小

修改对应分区配置中的 $(PATSIZE) 参数即可

分区大小修改后,要认真核对所有分区的大小累加起来有没有超过所用flash的容量

flash的容量 = FLASH_BLK_SIZE * FLASH_BLK_CNT,单位byte

简便的方式,检查partition_layout.txt中的 “FLASH HAS USED”的值是否有超过 flash容量

3.2.1.2. 修改分区位置

在CIS分区的配置中,变量 cis$(BOOTTAB0)cis$(BOOTTAB1)cis$(SYSTAB) 用于配置分区信息

cis(BOOTTAB0)和cis(BOOTTAB1)用于在onebin制作中指定其A-B分区的做法,这种做法会在partinfo.pni中标识其中使用的BOOT是否是活动的,目前在spinand分区中有引入A-B分区,其中BOOTTAB0是活动的分区,当BOOT0在烧录出现异常或者出现坏快的情况下会从BOOT0直接跳到BOOT1的备份分区中,并在partinfo.pni中重新标识活动的分区,下次启动时会自动跑到活动的分区中

BOOTTAB0BOOTTAB1SYSTAB 为分区表的定义,它使用的语法格式是mtdparts所支持的,格式可以写成:

partition0_size(partition0_name), partition1_size(partition1_name), ...

例如下面CIS和IPL分区的描述格式:

0x14000(CIS),0x60000(IPL)

每个分区都由逗号隔开。若没有指定分区的起始位置,则从第一个分区开始算,分区默认是从FLASH的0地址开始。若需要从分区的指定位置配置,则按照以下语法格式:

partition0_size@offset(partition0_name)

指定了分区的起始位置后,在这个分区后面追加的分区如果没有指定其位置,它的起始位置则会在当前分区之后的分区位置逐个增加

若当前分区在分区表中是最后一个,则可以用一个比较方便的方法自适应分区的大小

例如spinand的UBI分区,在分区表最后,它可以表示成:

xxxx(xxxx), xxxx(xxxx),-(UBI)

分区表解析的逻辑会参考当前flash配置的大小自适应UBI的大小

分区位置的修改就是改变 cis$(BOOTTAB0)cis$(BOOTTAB1)cis$(SYSTAB) 这三个变量里面所放分区的位置。但需要注意的是, 不要修改BOOTTAB 部分的分区, 可以修改SYSTAB 部分的分区位置

3.2.1.3. 修改分区文件系统类型

修改对应分区配置中的 $(FSTYPE) 参数即可

目前支持配置的文件系统有squashfs、jffs2、ubifs、fwfs

3.2.2. 增加分区

新增分区的一般步骤如下:

a) 设定所增加分区的分区名,如“usrpart”,并参照现有的分区配置相应的参数

b) 检查所有分区的大小累加起来有没有超过所用flash的容量

c) 在 cis$(SYSTAB) = ”xxx”中指定其放置的位置

d) 在变量“ IMAGE_LIST ”后追加“usrpart”

e) 若需要系统启动后能自动挂载的该分区,则在变量“USR_MOUNT_BLOCKS”后追加“usrpart”

f) 若需要做OTA升级,则在变量“OTA_IMAGE_LIST”后追加“usrpart”

g) 需要注意操作的 mtd 的序号以及节点名

3.2.2.1. 新增squashfs分区

新增的分区信息如下:

usrpart$(RESOUCE)       = $(OUTPUTDIR)/usrpart      #资源文件路径
usrpart$(FSTYPE)        = squashfs                  #文件系统
usrpart$(PATSIZE)       = 0x100000                  #分区大小
usrpart$(MOUNTTG)       = /usrpart                  #在设备端mount时的挂载点
usrpart$(MOUNTPT)       = /dev/mtdblock7            #在设备端mount时的设备节点
usrpart$(OTABLK)        = /dev/mtd7                 #OTA升级时操作的设备节点
usrpart$(MTDPART)       = $(usrpart$(PATSIZE))(usrpart)   #分区信息,用于填入cis$(SYSTAB)
usrpart$(OPTIONS)       = xz                        #分区的压缩方式

并在如下位置添加相应的参数

3.2.2.2. 新增jffs2分区

jffs2一般用于spinor flash上的可读写分区的文件系统

新增的分区信息如下:

usrpart$(RESOUCE)       = $(OUTPUTDIR)/usrpart      #资源文件路径
usrpart$(FSTYPE)        = jffs2                     #文件系统
usrpart$(PATSIZE)       = 0x100000                  #分区大小
usrpart$(MOUNTTG)       = /usrpart                  #在设备端mount时的挂载点
usrpart$(MOUNTPT)       = /dev/mtdblock7            #在设备端mount时的设备节点
usrpart$(OTABLK)        = /dev/mtd7                 #OTA升级时操作的设备节点
usrpart$(MTDPART)       = $(usrpart$(PATSIZE))(usrpart)   #分区信息,用于填入cis$(SYSTAB)

并在如下位置添加相应的参数

3.2.2.3. 新增ubifs分区

ubifs一般用于spinand flash上的可读写分区的文件系统

ubifs的所有的分区都属于UBI的mtd block中的一个子分区,即ubifs分区 不需要添加mtdpart信息 ,也就是 无需在cis$(SYSTAB) 中添加分区位置

新增的分区信息如下:

usrpart$(RESOUCE)       = $(OUTPUTDIR)/usrpart      #资源文件路径
usrpart$(FSTYPE)        = ubifs                     #文件系统
usrpart$(UBIVOLID)      = 2                         #ubi卷id
usrpart$(PATSIZE)       = 0x200000                  #分区大小
usrpart$(MOUNTTG)       = /usrpart                  #在设备端mount时的挂载点
usrpart$(MOUNTPT)       = ubi0:usrpart              #在设备端mount时的设备节点
usrpart$(OTABLK)        = /dev/ubi0_2               #OTA升级时操作的设备节点
usrpart$(OPTIONS)       = ubia                      #该分区将打包进名为ubia.bin的ubifs镜像中

并在如下位置添加相应的参数

3.2.2.4. 新增fwfs分区

fwfs文件系统可同时支持rtos/uboot/linux,其是基于littlefs改造的firmawarefs(fwfs)文件系统

新增的分区信息如下:

usrpart$(RESOUCE)       = $(OUTPUTDIR)/usrpart      #资源文件路径
usrpart$(FSTYPE)        = fwfs                      #文件系统
usrpart$(PATSIZE)       = 0x100000                  #分区大小
usrpart$(MOUNTTG)       = /usrpart                  #在设备端mount时的挂载点
usrpart$(MOUNTPT)       = /dev/mtd7                 #在设备端mount时的设备节点
usrpart$(OTABLK)        = /dev/mtd7                 #OTA升级时操作的设备节点
usrpart$(MTDPART)       = $(usrpart$(PATSIZE))(usrpart)   #分区信息,用于填入cis$(SYSTAB)

并在如下位置添加相应的参数

3.2.2.5. 新增特殊分区

特殊分区指的是没有文件系统的分区,如系统自带的cis、ipl、uboot、kernel等分区

因无法在脚本中做统一的处理,必须在脚本中添加相应的处理逻辑

a) 新增的分区信息如下:

usrpart$(RESOUCE)       = $(OUTPUTDIR)/usrpart      #资源文件路径
usrpart$(PATSIZE)       = 0x100000                  #分区大小
usrpart$(MTDPART)       = $(usrpart$(PATSIZE))(usrpart)   #分区信息,用于填入cis$(SYSTAB)

b) 在如下位置添加相应的参数

c) 在project/image/image.mk中添加 xxx_nofsimage 的指令用于打包,其中xxx即为分区名

usrpart_nofsimage:
    # 实现客户期望的操作,若无,则可置空,但指令节点不可省略

d) 在project/image/script.mk中添加 xxx_$(FLASH_TYPE)__script 的指令用于制作烧录脚本,其中xxx即为分区名。若需要制作烧录脚本,则必须设置IMAGE_LIST;若不需要制作烧录脚本,则不用设置IMAGE_LIST,可跳过该步骤

usrpart_$(FLASH_TYPE)__script:
    # 实现客户期望的操作

e) 如上操作,则可在设备端生成一个不带文件系统的mtd分区

3.2.3. 删除分区

IMAGE_LISTOTA_IMAGE_LISTUSR_MOUNT_BLOCKS 以及 cis$(SYSTAB) 中的需要删除的分区信息去掉,并删除相关的分区配置信息即可

3.3 UBI分区管理开销

UBI文件系统会占用一些flash空间用于自身的管理开销,因此在用df命令显示的ubi分区大小会比配置的ubi分区的大小要小些

UBI管理开销 = UBI特性开销 + UBI头开销

其中:

坏块预留 = MAX(出厂坏块数量,坏块管理预留数量)

特性开销 = (坏块预留 + 1磨损平衡开销 + 2卷表开销 + 1原子操作开销)* 物理块大小(物理块字节数,假设一个物理块是128KB)

UBI头开销 = 2 * 页大小 * (含坏块的总块数 - 坏块预留 - 1个磨损平衡开销 - 1个原子操作开销 - 2个层卷开销)

UBI管理开销 = (坏块预留 + 4)* 物理块大小 + 2 * 页大小 * (含坏块的总块数 - 坏块预留 - 4)

例子:

总大小:128M(1Gbit)

页大小:2K bytes

块大小:128K

块数量:1024

假设是完全无坏块的片子,其管理开销为:

UBI管理开销 = (20 + 4) * 128K + 2 * 2K * (1024 - 20 - 4) = 7072K ≈ 7M


4. 脚本介绍

该部分内容的相关脚本主要涉及分区制作、打包和分区烧录这三部分内容

下面流程图的两个分支,左边走的是分区制作、打包流程,右边走的是分区烧录脚本制作的流程

graph TB
1(分区配置文件:<br>xxx.partition.config) --> 2(分区制作脚本:<br>rootfs.mk/misc.mk/miservice.mk/customer.mk/ramdisk.mk) --> 3(分区打包脚本:<br>image.mk) --> 4(生成对应分区的bin档)
1 --> 5(烧录脚本制作:<br>script.mk) --> 6(生成对应的烧录脚本)

4.1. 分区制作脚本

在project/image/makefile中,会获取 IMAGE_LIST 中带文件系统的分区列表,并赋值给 PARTS_TARGETS 变量,并尝试加载各自对应的分区制作脚本,脚本需位于project/image/configs/general/$(分区名).mk,公版默认的情况下,会依次加载rootfs、misc、miservice、customer对应的分区制作脚本

在各自的分区制作脚本中,完成对各自分区的制作

4.2. 分区打包脚本

在完成分区的制作后,会统一由project/image/image.mk中的相关指令根据分区配置文件中的参数打包成对应形式的bin档,并输出到project/image/output/images/目录下

4.3. 分区烧录脚本制作

在完成分区的制作打包后,还需制作相应分区的烧录脚本,该功能由project/image/script.mk脚本实现,其内的相关指令会根据分区配置文件中的参数生成对应的烧录脚本,并输出到project/image/output/images/scripts/目录下

所制作的烧录脚本均是文本格式,可直接打开查看其中的内容,其内的指令仅能在uboot环境下执行。烧录脚本是以在设备端的uboot环境下,通过tftp的方式下载相关烧录脚本为基本形式,其它的烧录形式均是以此为基础进行相关脚本的改造以适配不同的烧录方式,其烧录流程基本是一致的

4.4. 烧录脚本

一般来说,project/image/output/images/auto_update.txt是整个烧录流程的入口,以公版的spinand为例,auto_update.txt的内容如下,其将依次执行各行的指令以完成各自的操作

4.5. 烧录方式差异

简要介绍不同打包指令生成的image的烧录方式的差异,具体的升级操作请查阅相应的文档:

打包指令 说明
make image-nocheck 生成的是适用于可在uboot环境下通过tftp的方式进行烧录的image,使用estar进行升级
make image-sd 生成的是适用于可在uboot环境下通过sd卡的方式进行烧录的image,名为SigmastarUpgradeSD.bin,使用sdstar进行升级
make image-usb 生成的是适用于可在uboot环境下通过U盘的方式进行烧录的image,名为SigmastarUpgrade.bin,使用usbstar进行升级
make image-ota 生成的是适用于可在linux环境下通过otaunpack的方式进行烧录的image,名为SStarOta.bin.gz,使用otaunpack进行升级