SPINAND UBI 离线烧录 开发指南

news2025/1/16 0:51:58

SPINAND UBI 离线烧录 开发指南

1 概述

编写目的: 介绍Sunxi SPINand 烧写时的数据布局

2 名词解释

UBIunsorted block image
PEBphysical erase block
LEBlogical erase block

PEB 和logical block 关系

1 PEB = 1 logical block
1 logical block = 2 physical blocks

3 总体数据布局

ubi 方案FLASH 上的数据布局

image-20221219104342487

image-20221219104355889

image-20221219104405073

sys_partition.fex 文件中的各个分区大小会按照LEB 大小对齐,sunxi_mbr 分区概念与UBI卷(volume)概念相同
需要修改原镜像文件:物理区TOC0 合逻辑区sunxi_mbr.fex
需要动态生成文件:逻辑区ubi layout volume
注意:

  1. 各分区镜像以实际应用为准
  2. logical page0 = logical block 的两个page0

4 toc0 or boot0

4.1 input file

boot0_nand.fex(非安)or toc0.fex(安全)

4.2 flow

• 验证checksum 是否准确
• 填充storage_data
• 重新生成checksum 并更新boot_file_head_t 中的check_sum

image-20221219104440259

image-20221219104449232

参考文件
include/private_boot0.h
sprite/sprite_download.c
参考函数
download_normal_boot0
download_secure_boot0

4.3 normal boot0

normal boot0 存放于block4-7
参考function: download_normal_boot0

typedef struct _boot0_file_head_t
{
boot_file_head_t boot_head;
boot0_private_head_t prvt_head;
char hash[64];
__u8 reserved[8];
union {
#ifdef CFG_SUNXI_SELECT_DRAM_PARA
boot_extend_head_t extd_head;
#endif
fes_aide_info_t fes1_res_addr;
} fes_union_addr;
}boot0_file_head_t;
/******************************************************************************/
/* file head of Boot0 */
/******************************************************************************/
typedef struct _boot0_private_head_t
{
>-------__u32 prvt_head_size;
>-------/*debug_mode = 0 : do not print any message,debug_mode = 1 ,print debug message*/
>-------__u8 debug_mode;
>-------/*0:axp, 1: no axp */
>-------__u8 power_mode;
>-------__u8 reserve[2];
>-------/*DRAM patameters for initialising dram. Original values is arbitrary*/
>-------unsigned int dram_para[32];
>-------/*uart: num & uart pin*/
>-------__s32>-->------->------->------->------->-------uart_port;
>-------normal_gpio_cfg uart_ctrl[2];
>-------/* jtag: 1 : enable, 0 : disable */
>-------__s32 enable_jtag;
normal_gpio_cfg>---- jtag_gpio[5];
>-------/* nand/mmc pin*/
normal_gpio_cfg storage_gpio[32];
>-------/*reserve data*/
char storage_data[512 - sizeof(normal_gpio_cfg) * 32];
}boot0_private_head_t;

4.4 secure boot0

secure boot0 存放于boot0-block3

typedef struct sbrom_toc0_config
{
unsigned char config_vsn[4];
unsigned int dram_para[32]; // dram参数
int uart_port; // UART控制器编号
normal_gpio_cfg uart_ctrl[2]; // UART控制器GPIO
int enable_jtag; // JTAG使能
normal_gpio_cfg jtag_gpio[5]; // JTAG控制器GPIO
normal_gpio_cfg storage_gpio[50]; // 存储设备GPIO信息
// 0-23放nand,24-31存放卡0,32-39放卡2
// 40-49存放spi
char storage_data[384]; // 0-159,存储nand信息;160-255,存放卡信息
unsigned int secure_dram_mbytes; //
unsigned int drm_start_mbytes; //
unsigned int drm_size_mbytes; //
unsigned int boot_cpu; //
special_gpio_cfg a15_power_gpio; //the gpio config is to a15 extern power enable
gpio
unsigned int next_exe_pa;
unsigned int secure_without_OS; //secure boot without semelis
unsigned char debug_mode; //1:turn on printf; 0 :turn off printf
unsigned char power_mode; /* 0:axp , 1: dummy pmu */
unsigned char rotpk_flag;
unsigned char reserver[1];
unsigned int card_work_mode;
unsigned int res[2]; // 总共1024字节
}
sbrom_toc0_config_t;

4.5 filling storage_data

image-20221219104521069

下表中红色字体不能配置错,大部分值直接参考drivers/mtd/awnand/spinand/physic/id.c

attribute nametypevaluecomment
ChipCntunsigned char1
ConnectModeunsigned char1忽略,可以不用理解
BankCntPerChipunsigned char1忽略,可以不用理解
DieCntPerChipunsigned char1
PlaneCntPerDieunsigned char2忽略,可以不用理解
SectorCntPerPageunsigned char4以具体物料为准, 常见为4
ChipConnectInfounsigned short1忽略,可以不用理解
PageCntPerPhyBlkunsigned int64以具体物料为准, 常见为64
BlkCntPerDieunsigned int1024以具体物料为准, 常见为1024,也可能为512 或2048
OperationOptunsigned int0x?参考id.c 各个物料配置
FrequenceParunsigned int100忽略,可以不用理解
SpiModeunsigned int0忽略,可以不用理解
NandChipId[8]unsigned char0x?参考id.c 各个物料配置
pagewithbadflagunsigned int0忽略,可以不用理解
MultiPlaneBlockOffsetunsigned int1忽略,可以不用理解
MaxEraseTimesunsigned int忽略,可以不用理解
EccLimitBitsunsigned int忽略,可以不用理解
uboot_start_blockunsigned int8
uboot_next_blockunsigned int40
logic_start_blockunsigned int40忽略,可以不用理解
nand_specialinfo_pageunsigned int0忽略,可以不用理解
nand_specialinfo_offsetunsigned int0忽略,可以不用理解
physic_block_reservedunsigned int0忽略,可以不用理解
Reserved[4]unsigned int0忽略,可以不用理解

以GigaDevice GD5F1GQ4UBYIG spinand 为例,其大部分信息直接来自id.c

{
.Model = "GD5F1GQ4UBYIG",
.NandID = {0xc8, 0xd1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
.DieCntPerChip = 1,
.SectCntPerPage = 4,
.PageCntPerBlk = 64,
.BlkCntPerDie = 1024,
.OobSizePerPage = 64,
.OperationOpt = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
SPINAND_DUAL_READ,
.MaxEraseTimes = 50000,
.EccFlag = HAS_EXT_ECC_SE01,
.EccType = BIT4_LIMIT5_TO_7_ERR8_LIMIT_12,
.EccProtectedType = SIZE16_OFF4_LEN8_OFF4,
.BadBlockFlag = BAD_BLK_FLAG_FRIST_1_PAGE,
},
参考文件:
include/linux/mtd/aw-spinand.h /定义id.c 中id 表的数据结构/
drivers/mtd/awnand/spinand/sunxi-spinand.h /定义boot_spinand_para_t 填充的数据结构/
drivers/mtd/awnand/spinand/sunxi-driver.c /填充函数参考/
drivers/mtd/awnand/spinand/physic/id.c /不同物料的信息配置(id 表配置)/
参考函数:
ubi_nand_get_flash_info–>spinand_mtd_get_flash_info

4.6 update checksum

参考文件:
sprite/sprite_download.c
sprite/sprite_verify.c
board/sunxi/board_common.c
参考函数流程:
download_normal_boot0/download_secure_boot0 -> sunxi_sprite_generate_checksum
-> sunxi_generate_checksum

4.7 burn boot0

• 参考文件:
drivers/mtd/awnand/spinand/sunxi-driver.c
参考函数流程:
spinand_mtd_download_boot0()

注意事项:
如果是安全方案,存放boot0 的blocks 中一半存放secure boot0,一半存放normal
boot0, 参考UBI 方案分区表信息以及第2 章节说明

各个备份按block 对齐(如果boot0 超过1 个block, 单个备份起始block 地址为偶数), 若写单个备份过程中遇到坏块,则中止当前备份写过程,写下一备份即可boot0 的镜像文件已经包含了boot0 header,不需额外分配组织boot0 header 格式,只需更新boot0 header 中的storage_data 部分,其他属性(比如dram_para)不需更新。更新后,需重新生成boot0 header 中的校验和check_sum

5 toc1 or uboot

区域:block8-block31
直接烧写toc1 镜像
参考文件:

sprite/sprite_download.c
drivers/sunxi_flash/nand.c
drivers/sunxi_flash/nand_for_ubi.c
drivers/mtd/awnand/spinand/sunxi-driver.c

参考函数:

sunxi_sprite_download_uboot–>sunxi_sprite_download_toc–sunxi_flash_nand_download_toc–>
ubi_nand_download_uboot–>spinand_mtd_download_uboot

6 secure storage block

区域:block32-block39
烧录器不用处理

7 计算逻辑区域LEB 总数

用户可见LEB 数= 总物理块数- 8 (boot0) - 24 (boot1) - 8 (secure storage) - 20* 总物理块
数/1024 - 4,规则如下:

  1. 减去物理区域块数
  2. 减去坏块处理预留数(每1024 物理块最多20 个物理块,即10 个逻辑块)
  3. 减去4(2 个用于ubi layout volume,1 个用于LEB 原子写,1 个用于磨损均衡处理)推算方式可以参考u-boot-2018/cmd/ubi_simu.c 的ubi_sim_part 和ubi_simu_create_vol函数。
    正常情况下,ubi 方案sys_partition.fex 中各个分区的大小会按照LEB 大小对齐。假如一款flash 有1024 个block, 每个block 有64 个page, 每个page 有2KB,则逻辑块大小为256K(642K2), 那么PEB 大小是256K,LEB 大小为252K, PEB 中的首逻辑页固定用于
    存放ubi_ec_hdr 和ubi_vid_hdr。
    由于预先不知道物料的容量信息及预留块信息,因此sys_partition.fex(sunxi_mbr.fex)中最后一个分区的size 信息默认先填0,待NAND 驱动初始化完成后才知道用户可见LEB 数有多少个,此时需要根据信息改写sunxi_mbr.fex 中最后一个分区的size。

8 动态调整sunxi_mbr 卷

sunxi_mbr.fex 共64k, 共4 个备份,每个备份16K

  1. 计算mbr 卷最后分区size, 单位:扇区(512 字节),计算规则如下:
    根据第5 章节计算出的用户可见leb 数转化出总的扇区数total_sector,依次减去分区表中各个
    分区占用的扇区数
  2. 回填sunxi_mbr.fex 最后一个分区size
  3. 重新计算并回填sunxi_mbr 的crc32
  4. 改写其余3 个备份
sunxi_mbr_t 结构体:u-boot-2018/include/sunxi_mbr.h,结构体各个成员均使用小端存储。
typedef struct sunxi_mbr
{
unsigned int crc32;
unsigned int version;
unsigned char magic[8];
unsigned int copy;
unsigned int index;
unsigned int PartCount;
unsigned int stamp[1];
sunxi_partition array[SUNXI_MBR_MAX_PART_COUNT];
unsigned int lockflag;
unsigned char res[SUNXI_MBR_RESERVED];
}attribute ((packed)) sunxi_mbr_t;

重新计算并回填sunxi_mbr crc32 的代码请参考u-boot-2018/drivers/mtd/aw-spinand/sunxiubi.
c 的adjust_sunxi_mbr 函数。

9 根据sunxi_mbr 动态生成ubi layout volume

ubi layout volume 可以理解为UBI 模块内部用的分区信息文件,sunxi_mbr 分区是用于全志烧写framework 的分区信息文件。二者记录的分区信息本质上是一样的,因此烧写时, 可以由sunxi_mbr 卷转化成ubi layout volume。
ubi layout volume 由128 个struct ubi_vtbl_record(u-boot-2018/drivers/mtd/ubi/ubimedia.h)组成, 结构体各个成员使用大端表示。

struct ubi_vtbl_record {
__be32 reserved_pebs;
__be32 alignment;
__be32 data_pad;
__u8 vol_type;
__u8 upd_marker;
__be16 name_len;
char name[UBI_VOL_NAME_MAX+1];
__u8 flags;
__u8 padding[23];
__be32 crc;
} __packed;
attribute nametypevaluecomment
reserved_pebs__be32卷大小/LEB size, 对于ubi layout volume,固定为2
alignment__be321
data_pad__be320
vol_type__u81动态卷:1,静态卷:2,当前方案均是动态卷
upd_marker__u80
name_len__be16卷名长度
name[128]char
flags__u8分区内最后一个卷udisk,flags UBI_VTBL_AUTORESIZE_FLG
padding[23]__u80
crc__be32crc32_le

ubi layout volume 的内容填充及烧写方法请参考u-boot-2018/cmd/ubi_simu.c 的ubi_simu_create_vol 和wr_vol_table 函数
注意ubi 中crc32_le 算法与sunxi_mbr 的crc32 算法不一样。
ubi 中crc32_le 参考crc32_le.c 用法sunxi_mbr 中crc32 参考crc32.c 用法

10 烧写逻辑卷

PEB = ubi_ec_hdr + ubi_vid_hdr + LEB
其中ubi_ec_hdr 和ubi_vid_hdr 存放于PEB 的首逻辑页(logical page0)。

ubi_ec_hdr 存放于0 字节偏移处,大小与物理页size 对齐
ubi_vid_hdr 存放于1 个物理页size 偏移处,大小也与物理页size 对齐

10.1 ubi_ec_hdr

ubi_ec_hdr:主要用于存储PEB 的擦除次数信息,需动态生成crc32_le 校验值。
struct ubi_ec_hdr 位于u-boot-2018/drivers/mtd/ubi/ubi-media.h,结构体各个成员使用大端表示。

struct ubi_ec_hdr {
__be32 magic;
__u8 version;
__u8 padding1[3];
__be64 ec; /* Warning: the current limit is 31-bit anyway! */
__be32 vid_hdr_offset;
__be32 data_offset;
__be32 image_seq;
__u8 padding2[32];
__be32 hdr_crc;
} __packed;
attribute nametypevaluecomment
magic__be320x55424923UBI#
version__u81
padding1[3]__u80
ec__be641
vid_hdr_offset__be32physical page size2048
data_offset__be32logical page size4096
image_seq__be320
padding2[32]__u80
hdr_crc__be32crc32_le

ubi_ec_hdr 的填充方法请参考u-boot-2018/cmd/ubi_simu.c 的fill_ec_hdr 函数。

10.2 ubi_vid_hdr

ubi_vid_hdr:存放PEB 和LEB&Volume 映射信息,需动态生成crc32_le 校验值
struct ubi_vid_hdr 位于u-boot-2018/drivers/mtd/ubi/ubi-media.h,结构体各个成员使用大端表示。

struct ubi_vid_hdr {
__be32 magic;
__u8 version;
__u8 vol_type;
__u8 copy_flag;
__u8 compat;
__be32 vol_id;
__be32 lnum;
__u8 padding1[4];
__be32 data_size;
__be32 used_ebs;
__be32 data_pad;
__be32 data_crc;
__u8 padding2[4];
__be64 sqnum;
__u8 padding3[12];
__be32 hdr_crc;
} __packed;

image-20221219104521069

ubi_vid_hdr 的填充方法请参考u-boot-2018/cmd/ubi_simu.c 的fill_vid_hdr 函数。

11 数据对齐

有数据对齐需求时,不能填充0xff 数据,可选择填充全0版

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/365372.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React从入门到精通二

React从入门到精通之购物车案例1. 购物车需求说明使用到的data list2. 项目code1. 购物车需求说明 list data展示到列表中每个item的通过按钮来控制购买的数据量删除按钮可以删除当前的itemTotal Price计算当前购物车的总的价格 使用到的data list const books [{id: 1,name…

OAK相机深度流探测草莓距离

编辑:OAK中国 首发:oakchina.cn 喜欢的话,请多多👍⭐️✍ 内容可能会不定期更新,官网内容都是最新的,请查看首发地址链接。 ▌前言 Hello,大家好,这里是OAK中国,我是助手…

uniapp 悬浮窗(悬浮球、动态菜单、在其他应用上层显示) Ba-FloatBall

简介(下载地址) Ba-FloatBall 是一款在其他应用上层显示的悬浮球插件。支持展示菜单、拖动、自动贴边等;支持自定义样式。 支持添加展示菜单,可自定义(不添加菜单,可只显示悬浮球)支持自定义悬…

一口吃不成ChatGPT,复旦版MOSS服务器被挤崩后续

ChatGPT 是目前最先进的 AI,由于 ChatGPT 的训练过程所需算力资源大、标注成本高,此前国内暂未出现对大众开放的同类产品。 适逢ChatGPT概念正火,2 月 21 日,复旦团队发布首个中国版类 ChatGPT 模型「MOSS」,没想到瞬时…

Python-生成列表

1.生成列表使用列表前必须先生成列表。1.1使用运算符[ ]生成列表在运算符[ ]中以逗号隔开各个元素会生成包含这些元素的新列表。另外,如果[ ]中没有元素就会生成空列表示例>>> list01 [] >>> list01 [] >>> list02 [1, 2, 3] >>…

云、安全、网络三位一体,Akamai 推出大规模分布式边缘和云平台 Akamai Connected Cloud

出品 | CSDN 云计算 云服务市场规模在持续增长。 基于网络技术积累与优势,与布局边缘计算之后,巨头 Akamai 在继续推进它的技术与产品进程。近日,Akamai 正式推出大规模分布式边缘和云平台 Akamai Connected Cloud,包含云计算、安…

软考学习笔记(题目知识记录)

答案为 概要设计阶段 本题涉及软件工程的概念 软件工程的任务是基于需求分析的结果建立各种设计模型,给出问题的解决方案 软件设计可以分为两个阶段: 概要设计阶段和详细设计阶段 结构化设计方法中,概要设计阶段进行软件体系结构的设计&…

学生管理系统-课后程序(JAVA基础案例教程-黑马程序员编著-第六章-课后作业)

【案例6-2】 学生管理系统 【案例介绍】 1.任务描述 在一所学校中,对学生人员流动的管理是很麻烦的,本案例要求编写一个学生管理系统,实现对学生信息的添加、删除、修改和查询功能。每个功能的具体要求如下: 系统的首页&#…

视频技术基础知识

一、视频图像基础 像素:图像的基本单元,即一个带有颜色的小块分辨率:图像的大小或尺寸,用像素个数来表示。原始图像分辨率越高,图像就越清晰位深:存储每位像素需要的二进制位数;位深越大&#…

JAVA线程入门简介

线程入门简介什么是程序?什么是进程?什么是线程?单线程与多线程并发与并行线程的使用用java查看有多少个cpu创建线程的两种方式继承Thread类,重写run方法实现Runnable接口,重写run方法多线程机制为社么是start?源码解析什么是程序? 是为完…

防错料使用二维码解决方案 生产过程物料防错管理

生产过程中,物料的防错管理是非常重要的一环。它能够有效地防止物料错用或混用,从而降低产品质量问题的发生率,减少生产成本和生产周期,提高生产效率和产品质量。以下是生产过程物料防错管理的具体措施:1.明确物料标识…

SpringBoot Data Redis来操作Redis

SpringBoot Data Redis来操作Redis1、Redis启动Redis主要的作用安装的位置启动2、Java中来操作Redis3、Spring Data Redis(重点)测试连接配置Redis序列化器redisTemplate操作常见数据类型通用操作,针对不同的数据类型都可以操作申明: 未经许可&#xff0…

浅谈Springboot自动化配置原理

文章目录1.前言2.SpringBoot的入口3.SpringBootApplication背后的秘密4.Configuration5.ComponentScan扫描bean6.EnableAutoConfiguration7.自动配置生效1.前言 不论在工作中,亦或是求职面试,Spring Boot已经成为我们必知必会的技能项。除了某些老旧的政…

java面试题-JUC线程池

1.FutureTask的作用?FutureTask 是 Java 并发编程中的一个类,用于异步执行任务并获取其结果。它实现了 Future 和 Runnable 接口,因此可以作为一个可运行的任务提交给 Executor 执行,也可以通过 Future 接口获取任务执行的结果。FutureTask …

2023年DAMA-CDGA/CDGP数据治理认证选择哪家机构好?

DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义,帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力,促进开展工作实践应用及实际问题解决,形成企业所需的新数字经济下的核心职业…

将整数数组变为浮点型数组的np.asfarray()方法

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 将整数数组转换为浮点型数组 np.asfarray() 选择题 关于以下代码说法错误的一项是? import numpy as np a1 np.array([1,2,3]) print("【显示】a1",a1) print("【执行】a…

网络工程(一) 简单的配置

网络工程 简单的配置 需求 两台交换机 两台路由器 两台PC AR1配置静态路由 system-view [HUAWEI]sysname ar1 [ar1]interface g 0/0/0 [ar1-G…0/0/0]ip address 192.168.2.1 24 [ar1-G…0/0/0]quit [ar1]interface g 0/0/1 [ar1-G…0/0/1]ip address 192.168.3.1 24 [ar1-G…

关于学习git时的一些疑惑与笔记

关于学习git时的一些疑惑与笔记SSH相关问题SSH是什么?SSH有什么作用?如何在github配置SSH?分支什么是本地分支,远程分支?main主分支与master主支?为什么要把master分支修改为main分支?什么时候用分支&…

Java线程——常见方法

一、 常见方法 1.1 概述 ① start_vs_run:直接调用run方法并不会启动新的线程 import cn.itcast.n2.util.FileReader; import lombok.extern.slf4j.Slf4j;Slf4j(topic "c.Test") public class Test {public static void main(String[] args) {Thread t…

【网络安全】Windows系统安全实验

第3模块 Windows操作系统安全部分 3.1 帐户和口令的安全设置 3.1.1 实验目的 本章实验的目的主要是熟悉Windows操作系统中帐户和口令的安全设置,掌握删除、禁用帐户的方法,了解并启用密码策略和用户锁定策略,体验查看“用户权限分配”、…