diff options
-rwxr-xr-x | board/rockchip/common/Makefile | 7 | ||||
-rwxr-xr-x | board/rockchip/common/storage/storage.c | 188 | ||||
-rwxr-xr-x | board/rockchip/common/storage/storage.h | 16 |
3 files changed, 211 insertions, 0 deletions
diff --git a/board/rockchip/common/Makefile b/board/rockchip/common/Makefile new file mode 100755 index 0000000000..1ecebc5a3d --- /dev/null +++ b/board/rockchip/common/Makefile @@ -0,0 +1,7 @@ +# +# (C) Copyright 2008 - 2015 Fuzhou Rockchip Electronics Co., Ltd +# Peter, Software Engineering, <superpeter.cai@gmail.com>. +# +# SPDX-License-Identifier: GPL-2.0+ +# +obj-y += storage/storage.o
\ No newline at end of file diff --git a/board/rockchip/common/storage/storage.c b/board/rockchip/common/storage/storage.c new file mode 100755 index 0000000000..299ba1f10b --- /dev/null +++ b/board/rockchip/common/storage/storage.c @@ -0,0 +1,188 @@ +/* + * (C) Copyright 2008 Fuzhou Rockchip Electronics Co., Ltd + * Peter, Software Engineering, <superpeter.cai@gmail.com>. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <mmc.h> +#include <part.h> +#include <malloc.h> + +#include "storage.h" + +#define VENDOR_TAG 0x524B5644 /* tag for vendor check */ +#define VENDOR_PART_NUM 4 /* The VendorStorage partition contains the number of Vendor blocks */ +#define VENDOR_PART_SIZE 128 /* The number of memory blocks used by each Vendor structure(128*512Bytes=64KB) */ +#define VENDOR_ITEM_NUM 126 /* The maximum number of items in each Vendor block */ +#define VENDOR_BTYE_ALIGN 0x3F /* align to 64 bytes */ + +struct vendor_item { + u16 id; + u16 offset; + u16 size; + u16 flag; +}; + +struct vendor_info { + u32 tag; + /* Together with version2, it is used to select + * which Vendor block is currently active. + */ + u32 version; + u16 next_index; + u16 item_num; + u16 free_offset; + u16 free_size; + struct vendor_item item[VENDOR_ITEM_NUM]; + /* The entire Vendor block size is:VENDOR_PART_SIZE * 512Bytes=64KB. + * The total size of the fields above this comment is:4B+4B+2B+2B+2B+2+VENDOR_ITEM_NUM*8B=1024B. + * The total size of the fields after the data element is:4B. + * So the size of the data element is:(VENDOR_PART_SIZE * 512B)-1024B-4B. + */ + u8 data[VENDOR_PART_SIZE * 512 - 1024 - 4]; + /* Used to ensure the current Vendor block content integrity. + * Normally, the value is equal to version; + * Others, the contents of this Vendor block is incorrect. + */ + u32 version2; +}; + +static struct vendor_info g_vendor; + +static int vendor_ops(u8 *buffer, u32 addr, u32 n_sec, int write) +{ + struct blk_desc *dev_desc; + disk_partition_t part_info; + char* part_name = NULL; + unsigned long ret = 0; /* return value */ + + /* get vendor_storage name */ + part_name = getenv("RkVendorStorage#"); + if(!part_name){ + printf("ERROR:%s RkVendorStorage# is not set.\n", __func__); + return -EPERM; + } + dev_desc = blk_get_dev("mmc", 0); + if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) { + printf("ERROR:%s Invalid mmc device\n", __func__); + return -ENODEV; + } + if (part_get_info_by_name(dev_desc, part_name, &part_info) < 0) { + printf("ERROR:%s Could not find %s partition\n", __func__, part_name); + return -EINVAL; + } + + if (write) + ret = blk_dwrite(dev_desc, addr+part_info.start, n_sec, buffer); + else + ret = blk_dread(dev_desc, addr+part_info.start, n_sec, buffer); + + return ((ret>0) ? 0 : (-1)); +} + +int vendor_storage_init(char* part_name) +{ + u32 i, max_ver, max_index; + u8 *p_buf; + int ret; + + /* set vendor storage part name */ + setenv("RkVendorStorage#", part_name); + max_ver = 0; + max_index = 0; + for (i = 0; i < VENDOR_PART_NUM; i++) { + /* read first 512 bytes */ + p_buf = (u8 *)&g_vendor; + ret = vendor_ops(p_buf, VENDOR_PART_SIZE * i, 1, 0); + if (ret) + return ret; + /* read last 512 bytes */ + p_buf += (VENDOR_PART_SIZE - 1) * 512; + ret = vendor_ops(p_buf, VENDOR_PART_SIZE * (i + 1) - 1, 1, 0); + if (ret) + return ret; + if ((g_vendor.tag == VENDOR_TAG) && + (g_vendor.version2 == g_vendor.version)) { + if (max_ver < g_vendor.version) { + max_index = i; + max_ver = g_vendor.version; + } + } + } + + if (max_ver) { + ret = vendor_ops((u8 *) &g_vendor, VENDOR_PART_SIZE * max_index, VENDOR_PART_SIZE, 0); + if (ret) + return ret; + } else { + memset(&g_vendor, 0, sizeof(g_vendor)); + g_vendor.version = 1; + g_vendor.tag = VENDOR_TAG; + g_vendor.version2 = g_vendor.version; + g_vendor.free_size = sizeof(g_vendor.data); + } + + return 0; +} + +int vendor_storage_read(u16 id, void *pbuf, u16 size) +{ + u32 i; + 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); + return size; + } + } + + return -EINVAL; +} + +int vendor_storage_write(u16 id, void *pbuf, u16 size) +{ + u32 i, align_size; + u16 next_index; + struct vendor_item *item; + + next_index = g_vendor.next_index; + align_size = (size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN); + if (size > align_size) + return -EINVAL; + for (i = 0; i < g_vendor.item_num; i++) { + if (g_vendor.item[i].id == id) { + memcpy(&g_vendor.data[g_vendor.item[i].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 >= VENDOR_PART_NUM) + g_vendor.next_index = 0; + return vendor_ops((u8 *) &g_vendor, VENDOR_PART_SIZE * next_index, + VENDOR_PART_SIZE, 1); + } + } + 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 >= VENDOR_PART_NUM) + g_vendor.next_index = 0; + return vendor_ops((u8 *) &g_vendor, VENDOR_PART_SIZE * next_index, + VENDOR_PART_SIZE, 1); + } + + return -ENOSPC; +} diff --git a/board/rockchip/common/storage/storage.h b/board/rockchip/common/storage/storage.h new file mode 100755 index 0000000000..9b255f14d3 --- /dev/null +++ b/board/rockchip/common/storage/storage.h @@ -0,0 +1,16 @@ +/* + * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd + * Peter, Software Engineering, <superpeter.cai@gmail.com>. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _STORAGE_H +#define _STORAGE_H + +/* Interface declaration */ +int vendor_storage_init(char* part_name); +int vendor_storage_read(u16 id, void *pbuf, u16 size); +int vendor_storage_write(u16 id, void *pbuf, u16 size); + +#endif /* _STORAGE_H */ + |