前言:

Vendor storage 被设计用来存储 SN,MAC,LAN,BT 等 vendor data。

特征:

  • 唯一的访问 ID;
  • 可靠的数据验证;
  • 掉电不会丢失;
  • 系统启动各个阶段都可访问;
  • PC 端可读写;
  • Kernel 可读写;
  • Linux Application 可读写;

如下图:

Data Layout:

也就是说 vendor storage 是从 eMMC 3.5M 之后开始存放,每个元素是 64K,一共 4 块总共 256K。

系统一共把 vendor 的存储块分成 4 个分区,vendor0、vendor1、vendor2、vendor3。每个 vendorX 的 hdr 里都有一个单调递增的 Version 字段用于表示 vendorX 被更新的时刻点。每次读操作只读取新的 vendorX(即 vendor 大),写操作的时候会更新 Version、并且把整个原有信息和新增信息搬移到下一个 vendor 分区里。例如当前 从 vendor2读取到信息,经过修改后再回写,此时写入的是 vendor3。这样做只是为了起到一个简单的安全防护作用。

存储数据结构:

在代码中用 struct vendor_info 表示:

struct vendor_info {u32  tag;u32 version;u16 next_index;u16  item_num;u16    free_offset;u16 free_size;struct    vendor_item item[126]; /* 126 * 8*/u8   data[EMMC_VENDOR_PART_SIZE * 512 - 1024 - 8];u32    hash;u32    version2;
};

各个阶段的驱动文件及接口如下, 两个阶段的初始化以及读写接口的本质实现是一样的。

        uboot:
        驱动文件: storage.c
        初始化接口: vendor_storage_init();
        读写接口: vendor_storage_read()/vendor_storage_write();

接口会在rockusb也就是loader模式被使用,可查看rkusb_handle_datatx()以及rkusb_handle_datarx()两个函数。

        kernel:
        驱动文件: sdmmc_vendor_storage.c和rk_vendor_storage.c
        初始化接口:emmc_vendor_storage_init(), 它被放在线程vendor_init_thread()中实现是因为
        1.不能阻塞kernel驱动初始化过程
        2.需要等待eMMC初始化完成。

接口一方面提供给用户空间使用,通过vendor_storage_ioctl()接口实现。
        另外读写函数也被注册为公共接口(通过rk_vendor_register()实现),供kernel使用,比如wifi模块的get_wifi_addr_vendor()会去读写Wifi MAC ID.

用户空间:

在 /system/eyeknowproj/vendoroper/ 目录下,有我们的项目源码:

Android.mk:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := vendorlib.c
LOCAL_SHARED_LIBRARIES := liblog libm libc libprocessgroup
LOCAL_CFLAGS := -Werror
LOCAL_MODULE := libvendoroper
LOCAL_C_INCLUDES := $(LOCAL_PATH)/
include $(BUILD_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_SRC_FILES := vendor_test.c
LOCAL_SHARED_LIBRARIES := libvendoroper liblog libm libc libprocessgroup
LOCAL_CFLAGS := -Werror
LOCAL_MODULE := vendor_test
LOCAL_C_INCLUDES := $(LOCAL_PATH)/
include $(BUILD_EXECUTABLE)

vendorlib.c:

#include "vendorlib.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>int vendor_read(enum VENDOR_ID vid,char* buf,int len)
{int ret;uint8 p_buf[sizeof(struct rk_vendor_req)+64];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){printf("vendor storage open fail");return -1;}req->tag = VENDOR_REQ_TAG;req->id = vid;req->len = len;ret = ioctl(sys_fd, VENDOR_READ_IO, req);if (!ret) {memcpy(buf, req->data, len);}close(sys_fd);return 0;
}
int vendor_write(enum VENDOR_ID vid,char* buf,int len)
{int ret;uint8 p_buf[sizeof(struct rk_vendor_req)+64];struct rk_vendor_req *req;int i;int sys_fd = open("/dev/vendor_storage",O_RDWR,0); req = (struct rk_vendor_req *)p_buf;if(sys_fd < 0){printf("vendor storage open fail");return -1;}req->tag = VENDOR_REQ_TAG;req->id = vid;req->len = len;for (int i = 0; i < len; i++)req->data[i] = buf[i];ret = ioctl(sys_fd, VENDOR_WRITE_IO, req);if (ret) {printf("vendor write fail\n");return -1;}close(sys_fd);return 0;
}

vendorlib.h:

#include <sys/ioctl.h>typedef     unsigned short      uint16;
typedef     unsigned int       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)enum VENDOR_ID
{VENDOR_SN_ID = 1,VENDOR_WIFI_MAC_ID = 2,VENDOR_LAN_MAC_ID = 3,VENDOR_BLUETOOTH_ID = 4,VENDOR_USER1 = 16,VENDOR_USER2 = 17,
};#define VENDOR_USER_LENGTH 32
struct rk_vendor_req {uint32 tag;uint16 id;uint16 len;uint8 data[1];
};
int vendor_read(enum VENDOR_ID vid,char* buf,int len);
int vendor_write(enum VENDOR_ID vid,char* buf,int len);

vendor_test.c:

#include "vendorlib.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>int main()
{char temp[64] = {'k','e','l','l','a','n','d','s',};char temp1[64] = {};vendor_write(VENDOR_USER1,temp,VENDOR_USER_LENGTH);vendor_read(VENDOR_USER1,temp1,VENDOR_USER_LENGTH);printf("%c,%c,%c,%c,%c,%c,%c\n",temp1[0],temp1[1],temp1[2],temp1[3],temp1[4],temp1[5],temp1[6]);return 0;
}

小结:

  1. 由于 Vendor Storage 位于 eMMC 上,所以做擦除的时候也会一并丢失;
  2. 重新烧写固件或者擦除 idb 是不会丢失的。
  3. 工具中目前是不支持添加新 id 的,如果要添加,那就要改工具源代码,或者直接通过驱动提供给用户空间的接口来添加新 id。

参考:

Rockchip Vendor Storage Application Note.pdf
Rockchip-Developer-Guide-UBoot-nextdev.pdf

[RK3399][Android7.1] Vendor Storage区域知识及探讨_Kris Fei's blog-CSDN博客

[Android O] [RK3399] -- Vendor Storage 功能探究相关推荐

  1. Android打开相机,报出 android.os.FileUriExposedException: file:///storage/emulated/0/test/img.jpg exposed

    执行以下代码后,打开相机 //调用相机自带的照相功能 指定图片目录 if (Environment.getExternalStorageState().endsWith(Environment.MED ...

  2. Android实现退出提示的功能

    摘要:本文主要是实现在Android中退出提示的功能,平常使用Android手机时,点击返回键时,由于不小心点击返回键过快,导至程序返回试界面之后直接退出程序,导至用户还要再重新登录一次.为解决此类问 ...

  3. android sharesdk分享功能,Android ShareSDK快速实现分享功能

    第一步 :获取ShareSDK 为了集成ShareSDK,您首先需要到ShareSDK官方网站注册并且创建应用,获得ShareSDK的Appkey,然后到SDK的下载页面下载SDK的压缩包,解压以后可 ...

  4. android api 相机,具有相机2 API的Android Lollipop上的ZSL功能

    我试图从相机应用程序,相机框架和libcameraservice实施以及相机HAL v3.2规范中了解Android 5.0对ZSL功能的支持. 据我了解,在Android中实现ZSL的方式有两种: ...

  5. android 禁止Viewpager左右滑动功能

    今天,简单讲讲Android如何禁止Viewpager左右滑动功能. 原理: 百度后发现重写ViewPager,覆盖ViewPager的onInterceptTouchEvent(MotionEven ...

  6. Android App Bundle:动态功能模块

    目录 Android App Bundle 创建动态功能模块 动态功能模块 与主模块建立关联 部署应用 按需分发On-Demand 免安装分发 自 2021 年 8 月起,Google Play 将开 ...

  7. android ztree,ztree实现权限功能(横向显示)

    最近在做权限功能的时候,采用的ztree实现的,但是产品要求最后一层的权限节点要横向显示.开始在网上找的解决方案是用css样式把最后一层的display设置为inline.在我本地电脑上看了下.效果不 ...

  8. android java 8_四个库,让你在 Android 中启用 Java 8 功能

    Java 8 的推出引入很多革命性变化,加入了函数式编程的特征,使基于行为的编程成为可能,同时简化了各种设计模式的实现方式,是 Java 有史以来最重要的更新. 自 Android N 之后,由于 J ...

  9. linux 短信功能,Android调用系统短信功能发送短信

    Android调用系统短信功能发送短信有两种方法: 第一种,设定发送的号码,和内容,界面没有联系人,群组组等按钮,如下图所示: 代码如下: Uri smsToUri = Uri.parse(" ...

  10. Android实现mp3分析,Android编程实现播放MP3功能示例

    本文实例讲述了Android编程实现播放MP3功能.分享给大家供大家参考,具体如下: 在android中播放mp3非常简单,也是项目中经常使用的,比如说要做项目的背景音乐,应用中某些功能的提示音等的. ...

最新文章

  1. 人工智能在能源行业的5个应用
  2. 问号和星号 php,星号和问号两个通配符
  3. 【深度学习入门到精通系列】阿里云人工智能平台的使用方法
  4. SAP的实施公司有哪些?
  5. android 获取u盘名字_android 获取U盘路径
  6. μC/OS-Ⅱ 操作系统内核知识
  7. memcached客户端_Memcached集群的使用
  8. Fastlane-iOS(调研篇)
  9. Java 单例模式详解(转)
  10. 远程键盘 App 被曝漏洞,成 Intel 弃子!
  11. css 中引入第三方字体
  12. 大数据如何推动医疗行业的发展
  13. 从今天开始阅读Java源码吧!
  14. ai老师人工智能培训老师计算机视觉老师叶梓:计算机视觉领域的自监督学习模型——MAE-12
  15. VB计算机中next是什么意思,VB程序的基本结构――循环结构之For-Next语句
  16. php TCPDF 生成pdf文件
  17. 卧室.餐厅.客厅要选择挂什么油画?
  18. php 实现 js escape unescape
  19. 数据仓库、数据集市和数据湖有什么区别?
  20. 【系列】区块链与以太坊实战(1)-基础知识

热门文章

  1. 闯关H5小游戏制作推荐,教你快速上手TOM闯关游戏H5
  2. CA证书出错,请登录微信支付商户平台下载证书
  3. wpsppt页面卷曲在哪里_用PPT制作页面卷角效果,你会吗?
  4. 凸优化基础知识—对偶(Duality)
  5. 保龄球积分c语言程序,C语言保龄球积分.doc
  6. TensorFlow 2.9的零零碎碎(二)-读取MNIST数据集
  7. matlab kmeans 质心,KMeans_SPD_Matrices
  8. Excel合并单元格快捷键
  9. python爬虫IP地址解析爬取(IP38.com)
  10. Ubuntu 安装amd 显卡驱动