Rockchip · AI & Linux Hub

存储与网络

Rockchip Vendor Storage V1.3.0:完整布局、ID 与 U-Boot/Linux/Android API

Rockchip Vendor Storage V1.3.0:完整布局、ID 与 U-Boot/Linux/Android API — RK-KF-YF-C35, kernel 4.19/5.10/6.1, GKI, SN, MAC.

· ArmSoM Editorial · Rockchip source documentation · 10 分钟阅读

本文完整保留 RK-KF-YF-C35 V1.3.0 英文 PDF 第 5–18 页技术正文。仅提供英文原稿,中文、俄文和德文均完整翻译,四语统一使用英文原图。这与 097 篇旧 Rev.08 说明不同,布局、ID 及 GKI/Android 接口存在差异。原稿列出 RockChip kernel-4.19、kernel-5.10、kernel-6.1,未列具体 ArmSoM 板卡或 SDK/BSP 发行版。本文仅为平台参考,不作通用兼容认证:须核对板卡 SoC、存储后端、预留区域布局、内核 ABI/模块配置、Android 分支和 SDK/BSP。未进行硬件读写或掉电测试。

安全与原文疑点:示例会用 0–31 字节覆盖 ID 1(SN),不可直接在生产设备执行,先备份身份/预置数据。ID 1063 的功能名写超分辨率,说明却写 MEMC;ID 76 写“离线密钥预留字段”,但 1076 又指回它。均保留原始信息,不猜测修正。ID 61 同时用于超分辨率预留和 HDCP2.x RKIV。不能套用 097/099 篇的 ID 分配。GKI 模块原句语法不清,实际 ram_vendor_storage.ko 的构建与加载方式须按 BSP 核对。代码保留原稿拼写、类型及未补齐的错误宏/清理逻辑。

ArmSoM Docs · Rockchip Linux kernel · EDITORIAL-NOTES

1. 应用说明概要

Vendor Storage 用于存储 SN、MAC 等厂商数据。功能包括:

  • 按唯一 ID 访问;
  • 可靠的数据校验;
  • 掉电恢复;
  • PC 读写;
  • UBOOT 读写;
  • 内核读写;
  • Linux 应用读写。

2. Vendor Storage 架构

2. Vendor Storage 架构:英文原图,第 5 页

2. Vendor Storage 架构:英文原图,第 5 页

3. 数据布局

3.1 SPI NOR 数据布局

3.1 SPI NOR 数据布局:英文原图,第 6 页

3.1 SPI NOR 数据布局:英文原图,第 6 页

3.2 Raw NAND 和 SPI NAND 数据布局

3.2 Raw NAND 和 SPI NAND 数据布局:英文原图,第 6 页

3.2 Raw NAND 和 SPI NAND 数据布局:英文原图,第 6 页

3.3 EMMC 数据布局

3.3 EMMC 数据布局:英文原图,第 7 页

3.3 EMMC 数据布局:英文原图,第 7 页

3.4 数据结构

3.4 数据结构:英文原图,第 7 页

3.4 数据结构:英文原图,第 7 页

偏移 (B) 大小 (B) 名称
0x0000 0x0004 Tag,值为 0x524B5644。
0x0004 0x0004 Version,写入后递增
0x0008 0x0002 下一个索引
0x000A 0x0002 item 总数
0x000C 0x0002 空闲偏移
0x000E 0x0002 空闲大小
0x0010 0x0002 Item0->id
0x0012 0x0002 Item0->offset
0x0014 0x0002 Item0->size
0x0016 0x0002 Item0->flag(reversed)
0x0018 0x0008 Item1
… … Item x
— — 数据
Size – 0x08 0x0004 Hash
Size – 0x04 0x0004 Version2,与 Version 值相同

3.5 ID 定义

ID 功能 说明
1 SN 序列号
2 WIFI MAC WIFI MAC 地址
3 LAN MAC 以太网 MAC 地址
4 BT MAC 蓝牙 MAC 地址
5 HDMITX HDCP1.4 KEY HDMITX HDCP1.4 KEY
6 DP HDCP1.4 KEY DP HDCP1.4 KEY
7 HDCP_2X_ID  
8 DRM_KEY_ID  
9 PLAYREADY_CERT_ID  
10 ATTENTION_KEY_ID  
11 PLAYREADY_ROOT_KEY_0_ID  
12 PLAYREADY_ROOT_KEY_1_ID  
13 HDMIRX HDCP1.4 KEY HDMIRX HDCP1.4 KEY
14 SENSOR_CALIBRATION_ID  
15 IMEI_ID  
16 LAN_RGMII_DL_ID  
17 EINK_VCOM_ID 电子墨水屏 VCOM 电压
18    
19    
20 HDMIRX HDCP2.3 KEY HDMIRX HDCP2.3 KEY
…    
60 sr 存储超分辨率在线授权密钥,对应离线密钥位置 +1000,即 1060。
61 超分辨率 算法预留字段 / HDCP2.x RKIV 超分辨率算法预留字段,对应离线预留 1061;RKIV 是 HDMI2.x 固件的 16 字节加密密钥,提供附加安全保护。原文称部分 3528、356x 客户使用这种附加加密方案。
ID 功能 说明
62 memc 存储MEMC在线授权密钥,对应离线密钥位置 +1000,即 1062。
63 MEMC 算法预留字段 MEMC算法预留字段,对应离线预留 1063。
64 pq 存储PQ在线授权密钥,对应离线密钥位置 +1000,即 1064。
65 PQ 算法预留字段 PQ算法预留字段,对应离线预留 1065。
66 RKP 预留字段 RKP CSR 使用;生成 CSR 时的序列号
67 RKP 预留字段 RKP CSR 使用;生成的 CSR 内容
68 multi-module 存储multi-module在线授权密钥,对应离线密钥位置 +1000,即 1068。
69 multi-module 预留字段 multi-module算法预留字段,对应离线预留 1069。
70 touch_read 存储点读在线授权密钥,对应离线密钥位置 +1000,即 1070。
71 touch_read 算法预留字段 点读算法预留字段,对应离线预留 1071。
72 rknpu_ocr 存储OCR 算法在线授权密钥,对应离线密钥位置 +1000,即 1072。
73 rknpu_ocr 算法预留字段 OCR 算法算法预留字段,对应离线预留 1073。
74 face 存储人脸解锁在线授权密钥,对应离线密钥位置 +1000,即 1074。
75 人脸解锁 算法预留字段 人脸解锁算法预留字段,对应离线预留 1075。
76 knowledge 离线密钥预留字段
77 knowledge 算法预留字段 Knowledge算法预留字段,对应离线预留 1077。
…    
84 asr 存储ASR 语音转文本算法在线授权密钥,对应离线密钥位置 +1000,即 1084。
ID 功能 说明
85 asr 算法预留字段 ASR 语音转文本算法算法预留字段,对应离线预留 1085。
86 llm 存储LLM 翻译在线授权密钥,对应离线密钥位置 +1000,即 1086。
87 llm 算法预留字段 LLM 翻译算法预留字段,对应离线预留 1087。
88 tts 存储TTS 文本转语音算法在线授权密钥,对应离线密钥位置 +1000,即 1088。
89 tts 算法预留字段 TTS 文本转语音算法算法预留字段,对应离线预留 1089。
…    
96 aieraser 存储AI 消除算法在线授权密钥,对应离线密钥位置 +1000,即 1096。
97 aieraser 算法预留字段 AI 消除算法算法预留字段,对应离线预留 1097。
…    
156 客户预留 保留供客户使用,不供 RK 内部使用
… 客户预留 保留供客户使用,不供 RK 内部使用
256 客户预留 保留供客户使用,不供 RK 内部使用
1060 超分辨率 离线密钥位置 超分辨率离线密钥位置,减去 1000 即在线密钥位置 60。
1061 超分辨率 离线密钥预留字段 超分辨率离线密钥预留字段
1062 MEMC 离线密钥位置 MEMC离线密钥位置,减去 1000 即在线密钥位置 62。
1063 超分辨率 离线密钥预留字段 MEMC离线密钥预留字段
1064 PQ 离线密钥位置 PQ离线密钥位置,减去 1000 即在线密钥位置 64。
1065 PQ 离线密钥预留字段 PQ离线密钥预留字段
1068 multi-module 离线密钥位置 multi-module离线密钥位置,减去 1000 即在线密钥位置 68。
ID 功能 说明
1069 multi-module 离线密钥预留字段 multi-module离线密钥预留字段
1070 点读 离线密钥位置 点读离线密钥位置,减去 1000 即在线密钥位置 70。
1071 点读 离线密钥预留字段 点读离线密钥预留字段
1072 OCR 离线密钥位置 OCR 算法离线密钥位置,减去 1000 即在线密钥位置 72。
1073 OCR 离线密钥预留字段 OCR 算法离线密钥预留字段
1074 Face 离线密钥位置 人脸解锁离线密钥位置,减去 1000 即在线密钥位置 74。
1075 Face 离线密钥预留字段 人脸解锁离线密钥预留字段
1076 Knowledge 离线密钥位置 Knowledge离线密钥位置,减去 1000 即在线密钥位置 76。
1077 Knowledge 离线密钥预留字段 Knowledge离线密钥预留字段
1084 ASR 离线密钥位置 ASR 语音转文本算法离线密钥位置,减去 1000 即在线密钥位置 84。
1085 ASR 离线密钥预留字段 ASR 语音转文本算法离线密钥预留字段
1086 LLM 离线密钥位置 LLM 翻译离线密钥位置,减去 1000 即在线密钥位置 86。
1087 LLM 离线密钥预留字段 LLM 翻译离线密钥预留字段
1088 TTS 离线密钥位置 TTS 文本转语音算法离线密钥位置,减去 1000 即在线密钥位置 88。
1089 TTS 离线密钥预留字段 TTS 文本转语音算法离线密钥预留字段
1096 AI 消除 Algorithm 离线密钥位置 AI 消除算法离线密钥位置,减去 1000 即在线密钥位置 96。
1097 AI 消除 Algorithm 离线密钥预留字段 AI 消除算法离线密钥预留字段

注意:NVM 中的数据按 64 字节对齐存放,每个 item 至少分配 64 字节。因此写入 1–64 字节分配 64 字节,写入 65–128 字节分配 128 字节。

4. UBOOT API

源代码:u-boot/board/rockchip/common/storage/storage.c

int vendor_storage_init(void)
function: Initialize vendor storage
input : none
return: 0: Initialize success
        other: Initialize fail

int vendor_storage_read(u32 id, void *pbuf, u32 size)
function: read vendor storage by id
input : id, item id;
pbuf, data buffer;
size, number byte to read.
return: other: number byte have read.
        -1: read fail.

int vendor_storage_write(u32 id, void *pbuf, u32 size)
function: write vendor storage by id
input : id: item id;
pbuf: data buffer;
size: number bytes to write.
return:  0: write success
         other: write fail

4.1 非 GKI 内核 API

源代码:kernel/drivers/soc/rockchip/rk_vendor_storage.c

int rk_vendor_read(u32 id, void *pbuf, u32 size)
function: read vendor storage by id
input : id: item id;
pbuf: data buffer;
size: number bytes to read.
return: other: number byte have read.
        -1: read fail

int rk_vendor_write(u32 id, void *pbuf, u32 size)
function: write vendor storage by id
input : id, item id;
pbuf: data buffer;
size: number bytes to write.
return: 0: write success
        other : write fail

Menuconfig 配置

4.1 非 GKI 内核 API:英文原图,第 13 页

4.1 非 GKI 内核 API:英文原图,第 13 页

CONFIG_ROCKCHIP_VENDOR_STORAGE:

Say Y here to enable vendor storage support.
Vendor storage is used for stored SN, MAC, BT ADDR etc.

Symbol: ROCKCHIP_VENDOR_STORAGE [=y]
Type  : boolean
Prompt: Rockchip vendor storage support
  Location:
    -> Device Drivers
      -> SOC (System On Chip) specific Drivers
  Defined at drivers/soc/rockchip/Kconfig:6
  Depends on: ARCH_ROCKCHIP [=y] || COMPILE_TEST

4.2 GKI 内核 API

受 GKI 内核接口限制,原文要求内核添加 ram_vendor_storage.ko,Vendor Storage 才能支持读取接口;不支持写入接口。

4.3 Android API

源代码:hardware/rockchip/libvendor_storage/vendor_storage.c

/*
 * vendor_storage_init must be call first
 * rerurn:  ret=0 succes   ret<0 failed
 */
 int vendor_storage_init(void);

/*
 * emmc_vendor_write
 * id: item id
 * pbuf: write data
 * size: vendor_item.size
 * rerurn:  ret>0 succes   ret<0 failed
 */
 int emmc_vendor_write(uint32 id, void *pbuf, uint32 size);

 /*
 * emmc_vendor_read
 * id: item id
 * pbuf: read data
 * size: vendor_item.size
 * rerurn:  ret>0 succes   ret<0 failed
 */
 int emmc_vendor_read(uint32 id, void *pbuf, uint32 size);

具体用法参考 hardware/rockchip/libvendor_storage/vendor_storage_test.c。

5. PC 演示工具

选择 SN 选项并输入 SN 值,按 ENTER 将 SN item 加入写请求列表。

5. PC 演示工具:英文原图,第 14 页

5. PC 演示工具:英文原图,第 14 页

点击 Burning 按钮会将数据写入 Vendor Storage。

5. PC 演示工具:英文原图,第 15 页

5. PC 演示工具:英文原图,第 15 页

选择 SN 选项并点击 Read,从 Vendor Storage 读取数据。

5. PC 演示工具:英文原图,第 15 页

5. PC 演示工具:英文原图,第 15 页

6. PC 工具源代码

PC 工具读取数据

/*----------------------------------------------------------------------
Name    : RK_ReadProvisioningData
Desc    : Read provisioning data by id
Params  : (IN)nID: id
          (OUT)pDataBuffer: buffer to save data, malloc by caller
          (IN|OUT)nBufferSize: in = size of buffer,out = actual data size
          (IN)dwLayer:device layer
Return  : TRUE: SUCCESSED
          FALSE: FAILED
----------------------------------------------------------------------*/
BOOL RK_ReadProvisioningData(USHORT nID,PBYTE pDataBuffer,USHORT &nBufferSize,DWORD dwLayer=0);

PC 工具写入数据

 /*----------------------------------------------------------------------
Name    : RK_WriteProvisioningData
Desc    : Write provisioning data by id
Params  : (IN)nID: id
          (IN)pDataBuffer: buffer to save data, malloc by caller
          (IN)nBufferSize: size of buffer
          (IN)dwLayer:device layer
Return  : TRUE: SUCCESSED
          FALSE: FAILED
----------------------------------------------------------------------*/
BOOL RK_WriteProvisioningData(USHORT nID,PBYTE pDataBuffer,USHORT nBufferSize,DWORD dwLayer=0);

7. Linux 应用演示代码

使用内核提供的 vendor_storage 节点访问。

#include <fcntl.h>
#include <sys/ioctl.h>

typedef unsigned short uint16;
typedef unsigned long uint32;
typedef unsigned char uint8;

#define VENDOR_REQ_TAG      0x56524551
#define VENDOR_READ_IO      _IOW('v', 0x01, unsigned int)
#define VENDOR_WRITE_IO     _IOW('v', 0x02, unsigned int)
#define VENDOR_SN_ID        1
#define VENDOR_WIFI_MAC_ID  2
#define VENDOR_LAN_MAC_ID   3
#define VENDOR_BLUETOOTH_ID 4

struct rk_vendor_req {
    u32 tag;
    u16 id;
    u16 len;
    u8 data[1];
};

int vendor_storage_read_test(void)
{
    uint32 i;
    int ret ;
    uint8 p_buf[2048]; /* malloc req buffer or used extern buffer */
    struct rk_vendor_req *req;

    req = (struct rk_vendor_req *)p_buf;
    int sys_fd = open("/dev/vendor_storage",O_RDWR,0);
    if(sys_fd < 0){
        ERROR("vendor_storage open fail\n");
        return -1;
    }

    req->tag = VENDOR_REQ_TAG;
    req->id = VENDOR_SN_ID;
    req->len = 512; /* max read length to read*/

    ret = ioctl(sys_fd, VENDOR_READ_IO, req);
    /* return req->len is the real data length stored in the NV-storage */
    if(ret){
        ERROR("vendor read error\n");
        return -1;
    }

    return 0;
}

int vendor_storage_write_test(void)
{
    uint32 i;
    int ret ;
    uint8 p_buf[2048]; /* malloc req buffer or used extern buffer */
    struct rk_vendor_req *req;

    req = (struct rk_vendor_req *)p_buf;
    int sys_fd = open("/dev/vendor_storage",O_RDWR,0);
    if(sys_fd < 0){
        ERROR("vendor_storage open fail\n");
        return -1;
    }
    req->tag = VENDOR_REQ_TAG;
    req->id = VENDOR_SN_ID;
    req->len = 32; /* data len */
    for (i = 0; i < 32; i++)
        req->data[i] = i;
    ret = ioctl(sys_fd, VENDOR_WRITE_IO, req);
    if(ret){
        ERROR("vendor write error\n");
        return -1;
    }

    return 0;
}

不使用内核驱动的用户态应用访问方式:

实现参考:hardware/rockchip/libvendor_storage/vendor_storage_test.c。

浏览此主题 → · 入门路线 →