RK3568平台(vendor篇)vendor storage分区

一.简介

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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IP 地址与 CDN 性能优化

内容分发网络&#xff08;CDN&#xff09;就是通过内容分配到离用户最优的服务器来提高访问速度。而IP地址如何分配与管理就是CND技术的基础。本文将来探讨介绍CDN中的IP地址分配与管理&#xff0c;以及如何通过CDN优化网络性能。 首先我们来了解CDN的基本原理 CDN是一种分布式…

宏任务与微任务对比【前端异步】

目录 简介微任务与宏任务的基本概念宏任务&#xff08;Macrotasks&#xff09;微任务&#xff08;Microtasks&#xff09;宏任务示例微任务示例微任务与宏任务的执行时序 结论 简介 在JavaScript的异步编程中&#xff0c;理解事件循环&#xff08;Event Loop&#xff09;是至关…

Elasticsearch:Node.js ECS 日志记录 - Morgan

这是之前系列文章&#xff1a; Elasticsearch&#xff1a;Node.js ECS 日志记录 - Pino Elasticsearch&#xff1a;Node.js ECS 日志记录 - Winston 中的第三篇文章。在今天的文章中&#xff0c;我将描述如何使用 Morgan 包针对 Node.js 应用进行日子记录。此 Morgan Node.j…

SpringCloud学习

认识微服务 1.单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包部署 优点&#xff1a;架构简单 部署成本低 缺点&#xff1a;耦合度高 2.分布式架构&#xff1a;根据业务功能对系统进行拆分&#xff0c;每个业务模块作为独立项目开发&…

使用来此加密申请多域名SSL证书

在数字化时代的浪潮中&#xff0c;网站的安全性已成为企业和个人不可或缺的一部分。特别是在数据传输和用户隐私保护方面&#xff0c;SSL证书的作用愈发显著。 申请多域名SSL证书步骤 1、登录来此加密网站&#xff0c;输入域名&#xff0c;可以勾选泛域名和包含根域。 2、选择…

【结构型模式-代理模式】

概述 由于某些原因需要给某对象提供一个代理以控制该对象的访问。这时&#xff0c;访问对象不适合或者不能直接引用目标对象&#xff0c;代理对象作为访问对象与目标对象之间的中介。 Java中的代理按照代理类生成时机不同又分为静态代理和动态代理。静态代理代理类在编译期就生…

手撸俄罗斯方块(五)——游戏主题

手撸俄罗斯方块&#xff08;五&#xff09;——游戏主题 当确定游戏载体&#xff08;如控制台&#xff09;后&#xff0c;界面将呈现出来。但是游戏的背景色、方块的颜色、方框颜色都应该支持扩展。 当前游戏也是如此&#xff0c;引入了 Theme 的概念&#xff0c;支持主题的扩…

ADS基础教程24 - Gerber文件的导入

EM介绍 一、引言二、基本概念1.仿真文件下载2.仿真文件介绍 二、导入步骤1.新建workspace2.选择Layout结构3.导入设计4.选择文件类型5.导入文件6.预览文件内容7.铜皮离散问题 四、总结 一、引言 本章节开始介绍在ADS中进行PCB仿真&#xff0c;首先讲解如何将Gerber文件导入到A…

顺序结构 ( 四 ) —— 标准数据类型 【互三互三】

序 C语言提供了丰富的数据类型&#xff0c;本节介绍几种基本的数据类型&#xff1a;整型、实型、字符型。它们都是系统定义的简单数据类型&#xff0c;称为标准数据类型。 整型&#xff08;integer&#xff09; 在C语言中&#xff0c;整型类型标识符为int。根据整型变量的取值范…

【RHCE】基于用户认证和TLS加密的HTTP服务(HTTPS)

目录 一、创建用户账号 二、TLS加密 三、配置http服务子配置文件 四、创建访问http服务的文件夹以及输入重定向到文件 五、配置Linux本地仓库以及Windows下的本地仓库 六、基础操作 七、测试 一、创建用户账号 用户认证 # 创建两个账户 [rootlocalhost ~]# htpasswd -…

YOLOv10改进 | 损失函数篇 | SlideLoss、FocalLoss、VFLoss分类损失函数助力细节涨点(全网最全)

一、本文介绍 本文给大家带来的是分类损失 SlideLoss、VFLoss、FocalLoss损失函数&#xff0c;我们之前看那的那些IoU都是边界框回归损失&#xff0c;和本文的修改内容并不冲突&#xff0c;所以大家可以知道损失函数分为两种一种是分类损失另一种是边界框回归损失&#xff0c;…

【安全设备】数据库审计

一、什么是数据库审计 数据库审计&#xff08;简称DBAudit&#xff09;是一种以安全事件为中心&#xff0c;实时记录网络上的数据库活动&#xff0c;并对数据库操作进行细粒度审计的合规性管理技术。它通过对用户访问行为的记录、分析和汇报&#xff0c;帮助用户事后生成合规报…

一套基于 Ant Design 和 Blazor 的开源企业级组件库

前言 今天大姚给大家分享一套基于Ant Design和Blazor的开源&#xff08;MIT License&#xff09;、免费的企业级组件库&#xff08;喜欢Ant Design风格的同学推荐使用&#xff09;&#xff1a;Ant Design Blazor。 项目特性 提炼自企业级中后台产品的交互语言和视觉风格。 开…

Codeforces Round #956 (Div. 2) and ByteRace 2024 E. I Love Balls(概率期望)

题目 思路来源 官方题解 题解 特殊球不会改变普通球的顺序&#xff0c;所以都是alice拿一半里较多的部分 n-k1一半向上取整就是(n-k2)/2&#xff0c;同理n-k个一般向上取整(n-k1)/2 每个特殊球独立地来看&#xff0c;在每个空隙的概率相同 所以分别统计特殊球和非特殊球的…

《Windows API每日一练》9.1.5 自定义资源

自定义资源&#xff08;Custom Resources&#xff09;是在 Windows 程序中使用的一种资源类型&#xff0c;用于存储应用程序特定的数据、图像、音频、二进制文件等。通过自定义资源&#xff0c;开发者可以将应用程序所需的各种资源文件集中管理和存储&#xff0c;便于在程序中访…

华为HCIP Datacom H12-821 卷34

1.单选题 防火墙默认已经创建了一些安全区域,以下哪一个安全区域不是防火墙上默认存在的? A、Trust B、DMZ C、Internet D、Local 正确答案&#xff1a; C 解析&#xff1a; 防火墙默认情况下为我们提供了三个安全区域&#xff0c;分别是 Trust、DMZ和Untrust 2.判断题 …

【RHCE】实验(HTTP,DNS,SELinux,firewalld的运用)

一、题目 二、主服务器配置 1.下载HTTP服务&#xff0c;DNS服务 [rootlocalhost ~]# yum install -y httpd bind 2.开启防火墙&#xff0c;放行服务 # 开启防火墙 [rootlocalhost ~]# systemctl start firewalld # 放行服务 [rootlocalhost ~]# firewall-cmd --add-service…

日常学习-20240710

1、一次一千万条数据插入和删除案例&#xff1a; 第一次&#xff1a;插入--批量插入&#xff0c;每次插入5000条数据&#xff0c;总耗时28min,数据无异常 删除--通过sql语句一次性删除&#xff0c;总耗时1h52min;一次删除的数据过多导致mysql的备份恢复文件极其庞大&#xff0…

在CentOS7虚拟机上使用Ollama本地部署Llama3大模型中文版+Open WebUI

一、创建虚拟机 1.1按照常规的CentOS教程来安装就行&#xff0c;我用的是以下版本&#xff1a; VMware版本&#xff1a;VMware Workstation Full v12.1.0-3272444 中文正式版 镜像版本&#xff1a;CentOS-7-x86_64-DVD-2009 1.2虚拟机配置参数&#xff0c;如下&#xff1a; 二…

彩虹小插画:成都亚恒丰创教育科技有限公司

彩虹小插画&#xff1a;色彩斑斓的梦幻世界 在繁忙的生活节奏中&#xff0c;总有一抹温柔的色彩能悄然触动心弦&#xff0c;那就是彩虹小插画带来的梦幻与宁静。彩虹&#xff0c;这一自然界的奇迹&#xff0c;被艺术家们巧妙地融入小巧精致的插画之中&#xff0c;不仅捕捉了瞬…