FLASH 分区管理

概述

partition(分区管理)是基于imtb(image mtb)里的分区信息来统一管理flash分区的接口。它能够统一管理flash分区信息,并对分区进行统一的读写以及擦除的操作。

分区定义

分区说明

分区信息保存在每个board组件的config中, 例如boards/pangu/config/config.yaml 该文件为文本格式可打开查看分区情况。

分区示例

mtb_version: 4
chip: yunvoice

diff:
  digest_type: SHA1
  signature_type: RSA1024
  fota_version: 0
  ram_buf: 50      #DEC     KB   ( max ram need)
  flash_buf: 8     #DEC     KB   ( buffer size)
  flash_sector: 4096 #DEC     byte ( flash sector)
  diff_mode: 010    #BIN
  double_control: 1
flash:
  base_address: 0
  run_base_address: 0x40000000 # base address of Storage
  sector: 4096       # Bytes
  size: 8388608      # $(sector count) * sector

partitions:
  - { name: boot,   address: 0x000000, load_addr: 0x20000, size: 0x01E000, verify: true }
  - { name: imtb,   address: 0x01E000, size: 0x001000 }
  - { name: ai,     address: 0x020000, size: 0x080000, load_addr: 0x40600000, update: DIFF, verify: true }
  - { name: prim,   address: 0x0A0000, size: 0x200000, load_addr: 0x40000000, update: DIFF, verify: true }
  - { name: kv,     address: 0x2A0000, size: 0x008000 }
  - { name: spiffs, address: 0x2A8000, size: 0x200000 }

一级字段说明

字段 说明
mtb_version mtb格式版本号
chip 芯片类型
diff 用于差分相关的配置参数
flash flash相关参数
partitions 分区表相关参数

diff字段说明

diff 是否必选 说明
ram_buf 差分还原时所需的ram空间,单位KB
flash_buf 差分还原时所需的flash空间,单位KB
flash_sector flash每个sector的尺寸,单位byte
diff_mode 差分模式,二进制字符串
double_control 是否使用双flash,此字段不填或者0:单片flash,1:双片flash
signature_type 签名算法
digest_type 摘要算法

diff_mode字段说明

mode_value verify auto_config
00 disable disable
01 disable enable
10 enable disable
11 enable enable

partitions字段说明

字段 是否必选 说明
name 分区名字,最长8个字节
address 分区起始地址
load_addr 分区加载地址,如果没有此字段,则默认使用address为加载地址
size 分区大小,单位byte
update 分区升级类型[DIFFFULL],默认值为DIFF;类似boot这种分区是不能升级的,因此不能填写此字段
verify 是否要对分区进行签名
file 指定分区对应的镜像文件名字,不填则表示文件名与分区名相同

常用分区说明

分区 说明
imtb 分区表,包含所有分区位置及安全信息
tee 安全执行镜像
boot bootloader
prim 应用镜像
misc 升级备份区
lpm 低功耗信息保存区
otp 只读分区,存放设备信息及安全密钥

imtb\tee\boot分区的调整会涉及tee镜像、boot镜像、otp安全数据的调整,不建议用户调整
prim\misc\kv 可以根据实际情况进行调整

安全引导流程

  • 上电BootRom验签bootloader,并跳转到bootloader
  • bootloader验签tee和prim分区,并跳转到tee
  • tee进行安全的初始化后,跳到prim执行用户应用

接口定义

相关数据结构

typedef int partition_t;

typedef struct {
    char     description[MTB_IMAGE_NAME_SIZE];  // 分区名字
    uint32_t base_addr;                         // Flash基地址
    uint32_t start_addr;                        // 分区的偏移地址(不是绝对地址)
    uint32_t length;                            // 分区大小
    uint32_t sector_size;                       // Flash sector大小
    uint8_t  idx;

    void    *flash_dev;

    uint32_t load_addr;                         // 加载地址,一般指在RAM中的运行地址
    uint32_t image_size;                        // 镜像实际大小
    scn_type_t type;
    uint16_t rsv;
} partition_info_t;

初始化分区管理

int partition_init(void);

初始化分区信息,从当前 IMTB 中读取分区信息,参考 分区定义

  • 参数: 无

  • 返回值:

    • 成功:>0
    • 失败:小于等于0

根据分区名字打开分区

partition_t partition_open(const char *name);

根据分区名字获取分区序列号

  • 参数:
    • name:分区名字
  • 返回值:
    • 分区管理的分区序列号:成功
    • <0:失败

根据分区序号关闭分区

void partition_close(partition_t partition);

根据分区序列号清除该分区信息

  • 参数:
    • partition:分区管理的分区序列号
  • 返回值: 无

获取分区详细信息

partition_info_t *partition_info_get(partition_t partition);
hal_flash_get_info(partition) partition_info_get(partition);

根据分区序列号获取该分区的详细信息。

  • 参数:
    • partition:分区管理的分区序列号
  • 返回值:
    • 0:成功
    • 非0:失败

按照分区读 flash

int partition_read(partition_t partition, off_t off_set, void *data, size_t size);

根据分区序列号读flash

  • 参数:
    • partition:分区管理的分区序列号
    • off_set:读取的分区起始地址
    • data:读取分区的数据指针
    • size:读取分区的数据量,单位byte
  • 返回值:
    • 0:成功
    • <0:失败

按照分区写flash

int partition_write(partition_t partition, off_t off_set, void *data, size_t size);

根据分区序列号写flash

  • 参数:
    • partition:分区管理的分区序列号
    • off_set:写入的分区起始地址
    • data:写入分区的数据指针
    • size:写入分区的数据量,单位byte
  • 返回值:
    • 0:成功
    • <0:失败

按照分区擦除flash信息

int partition_erase(partition_t partition, off_t off_set, uint32_t block_count );

根据分区序列号擦除flash信息

  • 参数:
    • partition:分区管理的分区序列号
    • off_set:擦除的分区起始地址
    • block_count:擦除的分区block数量
  • 返回值:
    • 0:成功
    • <0:失败

验证单个分区数据

int partition_verify(partition_t partition);
  • 参数:
    • partition:分区管理的分区序列号
  • 返回值:
    • 0:成功
    • <0:失败

验证分区数据

int partition_all_verify(void);
  • 参数:
  • 返回值:
    • 0:成功
    • <0:失败

获取目标分区的SHA摘要和类型

int partition_get_digest(partition_t partition, uint8_t *out_hash, uint32_t *out_len);
  • 参数:
    • partition:分区管理的分区序列号
    • out_hash:返回的SHA摘要
    • out_len:返回的SHA数据长度
  • 返回值:
    • 0:成功
    • <0:失败

设置安全分区

int partition_set_region_safe(partition_t partition);
  • 参数:
    • partition:分区管理的分区序列号
  • 返回值:
    • 0:成功
    • <0:失败

获取flash id

int get_flashid_by_abs_addr(unsigned long address);
  • 参数:
    • address:分区地址
  • 返回值:
    • flash id:成功
    • <0:失败

示例代码

分区信息接口

#ifndef YOC_PARTITION_H
#define YOC_PARTITION_H

#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>

#include <devices/device.h>

#ifndef MTB_IMAGE_NAME_SIZE
#define MTB_IMAGE_NAME_SIZE 8
#endif

#define MAX_FLASH_NUM   10

typedef int partition_t;

typedef struct {
    char     description[MTB_IMAGE_NAME_SIZE];
    uint32_t start_addr;
    uint32_t length;
    uint16_t sector_size;
    uint8_t  idx;

    dev_t   *g_eflash_dev;
} hal_logic_partition_t;
#endif

partition初始化

#include <yoc_init.h>
void board_base_init()
{
    flash_csky_register(0);
    partition_init();
}

partition接口对接kv api

#include <yoc_config.h>

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <devices/flash.h>
#include <yoc/partition.h>
#include <aos/debug.h>

#ifndef CONFIG_KVFS_EBLOCK_FOR_GC
#define CONFIG_KVFS_EBLOCK_FOR_GC 1
#endif

static int32_t     g_block_size;
static int32_t     g_kv_blk_cnt;
static partition_t g_eflash_part = -1;

ssize_t kvp_flash_read(int32_t bytesize, void *buff, int32_t off, int32_t blk_num)
{
    return partition_read(g_eflash_part, blk_num * g_block_size + off, buff, bytesize);
}

ssize_t kvp_flash_write(int32_t bytesize, void *buff, int32_t off, int32_t blk_num)
{
    return partition_write(g_eflash_part, blk_num * g_block_size + off, buff, bytesize);
}

ssize_t kvp_flash_erase(int32_t blk_num)
{
    return partition_erase(g_eflash_part, blk_num * g_block_size, 1);
}

extern int __kv_core_init(int eblock_num, int eblock_for_gc, int eblock_size);

int aos_kv_init(const char *partname)
{
    aos_check_return_einval(partname);

    g_eflash_part = partition_open(partname);

    if (g_eflash_part >= 0) {
        hal_logic_partition_t *lp = hal_flash_get_info(g_eflash_part);
        aos_assert(lp);

        g_block_size = lp->sector_size;
        g_kv_blk_cnt = lp->length / lp->sector_size;

        return __kv_core_init(g_kv_blk_cnt, CONFIG_KVFS_EBLOCK_FOR_GC, g_block_size);
    }

    return -1;
}

results matching ""

    No results matching ""