1 概述
编写目的: 介绍sunxi spinand 烧写时的数据布局
2 名词解释
词 义
ubi unsorted block image
peb physical erase block
leb logical erase block
peb 和logical block 关系
1 peb = 1 logical block
1 logical block = 2 physical blocks
3 总体数据布局
ubi 方案flash 上的数据布局
sys_partition.fex 文件中的各个分区大小会按照leb 大小对齐,sunxi_mbr 分区概念与ubi卷(volume)概念相同 需要修改原镜像文件:物理区toc0 合逻辑区sunxi_mbr.fex 需要动态生成文件:逻辑区ubi layout volume 注意:
各分区镜像以实际应用为准
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
参考文件
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
下表中红色字体不能配置错,大部分值直接参考drivers/mtd/awnand/spinand/physic/id.c
attribute name type value comment
chipcnt unsigned char 1
connectmode unsigned char 1 忽略,可以不用理解
bankcntperchip unsigned char 1 忽略,可以不用理解
diecntperchip unsigned char 1
planecntperdie unsigned char 2 忽略,可以不用理解
sectorcntperpage unsigned char 4 以具体物料为准, 常见为4
chipconnectinfo unsigned short 1 忽略,可以不用理解
pagecntperphyblk unsigned int 64 以具体物料为准, 常见为64
blkcntperdie unsigned int 1024 以具体物料为准, 常见为1024,也可能为512 或2048
operationopt unsigned int 0x? 参考id.c 各个物料配置
frequencepar unsigned int 100 忽略,可以不用理解
spimode unsigned int 0 忽略,可以不用理解
nandchipid[8] unsigned char 0x? 参考id.c 各个物料配置
pagewithbadflag unsigned int 0 忽略,可以不用理解
multiplaneblockoffset unsigned int 1 忽略,可以不用理解
maxerasetimes unsigned int 忽略,可以不用理解
ecclimitbits unsigned int 忽略,可以不用理解
uboot_start_block unsigned int 8
uboot_next_block unsigned int 40
logic_start_block unsigned int 40 忽略,可以不用理解
nand_specialinfo_page unsigned int 0 忽略,可以不用理解
nand_specialinfo_offset unsigned int 0 忽略,可以不用理解
physic_block_reserved unsigned int 0 忽略,可以不用理解
reserved[4] unsigned int 0 忽略,可以不用理解
以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,规则如下:
减去物理区域块数
减去坏块处理预留数(每1024 物理块最多20 个物理块,即10 个逻辑块)
减去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
计算mbr 卷最后分区size, 单位:扇区(512 字节),计算规则如下: 根据第5 章节计算出的用户可见leb 数转化出总的扇区数total_sector,依次减去分区表中各个 分区占用的扇区数
回填sunxi_mbr.fex 最后一个分区size
重新计算并回填sunxi_mbr 的crc32
改写其余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 name type value comment
reserved_pebs __be32 卷大小/leb size, 对于ubi layout volume,固定为2
alignment __be32 1
data_pad __be32 0
vol_type __u8 1 动态卷:1,静态卷:2,当前方案均是动态卷
upd_marker __u8 0
name_len __be16 卷名长度
name[128] char
flags __u8 分区内最后一个卷udisk,flags ubi_vtbl_autoresize_flg
padding[23] __u8 0
crc __be32 crc32_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 name type value comment
magic __be32 0x55424923 ubi#
version __u8 1
padding1[3] __u8 0
ec __be64 1
vid_hdr_offset __be32 physical page size 2048
data_offset __be32 logical page size 4096
image_seq __be32 0
padding2[32] __u8 0
hdr_crc __be32 crc32_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;
ubi_vid_hdr 的填充方法请参考u-boot-2018/cmd/ubi_simu.c 的fill_vid_hdr 函数。
11 数据对齐
有数据对齐需求时,不能填充0xff 数据,可选择填充全0版
英国陆军订购哈里斯T7拆弹机器人
区块链在供应链物流中的影响
防爆烟温复合探测器的特点和工作原理是怎样的
iphone8什么时候上市?iphone8最新消息:iphone8产能不足,网友大呼:我选三星note8!
垃圾代码应该怎么写
SPINAND UBI离线烧录开发指南
两款三星手机正在做HTML5的基准测试
关于骨传导耳机和气传导耳机的区别,你可能还不知道!
基于嵌入式Internet技术实现网络打印服务器系统的软硬件设计
苹果十周年:中国特供姨妈红iPhone7?据说5.8寸大屏iPhone8才是大招!
腾冲:智慧灯光照亮文明之路
TD-SCDMA规划的特点
这么牛的氧化皮去除机 不是亲眼见到都不敢相信
固定资产案例分享
SMT模板是怎样的一回事
晶体管和电子管的区别
反向放大电路设计
降压型DC-DC开关调节器驱动PA方案
等离子显示器输入接口简介
无人驾驶就等于把人装在电脑里?