Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

应用镜像格式与签名

WS63 app 镜像(flashboot 从 flash 0x230000 加载的对象)的字段布局。事实逐字段取自 hisi-fwpkg/crates/hisi-fwpkg/src/image.rssrc/fwpkg.rs。所有多字节字段为小端

构建命令见 打包成可启动镜像;安全启动原理见 安全启动与签名

整体布局

+--------------------------------------+ 0x000
| image_key_area_t   (0x100 字节)      |  magic = 0x4B0F2D1E
+--------------------------------------+ 0x100
| image_code_info_t  (0x200 字节)      |  magic = 0x4B0F2D2D
+--------------------------------------+ 0x300  = APP_IMAGE_HEADER_LEN
| code body(原始 .text/.rodata/...)  |  链接到 0x230300 运行
+--------------------------------------+

0x300 字节前缀为定长镜像头。secure boot 关闭(efuse SEC_VERIFY_ENABLE == 0)时,flashboot 的 verify_image_* 在检查任何签名/body hash 之前短路成功,故签名字段从不被读。关键只有两点:头恰好 0x300 字节、其后是链接到 0x230300 的真实代码。

常量

常量
APP_KEY_AREA_IMAGE_ID0x4B0F_2D1E
APP_CODE_INFO_IMAGE_ID0x4B0F_2D2D
KEY_AREA_LEN0x100
CODE_INFO_LEN0x200
IMAGE_HEADER_LEN0x300
STRUCTURE_VERSION0x0001_0000
SIG_LENBOOT_SIG_LEN0x40
KEY_ALG_ECC2560x2A13_C812(ECC256 / brainpoolP256r1)
ECC_CURVE_BP256R10x2A13_C812
PUB_KEY_LENBOOT_PUBLIC_KEY_LEN0x40
FLASH_NO_ENCRY_FLAG0x3C78_96E1
HASH_LEN32(SHA-256)

密钥区 image_key_area_t(偏移 0x000,长度 0x100)

偏移字段默认值
0x00image_id(magic)0x4B0F_2D1E
0x04structure_version0x0001_0000
0x08structure_length0x100
0x0Csignature_length0x40
0x10key_owner_id1(默认)
0x14key_id1(默认)
0x18key_alg0x2A13_C812
0x1Cecc_curve_type0x2A13_C812
0x20key_length0x40
0x24key_version_ext0(disabled 板)
0x28mask_key_version_ext0
0x2Cmsid_ext0
0x30mask_msid_ext0
0x34maintenance_mode0(关闭)
0x38..0x48die_id[16]dummy 0(仅维护模式检查)
0x48code_info_addr0(紧随其后)
ext_public_key_area[0x40]sig_key_area[0x40]dummy 0(ECC 签名/公钥 blob)

代码信息区 image_code_info_t(偏移 0x100,长度 0x200;下表偏移相对区起点)

偏移字段默认值
0x00image_id(magic)0x4B0F_2D2D
0x04structure_version0x0001_0000
0x08structure_length0x200
0x0Csignature_length0x40
0x10version_ext0
0x14mask_version_ext0
0x18msid_ext0
0x1Cmask_msid_ext0
0x20code_area_addr0(紧随头之后)
0x24code_area_lenbody.len()
0x28..0x48code_area_hash[32]body 的真实 SHA-256
0x48code_enc_flag0x3C78_96E1FLASH_NO_ENCRY_FLAG,未加密)
0x4C..0x5Cprotection_key_l1[16]0(加密关闭)
0x5C..0x6Cprotection_key_l2[16]0
0x6C..0x7Civ[16]0
0x7Ccode_compress_flag0(未压缩)
0x80code_uncompress_len= code_area_len
0x84text_segment_size0x0001_0000(默认,仅信息)
sig_code_info[0x40] + sig_code_info_ext[0x40]dummy 0

code_area_hash(区内偏移 0x28,即镜像绝对偏移 0x128)是 body 的真实 SHA-256,与厂商 sign_tool 一致。

code_enc_flag(区内 0x48,绝对 0x148)= 0x3C7896E1 是非零哨兵:flashboot ws63_flash_encrypt_config()if (code_enc_flag == FLASH_NO_ENCRY_FLAG) return;,故零值反而会令 flashboot 尝试配置 on-the-fly 解密而启动失败。明文镜像必须用此值。

dummy-zero 字段:两个区的 ECC 签名 blob(sig_key_areasig_code_infosig_code_info_ext)与公钥(ext_public_key_areadie_id、protection key、iv)。

fwpkg V1 容器(fwpkg.rs

“all-in-one” 固件包:小头 + 每分区描述符表 + 串接的分区负载。布局是 hisiflash 解析器的逆,匹配厂商 packet_create.py create_allinone()

+----------------------------------+ 0x000
| FWPKG_HEAD (12 字节)             |  flag(4) crc(2) cnt(2) total_len(4)
+----------------------------------+ 0x00C
| IMAGE_INFO[0] (52 字节)          |  name[32] off(4) len(4) burn_addr(4)
| IMAGE_INFO[1] ...                |           burn_size(4) type(4)
+----------------------------------+
| payload[0] || 16 个 0 字节       |
| payload[1] || 16 个 0 字节       |
+----------------------------------+

常量

常量
FWPKG_MAGIC_V1flag0xEFBE_ADDF
HEADER_SIZEFWPKG_HEAD12
BIN_INFO_SIZEIMAGE_INFO52
NAME_SIZE(名字字段宽)32(名字须 < 32 字节)
PAYLOAD_SEPARATOR16(每负载后补的 0 字节数)

FWPKG_HEAD(12 字节)

偏移字段大小
0x00flag(magic)40xEFBE_ADDF
0x04crc2CRC16/XMODEM
0x06cnt(分区数)2parts.len()
0x08total_len4头 + 全部负载 + 全部分隔

IMAGE_INFO(每分区 52 字节)

偏移字段大小
0x00name[32]32
0x20offset4
0x24length(负载字节数,不含 16 字节分隔)4
0x28burn_addr4
0x2Cburn_size4
0x30type4

分区 type

类型说明
Loader0LoaderBoot(一级加载器)
Normal1ssb / flashboot / nv / params / app …
KvNv2Key-Value NV
Efuse3eFuse 配置
Other(v)v其它原始类型码

CRC

crc = CRC16/XMODEM(poly 0x1021,init 0x0000),覆盖范围为从偏移 6(cnt 字段)到描述符表末尾的字节(即 out[6..head_len]head_len = 12 + cnt*52)。已知向量:crc16_xmodem("123456789") == 0x31C3

每个负载后跟 16 个 0 字节分隔,计入 total_len不计入描述符 length