RK3568平台(vendor篇)vendor storage分区

news2024/9/21 8:03:32

一.简介

rockchip vendor storage是一种用于存储SN, MAC, LAN, BT等数据的区域,它具有不会丢失和系统启动各个阶段都可以访问的特性。它使用GPT分区表格式,并在U-boot, kernel和用户空间中提供了相应的驱动文件和接口。

rockchip vendor storage是一种特殊的存储区域,用于存储一些设备相关的信息,比如序列号,MAC地址,蓝牙地址等。这些信息通常是在出厂时写入的,不会随着系统更新而改变。

rockchip vendor storage的特点是:

不会丢失:即使系统出现异常或者被恢复出厂设置,vendor storage中的数据也不会被擦除或者覆盖。

可访问性:vendor storage中的数据可以在系统启动的各个阶段被访问,包括U-boot, kernel和用户空间。这样可以方便地获取或者设置一些设备相关的参数。

安全性:vendor storage中的数据是加密的,只有通过特定的接口才能读写。这样可以防止数据被篡改或者泄露。

存储数据结构:

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

二.VendorStorage的数据结构

VendorStorage的头部结构包含标签,版本,索引,项目数,空闲偏移和空闲大小,其定义如下:

struct vendor_hdr {
  u32 tag;
  u32 version;
  u16 next_index;
  u16 item_num;
  u16 free_offset; /* Free space offset */
  u16 free_size; /* Free space size */
};

VendorStorage的信息结构包含头部,项目,数据,哈希和版本2。版本2和头部的版本一起用于确保当前Vendor块内容的完整性,其定义如下:

struct vendor_info {
  struct vendor_hdr * hdr;
  struct vendor_item * item;
  u8 * data;
  u32 * hash;
  u32 * version2;
};

三.VendorStorage u-boot阶段接口

路径:

u-boot\arch\arm\mach-rockchip\vendor.c

u-boot\arch\arm\include\asm\arch\vendor.h

读写接口

vendor_storage_read()/vendor_storage_write()

在Uboot阶段,VendorStorage的读写由vendor_storage_read()和vendor_storage_write()函数实现。

int vendor_storage_read(u16 id, void *pbuf, u16 size)
{
	int ret = 0;
	u32 i;
	u16 offset;
	struct vendor_item *item;

	/* init vendor storage */
	if (!bootdev_type) {
		ret = vendor_storage_init();
		if (ret < 0)
			return ret;
	}

	item = vendor_info.item;
	for (i = 0; i < vendor_info.hdr->item_num; i++) {
		if ((item + i)->id == id) {
			debug("[Vendor INFO]:Find the matching item, id=%d\n", id);
			/* Correct the size value */
			if (size > (item + i)->size)
				size = (item + i)->size;
			offset = (item + i)->offset;
			memcpy(pbuf, (vendor_info.data + offset), size);
			return size;
		}
	}
	debug("[Vendor ERROR]:No matching item, id=%d\n", id);

	return -EINVAL;
}
/*
 * @id: item id, first 4 id is occupied:
 *	VENDOR_SN_ID
 *	VENDOR_WIFI_MAC_ID
 *	VENDOR_LAN_MAC_ID
 *	VENDOR_BLUETOOTH_ID
 * @pbuf: write data buffer;
 * @size: write bytes;
 *
 * return: bytes equal to @size is success, other fail;
 */
 int vendor_storage_write(u16 id, void *pbuf, u16 size)
{
	u32 i, j, next_index, align_size, alloc_size, next_size;
	u16 part_size, max_item_num, offset, part_num;
	struct vendor_item *item;
	int cnt, ret = 0;

	/* init vendor storage */
	if (!bootdev_type) {
		ret = vendor_storage_init();
		if (ret < 0)
			return ret;
	}

	switch (bootdev_type) {
	case IF_TYPE_MMC:
		part_size = EMMC_VENDOR_PART_BLKS;
		max_item_num = EMMC_VENDOR_ITEM_NUM;
		part_num = VENDOR_PART_NUM;
		break;
	case IF_TYPE_RKNAND:
	case IF_TYPE_SPINAND:
		part_size = NAND_VENDOR_PART_BLKS;
		max_item_num = NAND_VENDOR_ITEM_NUM;
		part_num = NAND_VENDOR_PART_NUM;
		break;
	case IF_TYPE_SPINOR:
		part_size = FLASH_VENDOR_PART_BLKS;
		max_item_num = FLASH_VENDOR_ITEM_NUM;
		part_num = VENDOR_PART_NUM;
		break;
		#ifdef CONFIG_MTD_BLK
	case IF_TYPE_MTD:
		part_size = FLASH_VENDOR_PART_BLKS;
		max_item_num = FLASH_VENDOR_ITEM_NUM;
		part_num = MTD_VENDOR_PART_NUM;
		break;
#endif
	default:
		ret = -ENODEV;
		break;
	}
	/* Invalid bootdev? */
	if (ret < 0)
		return ret;

	next_index = vendor_info.hdr->next_index;
	/* algin to 64 bytes*/
	align_size = (size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN);
	if (size > align_size)
		return -EINVAL;

	item = vendor_info.item;
	/* If item already exist, update the item data */
	for (i = 0; i < vendor_info.hdr->item_num; i++) {
		if ((item + i)->id == id) {
			alloc_size = ((item + i)->size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN);
			if (size > alloc_size) {
				if (vendor_info.hdr->free_size < align_size)
					return -EINVAL;
				debug("[Vendor INFO]:Find the matching item, id=%d and resize\n", id);
				offset = (item + i)->offset;
				for (j = i; j < vendor_info.hdr->item_num - 1; j++) {
					(item + j)->id = (item + j + 1)->id;
					(item + j)->size = (item + j + 1)->size;
					(item + j)->offset = offset;
					next_size = ((item + j + 1)->size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN);
					memcpy((vendor_info.data + offset),
					       (vendor_info.data + (item + j + 1)->offset),
					       next_size);
					offset += next_size;
				}
				(item + j)->id = id;
				(item + j)->offset = offset;
				(item + j)->size = size;
				memcpy((vendor_info.data + offset), pbuf, size);
				vendor_info.hdr->free_offset = offset + align_size;
				vendor_info.hdr->free_size -= align_size - alloc_size;
			} else {
				debug("[Vendor INFO]:Find the matching item, id=%d\n", id);
				offset = (item + i)->offset;
				memcpy((vendor_info.data + offset), pbuf, size);
				(item + i)->size = size;
			}
			vendor_info.hdr->version++;
			*(vendor_info.version2) = vendor_info.hdr->version;
			vendor_info.hdr->next_index++;
			if (vendor_info.hdr->next_index >= part_num)
				vendor_info.hdr->next_index = 0;
			cnt = vendor_ops((u8 *)vendor_info.hdr, part_size * next_index, part_size, 1);
			return (cnt == part_size) ? size : -EIO;
		}
	}
	/*
	 * If item does not exist, and free size is enough,
	 * creat a new one
	 */
	if ((vendor_info.hdr->item_num < max_item_num) &&
	    (vendor_info.hdr->free_size >= align_size)) {
		debug("[Vendor INFO]:Create new Item, id=%d\n", id);
		item = vendor_info.item + vendor_info.hdr->item_num;
		item->id = id;
		item->offset = vendor_info.hdr->free_offset;
		item->size = size;

		vendor_info.hdr->free_offset += align_size;
		vendor_info.hdr->free_size -= align_size;
		memcpy((vendor_info.data + item->offset), pbuf, size);
		vendor_info.hdr->item_num++;
		vendor_info.hdr->version++;
		vendor_info.hdr->next_index++;
		*(vendor_info.version2) = vendor_info.hdr->version;
		if (vendor_info.hdr->next_index >= part_num)
			vendor_info.hdr->next_index = 0;

		cnt = vendor_ops((u8 *)vendor_info.hdr, part_size * next_index, part_size, 1);
		return (cnt == part_size) ? size : -EIO;
	}
	debug("[Vendor ERROR]:Vendor has no space left!\n");

	return -ENOMEM;
}

四.VendorStorage kernel阶段接口

文件路径:

/kernel/drivers/soc/rockchip/sdmmc_vendor_storage.c

/kernel/drivers/soc/rockchip/rk_vendor_storage.c

kernel阶段读写接口:

int rk_vendor_read(u32 id, void *pbuf, u32 size)
{
	if (_vendor_read)
		return _vendor_read(id, pbuf, size);
	return -1;
}
EXPORT_SYMBOL(rk_vendor_read);

int rk_vendor_write(u32 id, void *pbuf, u32 size)
{
	if (_vendor_write)
		return _vendor_write(id, pbuf, size);
	return -1;
}
EXPORT_SYMBOL(rk_vendor_write);

五.用户态读写接口

static int emmc_vendor_read(unsigned int id, void *pbuf, unsigned int size)
{
	unsigned int i;
	if (!g_vendor){
		DEBUG(("emmc_vendor_read g_vendor fail\n"));
		return -ENOMEM;
	}
	DEBUG(("emmc_vendor_read: id=%u, pbuf=%p, size=%u\n", id, pbuf, size));
	for (i = 0; i < g_vendor->item_num; i++) {
		if (g_vendor->item[i].id == id) {
			if (size > g_vendor->item[i].size)
				size = g_vendor->item[i].size;
			memcpy(pbuf,
			       &g_vendor->data[g_vendor->item[i].offset],
			       size);
			DEBUG(("emmc_vendor_read: read %u bytes from offset %u\n", size, g_vendor->item[i].offset));
			return size;
		}
	}
	DEBUG(("emmc_vendor_read: id=%u not found\n", id));
	return (-1);
}
static int emmc_vendor_write(unsigned int id, void *pbuf, unsigned int size)
{
	unsigned int i, j, next_index, align_size, alloc_size, item_num;
	unsigned int offset, next_size;
	unsigned char *p_data;
	int ret = 0;
	struct vendor_item *item;
	struct vendor_item *next_item;
	if (!g_vendor)
		return -ENOMEM;
	p_data = g_vendor->data;
	item_num = g_vendor->item_num;
	align_size = ALIGN(size, 0x40); /* align to 64 bytes*/
	next_index = g_vendor->next_index;
	for (i = 0; i < item_num; i++) {
		item = &g_vendor->item[i];
		if (item->id == id) {
			alloc_size = ALIGN(item->size, 0x40);
			if (size > alloc_size) {
				if (g_vendor->free_size < align_size) {
					ret = -EINVAL;
					goto exit;
				}
				offset = item->offset;
				for (j = i; j < item_num - 1; j++) {
					item = &g_vendor->item[j];
					next_item = &g_vendor->item[j + 1];
					item->id = next_item->id;
					item->size = next_item->size;
					item->offset = offset;
					next_size = ALIGN(next_item->size,
							  0x40);
					memcpy(&p_data[offset],
					       &p_data[next_item->offset],
					       next_size);
					offset += next_size;
				}
				item = &g_vendor->item[j];
				item->id = id;
				item->offset = offset;
				item->size = size;
				memcpy(&p_data[item->offset], pbuf, size);
				g_vendor->free_offset = offset + align_size;
				g_vendor->free_size -= (align_size -
							alloc_size);
			} else {
				memcpy(&p_data[item->offset],
				       pbuf,
				       size);
				g_vendor->item[i].size = size;
			}
			g_vendor->version++;
			g_vendor->version2 = g_vendor->version;
			g_vendor->next_index++;
			if (g_vendor->next_index >= EMMC_VENDOR_PART_NUM)
				g_vendor->next_index = 0;
			emmc_vendor_ops((unsigned char *)g_vendor, EMMC_VENDOR_PART_START +
					EMMC_VENDOR_PART_SIZE * next_index,
					EMMC_VENDOR_PART_SIZE, 1);
			goto exit;
		}
	}
	if (g_vendor->free_size >= align_size) {
		item = &g_vendor->item[g_vendor->item_num];
		item->id = id;
		item->offset = g_vendor->free_offset;
		item->size = size;
		g_vendor->free_offset += align_size;
		g_vendor->free_size -= align_size;
		memcpy(&g_vendor->data[item->offset], pbuf, size);
		g_vendor->item_num++;
		g_vendor->version++;
		g_vendor->version2 = g_vendor->version;
		g_vendor->next_index++;
		if (g_vendor->next_index >= EMMC_VENDOR_PART_NUM)
			g_vendor->next_index = 0;
		emmc_vendor_ops((unsigned char *)g_vendor, EMMC_VENDOR_PART_START +
				EMMC_VENDOR_PART_SIZE * next_index,
				EMMC_VENDOR_PART_SIZE, 1);
		goto exit;
	}
	ret = -1;
exit:
	return ret;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1916383.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

硅纪元AI应用推荐 | 百度橙篇成新宠,能写万字长文

“硅纪元AI应用推荐”栏目&#xff0c;为您精选最新、最实用的人工智能应用&#xff0c;无论您是AI发烧友还是新手&#xff0c;都能在这里找到提升生活和工作的利器。与我们一起探索AI的无限可能&#xff0c;开启智慧新时代&#xff01; 百度橙篇&#xff0c;作为百度公司在202…

软航文档控件VUE示例运行及控件替换方法记录

目录 示例运行 步骤一、npm install 步骤二、npm run dev 软航文档控件替换 附 vue小白记录一下软航文档控件VUE示例的运行方法以及示例中控件的替换过程。 示例运行 在已经安装好VUE环境的电脑上&#xff0c;VUE环境部署可以参考另一篇&#xff1a;配置VUE环境过程中 …

3.相机标定原理及代码实现(opencv)

1.相机标定原理 相机参数的确定过程就叫做相机标定。 1.1 四大坐标系及关系 &#xff08;1&#xff09;像素坐标系&#xff08;单位&#xff1a;像素&#xff08;pixel&#xff09;&#xff09; 像素坐标系是指相机拍到的图片的坐标系&#xff0c;以图片的左上角为坐标原点&a…

nvm安装使用 nrm使用

因维护老项目及开发新项目同时进行&#xff0c;需要使用不同版本的node进行运行&#xff0c;所以用nvm进行多个版本的node维护&#xff0c;通过nrm进行镜像源管理切换 简介 Node.js 是一种基于 Chrome V8 引擎的 JavaScript 运行环境&#xff0c;用于构建高性能的网络应用程序…

mobx学习笔记

mobx介绍 mobx是一个功能强大&#xff0c;上手容易的状态管理工具。MobX背后的哲学很简单:任何源自应用状态的东西都应该自动地获得。利用getter和setter来收集组件的数据依赖关系&#xff0c;从而在数据发生变化的时候精确知道哪些组件需要重绘。 mobx和redux的区别 mobx更…

javaweb学习day1《HTML篇》--新浪微博(前端页面的创建思路及其HTML、css代码详解)

一、前言 本篇章为javaweb的开端&#xff0c;也是第一篇综合案例&#xff0c;小编也是看着黑马程序员的视频对里面的知识点进行理解&#xff0c;然后自己找一个新浪微博网页看着做的&#xff0c;主要还是因为懒&#xff0c;不想去领黑马程序员的资料了。 小编任务javaweb和ja…

人工智能算法工程师(中级)课程6-sklearn机器学习之聚类问题与代码详解

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能算法工程师(中级)课程6-sklearn机器学习之聚类问题与代码详解。在机器学习领域&#xff0c;聚类是一种无监督学习方法&#xff0c;旨在将相似的数据点划分为同一类别。sklearn是一个广泛应用于机器学习的Py…

初识C++语言(1)

目录 C语言简介 C 语言概述 C 语言的特点 语言简洁紧凑&#xff0c;使用灵活方便 运算符丰富 数据结构丰富 结构化语言 生成的代码质量高 可移植性强 C程序结构 C语言系统的使用 一.启动Dev-C 二、新建源程序 三…

【观察】甲骨文:用“SQL”实现AI的“融会贯通”,打通应用落地的“最后一公里”...

从2022年的ChatGPT&#xff0c;到2024年的Sora&#xff0c;生成式AI和大模型技术正以不可思议的发展速度颠覆着我们的认知。刚刚过去的一年&#xff0c;国内的“百模大战”更让大模型站上了市场“风口”&#xff0c;通过更为泛化的能力&#xff0c;赋予了千行万业数智化无限的想…

ChatGPT提问获取高质量答案的艺术PDF下载书籍推荐分享

ChatGPT高质量prompt技巧分享pdf&#xff0c; ChatGPT提问获取高质量答案的艺术pdf。本书是一本全面的指南&#xff0c;介绍了各种 Prompt 技术的理解和利用&#xff0c;用于从 ChatGPTmiki sharing中生成高质量的答案。我们将探讨如何使用不同的 Prompt 工程技术来实现不同的目…

aws sap认证考试如何轻松通过

如何高效备考AWS SAP (Solutions Architect Professional) 认证? AWS SAP认证是AWS认证体系中难度最高的认证之一,要通过这个考试确实需要下一番功夫。但通过合理规划和有效准备,你可以提高通过的几率。以下是一些建议: 评估起点 首先诚实地评估自己的AWS知识水平和实践经验。…

聚鼎科技:装饰画未来前景好不好

在这个快速变化的时代&#xff0c;装饰画作为家居装饰和艺术表达的一种形式&#xff0c;其未来前景备受各界关注。随着人们审美的多元化和居住环境的个性化需求增长&#xff0c;装饰画逐渐从传统领域延伸到更加广阔的生活空间。 装饰画的市场潜力不容小觑。现代社会对美的追求日…

重塑肌肤DNA!华贝甄选解锁生命活力密码

在探索生命奥秘与健康的征途中&#xff0c;华贝甄选携手前沿干细胞科技&#xff0c;为您开启一场前所未有的健康革命。我们深知&#xff0c;生命的活力源自细胞的不懈更新与修复&#xff0c;而干细胞&#xff0c;正是这场生命奇迹的钥匙。 【重塑内分泌平衡&#xff0c;焕发自…

spring boot的学习--Springboot的Web开发(3)

1. 简介 1.1 创建springboot应用,选中我们需要的模块 1.2 springBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来 1.3 自己编写业务代码 顺便回顾下上一篇的自动装配 这个场景SpringBoot帮我们配置了什么&#xff1f;能不能修改&#xff1f;能修…

vue 搭建 pinia

文章目录 环境设置存储读取数据【 storeToRefs】借助storeToRefs将store中的数据转为ref对象&#xff0c;方便在模板中使用【getters】当state中的数据&#xff0c;需要经过处理后再使用时&#xff0c;可以使用getters配置【$subscribe】通过 store 的 $subscribe() 方法侦听 s…

韦尔股份:深蹲起跳?

利润大增7倍&#xff0c;是反转信号还是回光返照&#xff1f; 今天我们聊聊光学半导体龙头——韦尔股份。 上周末&#xff0c;韦尔股份发布半年业绩预告&#xff0c;预计上半年净利润13至14亿&#xff0c;同比增幅高达 754%至 819%。 然而&#xff0c;回首 2023 年它的净利仅 …

代码随想录算法训练营第二十九天

452. 用最少数量的箭引爆气球 这道题目我原本的想法是只要当前的气球半径范围在已有的箭头能够击穿的气球半径内就可以实现 但是 箭射出去的地方是一个值 而不是一个范围 因此有相同的重叠范围的许多气球并一定都有相同的值&#xff0c;因此这种方法不可取 这题的主要局部最…

『Django』自带的后台

theme: smartblue 本文简介 点赞 关注 收藏 学会了 上一篇讲了 Django 操作 MySQL 的方法&#xff0c;讲了如何创建模型&#xff0c;如何对数据库做增删改查的操作。但每次修改数据都要写代码&#xff0c;多少有点麻烦。 有没有简单一点的方法呢&#xff1f; 有的有的&#…

kotlin Flow 学习指南 (三)最终篇

目录 前言Flow生命周期StateFlow 替代LiveDataSharedFlow其他常见应用场景处理复杂、耗时逻辑存在依赖关系的接口请求组合多个接口的数据 Flow使用注意事项总结 前言 前面两篇文章&#xff0c;介绍了Flow是什么&#xff0c;如何使用&#xff0c;以及相关的操作符进阶&#xff…

leetcode 1421 净现值查询(postgresql)

需求 表: NPV ---------------------- | Column Name | Type | ---------------------- | id | int | | year | int | | npv | int | ---------------------- (id, year) 是该表主键. 该表有每一笔存货的年份, id 和对应净现值的信息. 表: Queries ---------------------- …