X5 eFuse 介绍

以下关于开启secure boot要烧写secure bank13-20,non secure bank10的bit0的介绍,仅针对地瓜key对BL2加密签名芯片,如果客户key签名BL2的芯片(X5 Customer root rsa key hash烧录使用),可以忽略对应部分

概述

eFuse(电子熔丝)是一种可编程非易失性存储技术,广泛用于各种硬件平台上,如微控制器( MCU)、处理器、嵌入式设备、 SoC(系统芯片)等。 eFuse 通过电子方式进行编程,能够存储保护敏感信息,且具有编程不可更改特性。

eFuse 通常用于存储设备安全密钥、配置参数、设备标识符、校准数据重要信息。

X5 eFuse 特性

X5 eFuse 分为 secure bank 和 non-secure bank,每个 region 有 32 个 bank,每个 bank 是 32bit,即每个 region 有 128Byte。其布局如下

efuse_banks

支持特性如下

  • eFuse 比特默认为 0,可以从 0 写为 1 ,但不能从 1 写为 0 (eFuse 硬件特性)

  • 用户烧写区域

区域 bank 用途 备注
secure 13 - 20 公钥hash 对应文件 bl2_rot_prikey.pem 使用客户的 key 签名 BL2,这些 bank 由客户自由定义
考虑安全问题,这些 bank 写过数据为0后,不论是否 lock,都允许再次写入
secure 25 - 28 用户的 user root aes key
non-secure 10 配置开启 secure boot 和 关闭 JTAG 使用客户的 key 签名 BL2,bit0 由客户自由定义
non-secure 11 - 13 用户定义数据 没有 lock 的情况下,这些 bank 中未更新为1的 bit,仍然可以继续更新
  • 特殊 bank 说明

    • secure 和 non-secure region 的 bank0 的每个 bit 表示对应的 bank 是否被 lock, 1 表示 lock, 0 表示没有 lock.

    • non-secure bank10 用于设置 secure boot 和 JTAG 使能开关,其定义如下

比特 功能描述 定义 默认值
bit0 enable secure boot 0 : 关闭 secure boot
1 : 开启 secure boot
0
bit1 disable debug port 0 : 开启 JTAG
1 : 关闭 JTAG
0

eFuse 的烧录(读写),可通过以下三个阶段:

BL2 烧录 eFuse

eFuse 配置文件

eFuse 的配置信息位于 BL2 CFG 文件中,文件路径device/horizon/x5/board_cfg/soc/bl2_cfg/bl2_cfg.json

内容如下所示:

{
    "bl2_cfg": {
        ...
      },
      "efuse_cfg": {
        "bypass": 1,
        "secure_boot": "false",
        "debug_disable": "false",
        "burn_user_rot_key": "false",
        ...
      },
	   "nonsecure_bank": {
            "bank11":["0x0"],
            "bank12":["0x0"],
            "bank13":["0x0"]
        },
}

参数说明

  • bypass: bl2 是否烧录 eFuse

    • 1 : 表示 bypass

    • 0 : 表示 bl2 将烧录 eFuse

  • secure_boot: 是否开启 secure boot,对应 eFuse 的 non-secure bank10 bit0

    • false : 表示开启 secure boot

    • true : 表示开启 secure boot,开启将 Uboot 公钥的 hash 烧写到 eFuse secure region bank13~20

  • debug_disable: 是否禁止 debug port,对应 eFuse 的 non-secure bank10 bit1

    • false : 表示开启 debug port

    • true : 表示禁止 debug port

  • burn_user_rot_key: 是否烧写 user root aes key。对应的 key 文件位于 device/horizon/x5/board_cfg/soc/bl2_cfg/user_root.key,同时注意为小端格式

  • nonsecure_bank: 要烧写的 non-secure bank11/12/13 的

注意:

  • 烧写 eFuse 之后,相应的 bank 都被 lock

  • BL2 CFG 会打包镜像中,如果烧录 user root aes key,直接将 key 保存外部 storage,如 eMMC 中安全,推荐使用以下方法:

    • 在 Linux 下调用接口形式更新 key

    • 通过 UART/USB 形式下载 miniboot 更新 key,路径位于 out/product/uart_usb,并妥善保存文件夹。

eFuse 电源控制烧录状态

eFuse 烧录状态

BL2 可以通过一个 GPIO 指示烧录成功失败状态。如烧写成功拉高该 GPIO,烧写失败保持低,在硬件通过外接 LED 用于显示 eFuse 烧录状态。

device/horizon/x5/board_cfg/soc/bl2_cfg/bl2_cfg.json 为例,通过 efuse_cfg 配置 :

{
    "bl2_cfg": {
        ...
      },
      "efuse_cfg": {
        "bypass": 1,
        "secure_boot": "false",
        "debug_disable": "false",
        "burn_user_rot_key": "false",
        "status_gpio" : {
            "gpio_sub": "none",
            "gpio_group": 0,
            "gpio_num": 0
        },
        "delay_before_efuse": 0,
        "delay_after_efuse": 0
      },
        ...
}
  • status_gpio表示用于指示 eFuse 烧写状态的 GPIO 信息,其配置参数如下

    • gpio_sub: 表示 GPIO 所在的 subsystem,包括 aonhsiolsiodsp

    • gpio_group: 表示 GPIO 的 group

    • gpio_num: 表示 GPIO 号

    • polarity:可参数,表示 GPIO 的默认值, default_low 默认低, default_high 默认高,该字时,选择为 default_low

  • delay_before_efuse: 烧写操作 power_gpio真正烧写 eFuse 的延迟时间,单位 ms,目的为了保证烧写之前 eFuse 电源稳定

    • 默认配置为 0 时,延迟时间为 1s

    • 这个时间只有真正烧写 eFuse 时才作用。例如产线烧录固件第一次启动, BL2 将要烧录 eFuse,此时延时时间作用,之后再次启动由于不会重复烧写 eFuse,因此这个延时时间失效

  • delay_after_efuse: 表示烧写完成之后动作,其定义如下

delay_after_efuse 烧写完成之后行为
0 烧写成功代码继续执行,烧写失败停止
-1 烧写成功与否,代码停止
正值 烧写失败代码停止,成功则 delay 一段时间,单位 ms
负值(不包括 -1 ) 烧写成功失败都 delay 一段时间,单位 ms

eFuse 电源控制

硬件设计时 eFuse 默认电源关闭,只有烧写 eFuse 的阶段电, BL2 在烧录 eFuse 之前操作一个 GPIO(如拉高电平)来通知外部给 eFuse 上电,烧录完成再次操作一次(如拉低)来通知烧录完毕, eFuse 应下电。

注意: X5 默认使用aon gpio0_7 控制 eFuse 电源,如果使用其他 GPIO,则需要添加特殊power_gpio 描述信息

如下所示,使用方法status_gpio类似。

{
    "bl2_cfg": {
        ...
      },
      "efuse_cfg": {
        ...
        "power_gpio" : {
            "gpio_sub": "none",
            "gpio_group": 0,
            "gpio_num": 0
        },
        ...
      },
        ...
}

使用示例

示例 : 以 aon gpio0_7 为 power GPIO,hsio1_1 为 state GPIO ,两个 GPIO 默认值低,则最终状态如下

power GPIO status 描述
拉高再拉低 拉高 烧写成功
拉高再拉低 拉低 烧写失败
一直拉高 x 进入烧写 eFuse 流程,如失败

uboot 读写 eFuse

在 uboot 命令支持读写 eFuse,支持三个 eFuse 命令 dump, read 和 write。

读取 eFuse

uboot 读取 eFuse 信息命令 efuse dump

命令用于读取 socid, public key hash 和 non-secure 区域

efuse_dump

读取 eFuse 指定 bank 值

uboot 读取 eFuse 指定 bank 值命令格式 efuse read [type] [bank_index] 参数说明

  • type: secure 表示读取 secure region, nonsecure 表示读取 non-secure region

  • bank_index: 表示读取的 bank 的 index, 16 进制形式

注意: 可区域

  • secure region 的 bank0 , bank13~bank20 可以

  • non secure region 的所有 bank 均

执行命令后,将返回相应 bank 的以及的 lock 状态

Hobot>efuse read nonsecure 0xc
value:0xabcdef12
lock:true

Hobot>efuse read secure 0x13
value:0xed3137
lock:true

写入 eFuse

命令用于写入 eFuse 相应 bank,命令格式如下

efuse write [type] [bank_index] [bank_value] [lock_status]
  • type: secure 表示写 secure region, nonsecure 表示写 non-secure region

  • bank_index: 表示的 bank 的 index, 16 进制形式

  • bank_value: 表示的 bank 的 value, 16 进制形式

  • lock_status: 烧写之后是否要 lock, 取值范围 lock/unlock

注意: 可区域

  • secure region 的 bank13~bank20 , bank25~bank28 可

  • non-secure region 的 bank10/11/12/13 可写。

示例: 将 0x1eff5f0d 写入 secure region bank20

Hobot>efuse write secure 0x14 0x1eff5f0d lock
write SECURE bank:0x14 success

注意事项

  • 执行 efuse write 命令之后,需要重启之后才能正确数据

  • eFuse 电源默认关闭状态,通过 aon gpio0_7控制,在 efuse write 命令中,其控制时序如下 :

    1. aon gpio0_7 拉高,给 eFuse 上电

    2. 等待 1S,待 eFuse 电源稳定之后,再写 eFuse

    3. 写 eFuse 完成,控制 GPIO 下电

示例: 将 user root aes key 写入 secure bank 25 - 28

烧录 user root aes key,对应的 key 文件位于 device/horizon/x5/board_cfg/soc/bl2_cfg/user_root.key,同时注意为小端格式

$ hexdump user_root.key -C
00000000  78 56 34 12 89 67 45 23  9a 78 56 34 ab 89 67 45  |xV4..gE#.xV4..gE|
00000010

user root aes key 的内容上,则对应烧录

secure bank[25]=0x12345678

secure bank[26]=0x23456789

secure bank[27]=0x3456789a

secure bank[28]=0x456789ab

Linux 读写 eFuse

在 Linux 中提供接口用于读写 eFuse,动态库是 libefuse.so,头文件drobot_efuse.h

API 参考

数据结构

efuse_type

enum efuse_type 表示 efuse 的类型

名称 含义
EFUSE_SECURE secure region
EFUSE_NONSECURE non-secure region

efuse_info

struct efuse_info 是描述 efuse 某个 bank 信息结构

名称 类型 最小值 最大值 默认值 含义
type efuse_type - - - efuse 的类型
bank uint32_t - - - bank 的 index 值
value uint32_t - - - bank 的 value 值
lock bool - - - 该 bank 是否 lock

接口说明

drobot_efuse_read

【函数声明】

int drobot_efuse_read(struct efuse_info *efuse);

【功能描述】

用于读 eFuse 某个 bank 的

【参数描述】

  • [IN] struct efuse_info *efuse : 要读取的 efuse bank 属性结构指针, efuse bank 属性结构体为 efuse_info

【返回值】

  • 成功,返回 0

  • 失败:异常负值

drobot_efuse_write

【函数声明】

int drobot_efuse_write(struct efuse_info *efuse);

【功能描述】

用于写 eFuse 某个 bank 的

【参数描述】

  • [IN] struct efuse_info *efuse : 要写入的 efuse bank 属性结构指针, efuse bank 属性结构体为 efuse_info

【返回值】

  • 成功,返回 0

  • 失败:异常负值

示例: 将 user root aes key 写入 secure bank 25 - 28

烧录 user root aes key,对应的 key 文件位于 device/horizon/x5/board_cfg/soc/bl2_cfg/user_root.key,同时注意为小端格式

$ hexdump user_root.key -C
00000000  78 56 34 12 89 67 45 23  9a 78 56 34 ab 89 67 45  |xV4..gE#.xV4..gE|
00000010

user root aes key 的内容上,则对应烧录

secure bank[25]=0x12345678

secure bank[26]=0x23456789

secure bank[27]=0x3456789a

secure bank[28]=0x456789ab

注意事项

开启 secure boot 的操作顺序

以下针对地瓜KEY的芯片,如果客户自己的KEY,请

non secure bank10 的 bit0 用于开启 secure boot,开启启动阶段验证各个阶段镜像。如果没有烧写公钥 hash (即 secure region bank13~20 ),将导致验证失败。所以开启 secure boot 之前烧写公钥 hash。

  • 公钥的 hash 数据保存在 BSP 路径 out/deploy/uboot/pubkey-hash.txt,可以在 uboot 阶段烧入 secure region bank13~20 。

强制开启 debug port

non secure bank10 的 bit1 用于关闭 debug port,若烧写 eFuse 将关闭之后,仍然需要开启 debug,可通过 BL2 CFG 的 socid 白名单机制进行开启。

注意: 最支持100个 socid 白名单

  • 通过以下命令获取 socid

hrut_socuid
  • 将 socid 填充到 BL2 CFG 文件

{
    "bl2_cfg": {
      "feature": {
        ...
      },
      "efuse_cfg": {
        .....
      },
      "socid":["0x12345678123456781234567812345678","0x0", "0x0", "0x0", "0x0","0x0", "0x0", "0x0", "0x0", "0x0",
      "0x0","0x0", "0x0", "0x0", "0x0","0x0", "0x0", "0x0", "0x0", "0x0",
      "0x0","0x0", "0x0", "0x0", "0x0","0x0", "0x0", "0x0", "0x0", "0x0",
      "0x0","0x0", "0x0", "0x0", "0x0","0x0", "0x0", "0x0", "0x0", "0x0",
      "0x0","0x0", "0x0", "0x0", "0x0","0x0", "0x0", "0x0", "0x0", "0x0",
      "0x0","0x0", "0x0", "0x0", "0x0","0x0", "0x0", "0x0", "0x0", "0x0",
      "0x0","0x0", "0x0", "0x0", "0x0","0x0", "0x0", "0x0", "0x0", "0x0",
      "0x0","0x0", "0x0", "0x0", "0x0","0x0", "0x0", "0x0", "0x0", "0x0",
      "0x0","0x0", "0x0", "0x0", "0x0","0x0", "0x0", "0x0", "0x0", "0x0",
      "0x0","0x0", "0x0", "0x0", "0x0","0x0", "0x0", "0x0", "0x0", "0x0"]
    }
}

编译之后,再次烧写镜像,将会开启 debug port