RISC-V生态全景解析(十四):YoC组件介绍系列四: PARTITION组件

简介: 芯片开放社区(OCC)面向开发者推出RISC-V系列内容,通过多角度、全方位解读RISC-V,系统性梳理总结相关理论知识,构建RISC-V知识图谱,促进开发者对RISC-V生态全貌的了解。

编辑语:

芯片开放社区(OCC)面向开发者推出RISC-V系列内容,通过多角度、全方位解读RISC-V,系统性梳理总结相关理论知识,构建RISC-V知识图谱,促进开发者对RISC-V生态全貌的了解。


YoC基础软件平台具有丰富的IoT组件,可有效支持RISC-V生态应用开发。前几期内容中,我们已经陆续介绍了YoC的CSI组件AT组件AV(多媒体)组件。本期内容,我们将为大家介绍YoC的PARTITION组件,从分区表介绍、配置与接口、配置示例三方面带大家详细了解该组件。


01 概述

PARTITION组件是一个分区管理的组件。基于分区表(MTB)的分区信息来统一管理Flash分区,对分区进行统一的读写、擦除、以及验签的操作。


下面就来介绍下分区表的定义以及组件提供的一些API接口。


02 分区表介绍

分区表简称为MTB(manifest table)。保存系统镜像的基本信息以及签名值。MTB分为两类。

名称

说明

BMTB

bootloader manifest table,记录bootloader镜像的信息,给bootrom使用

IMTB

images manifest table,记录除bootloader以外的其他镜像的信息,给bootloader使用


其中IMTB是必须的,而BMTB则取决于芯片bootrom的设计,是否需要这张BMTB表,使用BMTB的优势是可以灵活的配置boot的地址信息,避免固化在bootrom里。这2张表本身就是以分区的形式存储在Flash中的,在定义分区的时候要预留出来。分区名字也是固定为"bmtb"和"imtb"。

截屏2021-11-22 下午9.29.29.png


分区的信息存储在一个叫config.yaml的文件中,一般放在工程的board或者solution目录下,在打包镜像的时候通过工具自动生成bmtb/imtb两个镜像。


一个典型的分区表如下:

mtb_version: 4
chip: pangu        # cb2201 / cb6501 / pangu
diff:
  fota_version: 0
  ram_buf: 50         #DEC     KB   ( max ram need)
  flash_buf: 16       #DEC     KB   ( buffer size)
  flash_sector: 4096  #DEC     byte ( flash sector)
  diff_mode: 010      #BIN
  double_control: 1   #DEC (1--use 2 sector for diff restore,0--1 sector)
flash:
  base_address: 0x8000000       # the base address of flash
  run_base_address: 0x18000000  # the run address, maybe sdram address
  sector: 4096                  # Bytes
  size: 16777216                # Bytes, $(sector count) * sector
partitions:
  - { name: bmtb,   address: 0x8000000, size: 0x001000 }
  - { name: boot,   address: 0x8001000, size: 0x020000 }
  - { name: tee,    address: 0x8021000, load_addr: 0x18000000, size: 0x010000 }
  - { name: imtb,   address: 0x8031000, size: 0x002000 }
  - { name: prim,   address: 0x8033000, load_addr: 0x18010000, size: 0x300000, verify: true, update: FULL}
  - { name: kv,     address: 0x8633000, size: 0x004000 }
  - { name: lpm,    address: 0x8637000, size: 0x020000 }
  - { name: misc,   address: 0x8657000, size: 0x400000 }


下面介绍下各个字段的意思。


2.1 一级字段说明

字段

说明

mtb_version

MTB格式版本号,默认填4即可

chip

芯片类型

diff

用于差分升级相关的配置参数

flash

flash信息相关参数

partitions

分区表相关参数


2.2 diff字段说明

字段

是否必选

说明

ram_buf

差分还原时所需的ram空间,单位KB;

大于2.3倍flash缓存大小;建议配置为设备系统最大可用内存,以提高差分效率;

大致计算公式:

ram_buf = 2.2 * <flash_buf> + 2 * <flash_sector> + 1024B;

flash_buf

差分还原时所需的flash缓存空间,最小4KB,单位KB;

大于扇区大小,且为扇区大小整数倍;

flash_sector

flash扇区大小,单位byte;

diff_mode

差分模式,二进制字符串,默认使用10模式即可;

value verify  auto_config

00  disable  disable

01  disable  enable

10  enable  disable

11  enable  enable

double_control

是否使用2个flash_sector作为差分控制区域;

此字段不填或者0:1个sector,1:2个sector;

如果在Flash空间上没有特别的紧张,建议使用2个sector作为差分控制区域;


2.3 flash字段说明

字段

是否必选

说明

base_address

flash的起始绝对地址

run_base_address

镜像的运行地址,不填则为flash起始地址

sector

flash每个sector的尺寸,单位byte

size

flash总的大小,单位byte


2.4 partitions字段说明

字段

是否必选

说明

name

分区名字,最长8个字节

address

分区起始地址

load_addr

分区加载地址,如果没有此字段,则默认使用address为加载地址

size

分区大小,单位byte

update

分区升级类型[DIFFFULLNONE],不填则默认为NONE;针对boot分区的升级需要谨慎,因为本身升级的功能在boot里面。

verify

是否要对分区进行签名

file

指定分区对应的镜像文件名字,不填则表示文件名与分区名相同


2.5 常用分区说明

分区

说明

imtb

分区表信息,包含所有分区位置及安全信息

tee

安全执行镜像

boot

bootloader

prim

应用镜像

kv

用户数据区域

misc

升级备份区

lpm

低功耗信息保存区


2.6 注意事项

  • bmtb分区名字固定,大小为1个sector大小,非必选分区。

  • imtb分区名字固定,大小为2个sector大小,必选分区。最好放在比较靠前的地址区域,可以减少查表的时间。
  • tee、prim、boot、kv分区名字固定,不建议修改,大小根据用户自己实际情况来配置,sector对齐。
  • misc分区名字固定,全量和差分升级时所需要的备份分区,大小根据实际情况来配置,sector对齐。
  • 其他分区大小也是sector对齐,名字用户可以自定义。


03 配置与接口介绍

介绍partition组件的一些参数配置和常用API接口。


3.1 参数配置

以下宏定义在PARTITION组件的yoc/partition.h文件中,用户可以在应用方案的package.yaml中的def_config字段中进行重新定义。

宏配置

说明

CONFIG_MAX_PARTITION_NUM

分区个数配置。

定义最大的分区个数,如果用户没有自定义,那么默认为12个分区大小。如果ram资源比较紧张,而分区又没有达到12个,那么可以把这个宏改成实际分区个数。每减少一个分区,分别可以节省40个字节的data段size,和调用partition_init的任务最多40个字节的栈空间。

CONFIG_PARITION_NO_VERIFY

分区校验配置。

是否开启分区校验功能,默认值为1,为不开启校验。

安全的方案需要配置成0。

CONFIG_NOT_SUPORRT_SASC

安全区域设置配置。配置分区的访问权限。

是否支持设置安全区域,默认值为1,不支持设置安全区域。

如果芯片支持,可以在board组件中配置为0,开启此功能。


3.2 接口介绍

API接口定义在yoc/partition.h文件中。提供了包括分区初始化、打开、关闭、读写、Verify等操作。


整个系统中需要调用partition_init初始化一次,后面才能对分区进行一些操作。

接口

说明

partition_init

分区初始化

partition_open

打开分区

partition_close

关闭分区

partition_info_get

获取分区信息

partition_read

读取分区数据

partition_write

往分区写数据

partition_erase

擦除分区数据

partition_verify

校验分区

partition_all_verify

校验所有分区

partition_get_digest

获取分区数字摘要信息

partition_set_region_safe

设置安全区域,调用此接口可以把分区配置成只在安全环境下可读写。


3.3 Flash操作接口适配

在yoc/partition_flash.h文件中,定义了一个partition_flash_ops_t结构体,有自定义Flash操作接口的用户可以实现这个结构体的操作接口,并通过partition_flash_register接口进行注册。


注意:系统默认带有一套基于设备驱动框架的Flash接口。如果是无操作系统的应用,则需要用户自己实现一套接口,并注册。


以下为在BOOT方案中实现Flash接口的一个例子:


#include <drv/spiflash.h>
#include <yoc/partition_flash.h>
static csi_spiflash_t spiflash_hd;
static csi_spiflash_info_t spiflash_info;
static int _boot_flash_info_get(void *handle, partition_flash_info_t *info)
{
    if (info != NULL) {
        csi_error_t ret = csi_spiflash_get_flash_info(&spiflash_hd, &spiflash_info);
        if (ret != CSI_OK) {
            return -1;
        }
        info->start_addr = spiflash_info.xip_addr;
        info->sector_size = spiflash_info.sector_size;
        info->sector_count = spiflash_info.flash_size / spiflash_info.sector_size;
        return 0;
    }
    return -1;
}
static int _boot_flash_read(void *handle, uint32_t addr, void *data, size_t data_len)
{
    int ret = csi_spiflash_read(&spiflash_hd, addr - spiflash_info.xip_addr, data, data_len);
    if (ret < 0) {
        return -1;
    }
    return 0;
}
static int _boot_flash_write(void *handle, uint32_t addr, void *data, size_t data_len)
{
    int ret = csi_spiflash_program(&spiflash_hd, addr - spiflash_info.xip_addr, data, data_len);
    if ( ret < 0) {
        return -1;
    }
    return 0; 
}
static int _boot_flash_erase(void *handle, uint32_t addr, size_t len)
{
    csi_error_t ret;
    if (len % spiflash_info.sector_size) {
        len = (len / spiflash_info.sector_size + 1) * spiflash_info.sector_size;
    }
    ret = csi_spiflash_erase(&spiflash_hd, addr, len);
    if (ret) {
        return ret;
    }
    return 0;
}
static const partition_flash_ops_t g_flash_ops = {
    .open = NULL,
    .close = NULL,
    .info_get = _boot_flash_info_get,
    .read = _boot_flash_read,
    .write = _boot_flash_write,
    .erase = _boot_flash_erase
};
int boot_flash_init(void)
{
    csi_spiflash_qspi_init(&spiflash_hd, 0, NULL);
    partition_flash_register((void *)&g_flash_ops);
    return 0;
}


04 配置示例

下面介绍几种方案的配置。主要是BOOT、TEE、APP三种类型的方案。其中BOOT、TEE是无操作系统的,APP是带操作系统的。


4.1 BOOT方案

BOOT方案只涉及到package.yaml的配置。


4.1.1 非安全方案


def_config:
  CONFIG_PARITION_NO_VERIFY: 1
  CONFIG_NOT_SUPORRT_SASC: 1


4.1.2 安全方案


def_config:
  CONFIG_PARITION_NO_VERIFY: 0
  CONFIG_NOT_SUPORRT_SASC: 0


4.2 TEE方案

TEE方案只涉及到package.yaml的配置。

def_config:
  CONFIG_PARITION_NO_VERIFY: 0
  CONFIG_NOT_SUPORRT_SASC: 0


4.3 APP方案

APP方案涉及到package.yaml和config.yaml的配置。


4.3.1 非安全方案

非安全的方案不会对分区进行验签,没有TEE。


  • config.yaml分区配置表中partitions字段的配置
partitions:
  - { name: bmtb,   address: 0x8000000, size: 0x001000 }
  - { name: boot,   address: 0x8001000, size: 0x020000 }
  - { name: imtb,   address: 0x8031000, size: 0x002000 }
  - { name: prim,   address: 0x8033000, load_addr: 0x18010000, size: 0x300000, update: FULL}
  - { name: kv,     address: 0x8633000, size: 0x004000 }
  - { name: lpm,    address: 0x8637000, size: 0x020000 }
  - { name: misc,   address: 0x8657000, size: 0x400000 }


  • 应用方案的package.yaml文件
def_config:
  CONFIG_PARITION_NO_VERIFY: 1
  CONFIG_NOT_SUPORRT_SASC: 1



4.3.2 安全方案

安全方案需要对分区进行验签,需要有TEE的系统。当然还需要有OTP或者eFuse来保证验签公钥的安全可靠性。


  • config.yaml分区配置表中partitions字段的配置
partitions:
  - { name: bmtb,   address: 0x8000000, size: 0x001000 }
  - { name: boot,   address: 0x8001000, size: 0x020000 }
  - { name: tee,    address: 0x8021000, load_addr: 0x18000000, size: 0x010000, verify: true }
  - { name: imtb,   address: 0x8031000, size: 0x002000 }
  - { name: prim,   address: 0x8033000, load_addr: 0x18010000, size: 0x300000, verify: true, update: FULL}
  - { name: kv,     address: 0x8633000, size: 0x004000 }
  - { name: lpm,    address: 0x8637000, size: 0x020000 }
  - { name: misc,   address: 0x8657000, size: 0x400000 }


跟非安全方案相比较,主要是多了TEE系统分区,然后对tee和prim分区进行验签配置。对需要验签的分区加上verify: true,打包工具会把这个字段保存到imtb表中,由bootloader去判断这个分区是否需要验签。


  • 应用方案的package.yaml文件
def_config:
  CONFIG_PARITION_NO_VERIFY: 0
  CONFIG_NOT_SUPORRT_SASC: 0


05 下期预告

PARTITION组件是一个轻量级的分区管理组件。用户可以根据宏进行灵活的配置,打开或者关闭某些功能。是一个适用于RTOS系统或者裸系统的功能组件。下期内容,我们将为大家介绍YoC的KV组件,欢迎大家持续关注RISC-V系列内容。



相关文章
|
5天前
|
缓存 安全 PHP
【PHP开发专栏】Symfony框架核心组件解析
【4月更文挑战第30天】本文介绍了Symfony框架,一个模块化且高性能的PHP框架,以其可扩展性和灵活性备受开发者青睐。文章分为三部分,首先概述了Symfony的历史、特点和版本。接着,详细解析了HttpFoundation(处理HTTP请求和响应)、Routing(映射HTTP请求到控制器)、DependencyInjection(管理依赖关系)、EventDispatcher(实现事件驱动编程)以及Security(处理安全和认证)等核心组件。
|
24天前
|
消息中间件 存储 运维
王者归位:Kafka控制器组件解析
王者归位:Kafka控制器组件解析
33 0
|
5天前
|
缓存 Java 开发者
10个点介绍SpringBoot3工作流程与核心组件源码解析
Spring Boot 是Java开发中100%会使用到的框架,开发者不仅要熟练使用,对其中的核心源码也要了解,正所谓知其然知其所以然,V 哥建议小伙伴们在学习的过程中,一定要去研读一下源码,这有助于你在开发中游刃有余。欢迎一起交流学习心得,一起成长。
|
9天前
|
存储 JavaScript 开发者
Vue3中的组件间通信:多种方法解析
【4月更文挑战第20天】
7 1
|
10天前
|
存储 前端开发 JavaScript
React的表单处理:受控组件与非受控组件深入解析
【4月更文挑战第25天】React表单处理涉及受控和非受控组件。受控组件通过状态管理表单数据,每次用户输入都触发状态更新,确保数据同步,适合实时交互但可能影响性能。非受控组件不直接管理状态,数据存储在DOM中,简化代码,适用于更新不频繁的场景,但在数据验证和同步上存在挑战。开发者应根据需求灵活选择。
|
26天前
|
Linux SDN 网络虚拟化
Linux虚拟网络设备全景解析:定义、工作模式与实践应用
在深入探索Linux操作系统的强大功能时,我们不可避免地会遇到虚拟网络设备的概念。这些设备扮演着构建和维护虚拟化环境中网络通信的关键角色。本文旨在详细介绍Linux虚拟网络设备的定义、工作模式以及它们的多样化用途。
Linux虚拟网络设备全景解析:定义、工作模式与实践应用
|
2月前
|
存储 安全 编译器
【Qt 底层之属性系统】Qt 属性系统全景:深入解析 Q_PROPERTY 宏的核心作用
【Qt 底层之属性系统】Qt 属性系统全景:深入解析 Q_PROPERTY 宏的核心作用
100 2
|
2月前
|
存储 安全 Linux
嵌入式Linux系统bringup 启动全景解析
嵌入式Linux系统bringup 启动全景解析
70 0
|
2月前
|
存储 传感器 网络协议
通信协议缓冲区管理全景:TCP、UDP、ZMQ、DBus、SSL、SOME/IP通讯协议的缓冲区解析...
通信协议缓冲区管理全景:TCP、UDP、ZMQ、DBus、SSL、SOME/IP通讯协议的缓冲区解析...
71 0
|
2月前
|
Web App开发 存储 网络协议
C/C++ 数据结构设计与应用(四):C++数据压缩与传输:从理论到实践的全景解析
C/C++ 数据结构设计与应用(四):C++数据压缩与传输:从理论到实践的全景解析
73 3

推荐镜像

更多