xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/vendor.c (revision 2a3fb7bb049d69d96f3bc7dae8caa756fdc8a613)
1 /*
2  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <malloc.h>
9 #include <asm/arch/vendor.h>
10 #include <boot_rkimg.h>
11 #include <nand.h>
12 #include <part.h>
13 
14 /* tag for vendor check */
15 #define VENDOR_TAG		0x524B5644
16 /* The Vendor partition contains the number of Vendor blocks */
17 #define MTD_VENDOR_PART_NUM	1
18 #define NAND_VENDOR_PART_NUM	2
19 #define VENDOR_PART_NUM		4
20 /* align to 64 bytes */
21 #define VENDOR_BTYE_ALIGN	0x3F
22 #define VENDOR_BLOCK_SIZE	512
23 
24 /* --- Emmc define --- */
25 /* Starting address of the Vendor in memory. */
26 #define EMMC_VENDOR_PART_OFFSET		(1024 * 7)
27 /*
28  * The number of memory blocks used by each
29  * Vendor structure(128 * 512B = 64KB)
30  */
31 #define EMMC_VENDOR_PART_BLKS		128
32 /* The maximum number of items in each Vendor block */
33 #define EMMC_VENDOR_ITEM_NUM		126
34 
35 /* --- Spi Nand/SLC/MLC large capacity case define --- */
36 /* The Vendor partition contains the number of Vendor blocks */
37 #define NAND_VENDOR_PART_OFFSET		0
38 /*
39  * The number of memory blocks used by each
40  * Vendor structure(8 * 512B = 4KB)
41  */
42 #define NAND_VENDOR_PART_BLKS		128
43 /* The maximum number of items in each Vendor block */
44 #define NAND_VENDOR_ITEM_NUM		126
45 
46 /* --- Spi/Spi Nand/SLC/MLC small capacity case define --- */
47 /* The Vendor partition contains the number of Vendor blocks */
48 #define	FLASH_VENDOR_PART_OFFSET	8
49 /*
50  * The number of memory blocks used by each
51  * Vendor structure(8 * 512B = 4KB)
52  */
53 #define FLASH_VENDOR_PART_BLKS		8
54 /* The maximum number of items in each Vendor block */
55 #define FLASH_VENDOR_ITEM_NUM		62
56 
57 /* Vendor uinit test define */
58 int vendor_storage_test(void);
59 
60 struct vendor_hdr {
61 	u32	tag;
62 	u32	version;
63 	u16	next_index;
64 	u16	item_num;
65 	u16	free_offset; /* Free space offset */
66 	u16	free_size; /* Free space size */
67 };
68 
69 /*
70  * Different types of Flash vendor info are different.
71  * EMMC:EMMC_VENDOR_PART_BLKS * BLOCK_SIZE(512) = 64KB;
72  * Spi Nor/Spi Nand/SLC/MLC: FLASH_VENDOR_PART_BLKS *
73  * BLOCK_SIZE(512) = 4KB.
74  * hash: For future expansion.
75  * version2: Together with hdr->version, it is used to
76  * ensure the current Vendor block content integrity.
77  *   (version2 == hdr->version):Data valid;
78  *   (version2 != hdr->version):Data invalid.
79  */
80 struct vendor_info {
81 	struct vendor_hdr *hdr;
82 	struct vendor_item *item;
83 	u8 *data;
84 	u32 *hash;
85 	u32 *version2;
86 };
87 
88 struct mtd_nand_info {
89 	u32 part_offset;
90 	u32 part_size;
91 	u32 blk_offset;
92 	u32 page_offset;
93 	u32 version;
94 	u32 ops_size;
95 	u32 page_size;
96 	u32 blk_size;
97 };
98 
99 /*
100  * Calculate the offset of each field for emmc.
101  * Emmc vendor info size: 64KB
102  */
103 #define EMMC_VENDOR_INFO_SIZE	(EMMC_VENDOR_PART_BLKS * VENDOR_BLOCK_SIZE)
104 #define EMMC_VENDOR_DATA_OFFSET	(sizeof(struct vendor_hdr) + EMMC_VENDOR_ITEM_NUM * sizeof(struct vendor_item))
105 #define EMMC_VENDOR_HASH_OFFSET (EMMC_VENDOR_INFO_SIZE - 8)
106 #define EMMC_VENDOR_VERSION2_OFFSET (EMMC_VENDOR_INFO_SIZE - 4)
107 
108 /*
109  * Calculate the offset of each field for spi nand/slc/mlc large capacity case.
110  * Flash vendor info size: 4KB
111  */
112 #define NAND_VENDOR_INFO_SIZE	(NAND_VENDOR_PART_BLKS * VENDOR_BLOCK_SIZE)
113 #define NAND_VENDOR_DATA_OFFSET	(sizeof(struct vendor_hdr) + NAND_VENDOR_ITEM_NUM * sizeof(struct vendor_item))
114 #define NAND_VENDOR_HASH_OFFSET (NAND_VENDOR_INFO_SIZE - 8)
115 #define NAND_VENDOR_VERSION2_OFFSET (NAND_VENDOR_INFO_SIZE - 4)
116 
117 /*
118  * Calculate the offset of each field for spi nor/spi nand/slc/mlc large small capacity case.
119  * Flash vendor info size: 4KB
120  */
121 #define FLASH_VENDOR_INFO_SIZE	(FLASH_VENDOR_PART_BLKS * VENDOR_BLOCK_SIZE)
122 #define FLASH_VENDOR_DATA_OFFSET (sizeof(struct vendor_hdr) + FLASH_VENDOR_ITEM_NUM * sizeof(struct vendor_item))
123 #define FLASH_VENDOR_HASH_OFFSET (FLASH_VENDOR_INFO_SIZE - 8)
124 #define FLASH_VENDOR_VERSION2_OFFSET (FLASH_VENDOR_INFO_SIZE - 4)
125 
126 /* vendor info */
127 static struct vendor_info vendor_info;
128 /* The storage type of the device */
129 static int bootdev_type;
130 
131 #ifdef CONFIG_MTD_BLK
132 static struct mtd_nand_info nand_info;
133 static const char *vendor_mtd_name = "vnvm";
134 #endif
135 
136 /* vendor private read write ops*/
137 static	int (*_flash_read)(struct blk_desc *dev_desc,
138 			   u32 sec,
139 			   u32 n_sec,
140 			   void *buffer);
141 static	int (*_flash_write)(struct blk_desc *dev_desc,
142 			    u32 sec,
143 			    u32 n_sec,
144 			    void *buffer);
145 
146 int flash_vendor_dev_ops_register(int (*read)(struct blk_desc *dev_desc,
147 					      u32 sec,
148 					      u32 n_sec,
149 					      void *p_data),
150 				  int (*write)(struct blk_desc *dev_desc,
151 					       u32 sec,
152 					       u32 n_sec,
153 					       void *p_data))
154 {
155 	if (!_flash_read) {
156 		_flash_read = read;
157 		_flash_write = write;
158 		return 0;
159 	}
160 
161 	return -EPERM;
162 }
163 
164 #ifdef CONFIG_MTD_BLK
165 static int mtd_vendor_storage_init(struct blk_desc *dev_desc)
166 {
167 	struct mtd_info *mtd = (struct mtd_info *)dev_desc->bdev->priv;
168 	disk_partition_t vnvm_part_info;
169 	void *buf = vendor_info.hdr;
170 	int ret, offset;
171 	int part_num, bad_block_size;
172 
173 	memset(&vnvm_part_info, 0x0, sizeof(vnvm_part_info));
174 	part_num = part_get_info_by_name(dev_desc, vendor_mtd_name, &vnvm_part_info);
175 	if (part_num < 0)
176 		return -EIO;
177 
178 	nand_info.part_offset = (u32)vnvm_part_info.start;
179 	nand_info.part_size = (u32)vnvm_part_info.size;
180 	nand_info.page_offset = 0;
181 	nand_info.blk_offset = 0;
182 	nand_info.version = 0;
183 	nand_info.page_size = mtd->writesize >> 9;
184 	nand_info.blk_size = mtd->erasesize >> 9;
185 	nand_info.ops_size = (FLASH_VENDOR_INFO_SIZE + mtd->writesize - 1) /
186 			     mtd->writesize;
187 	nand_info.ops_size *= nand_info.page_size;
188 
189 	/* scan bad block and calculate the real size can be used */
190 	bad_block_size = 0;
191 	for (offset = 0; offset < nand_info.part_size; offset += nand_info.blk_size) {
192 		if (mtd_block_isbad(mtd, (nand_info.part_offset + offset) << 9))
193 			bad_block_size += nand_info.blk_size;
194 	}
195 	nand_info.part_size -= bad_block_size;
196 
197 	for (offset = 0; offset < nand_info.part_size; offset += nand_info.blk_size) {
198 		ret = blk_dread(dev_desc, nand_info.part_offset + offset,
199 				FLASH_VENDOR_INFO_SIZE >> 9,
200 				(u8 *)buf);
201 		debug("%s: read %x version = %x\n", __func__,
202 		      nand_info.part_offset + offset,
203 		      vendor_info.hdr->version);
204 		if (ret == (FLASH_VENDOR_INFO_SIZE >> 9) && vendor_info.hdr->tag == VENDOR_TAG &&
205 		    vendor_info.hdr->version == *vendor_info.version2) {
206 			if (vendor_info.hdr->version > nand_info.version) {
207 				nand_info.version = vendor_info.hdr->version;
208 				nand_info.blk_offset = offset;
209 			}
210 		}
211 	}
212 
213 	debug("%s: nand_info.version = %x %x\n", __func__, nand_info.version, nand_info.blk_offset);
214 	if (nand_info.version) {
215 		for (offset = nand_info.blk_size  - nand_info.ops_size;
216 		     offset >= 0;
217 		     offset -= nand_info.ops_size) {
218 			ret = blk_dread(dev_desc, nand_info.part_offset +
219 					nand_info.blk_offset + offset,
220 					1,
221 					(u8 *)buf);
222 
223 			/* the page is not programed */
224 			if (ret == 1 && vendor_info.hdr->tag == 0xFFFFFFFF)
225 				continue;
226 
227 			/* point to the last programed page */
228 			if (nand_info.page_offset < offset)
229 				nand_info.page_offset = offset;
230 
231 			if (ret != 1 || vendor_info.hdr->tag != VENDOR_TAG)
232 				continue;
233 			ret = blk_dread(dev_desc, nand_info.part_offset +
234 					nand_info.blk_offset + offset,
235 					FLASH_VENDOR_INFO_SIZE >> 9,
236 					(u8 *)buf);
237 			debug("%s: read %x version = %x\n", __func__,
238 			      nand_info.part_offset + nand_info.blk_offset  + offset,
239 			      vendor_info.hdr->version);
240 
241 			if (ret == (FLASH_VENDOR_INFO_SIZE >> 9)  && vendor_info.hdr->tag == VENDOR_TAG &&
242 			    vendor_info.hdr->version == *vendor_info.version2) {
243 				nand_info.version = vendor_info.hdr->version;
244 				break;
245 			}
246 		}
247 	} else {
248 		memset((u8 *)vendor_info.hdr, 0, FLASH_VENDOR_INFO_SIZE);
249 		vendor_info.hdr->version = 1;
250 		vendor_info.hdr->tag = VENDOR_TAG;
251 		vendor_info.hdr->free_size =
252 			((u32)(size_t)vendor_info.hash
253 			- (u32)(size_t)vendor_info.data);
254 		*vendor_info.version2 = vendor_info.hdr->version;
255 	}
256 
257 	return 0;
258 }
259 
260 static int mtd_vendor_write(struct blk_desc *dev_desc,
261 			    u32 sec,
262 			    u32 n_sec,
263 			    void *buf)
264 {
265 	int ret, count = 0, err = 0;
266 
267 re_write:
268 	debug("[Vendor INFO]:%s page_offset=0x%x count = %x\n", __func__, nand_info.part_offset +
269 	      nand_info.blk_offset + nand_info.page_offset, count);
270 	if (nand_info.page_offset >= nand_info.blk_size) {
271 		nand_info.blk_offset += nand_info.blk_size;
272 		if (nand_info.blk_offset >= nand_info.part_size)
273 			nand_info.blk_offset = 0;
274 		nand_info.page_offset = 0;
275 	}
276 
277 	ret = blk_dwrite(dev_desc, nand_info.part_offset +
278 			 nand_info.blk_offset + nand_info.page_offset,
279 			 FLASH_VENDOR_INFO_SIZE >> 9,
280 			 (u8 *)buf);
281 
282 	nand_info.page_offset += nand_info.ops_size;
283 	if (ret != (FLASH_VENDOR_INFO_SIZE >> 9)) {
284 		err++;
285 		if (err > 3)
286 			return -EIO;
287 		goto re_write;
288 	}
289 
290 	count++;
291 	/* write 2 copies for reliability */
292 	if (count < 2)
293 		goto re_write;
294 
295 	return ret;
296 }
297 #endif
298 
299 /**********************************************************/
300 /*              vendor API implementation                 */
301 /**********************************************************/
302 static int vendor_ops(u8 *buffer, u32 addr, u32 n_sec, int write)
303 {
304 	struct blk_desc *dev_desc;
305 	unsigned int lba = 0;
306 	int ret = 0;
307 
308 	dev_desc = rockchip_get_bootdev();
309 	if (!dev_desc) {
310 		printf("%s: dev_desc is NULL!\n", __func__);
311 		return -ENODEV;
312 	}
313 	/* Get the offset address according to the device type */
314 	switch (dev_desc->if_type) {
315 	case IF_TYPE_MMC:
316 		/*
317 		 * The location of VendorStorage in Flash is shown in the
318 		 * following figure. The starting address of the VendorStorage
319 		 * partition offset is 3.5MB(EMMC_VENDOR_PART_OFFSET*BLOCK_SIZE(512)),
320 		 * and the partition size is 256KB.
321 		 * ----------------------------------------------------
322 		 * |   3.5MB    |  VendorStorage  |                   |
323 		 * ----------------------------------------------------
324 		 */
325 		lba = EMMC_VENDOR_PART_OFFSET;
326 		debug("[Vendor INFO]:VendorStorage offset address=0x%x\n", lba);
327 		break;
328 	case IF_TYPE_RKNAND:
329 	case IF_TYPE_SPINAND:
330 		/*
331 		 * The location of VendorStorage in Flash is shown in the
332 		 * following figure. The starting address of the VendorStorage
333 		 * partition offset is 0KB in FTL vendor block,
334 		 * and the partition size is 128KB.
335 		 * ----------------------------------------------------
336 		 * |  VendorStorage  |                     |
337 		 * ----------------------------------------------------
338 		 */
339 		lba = NAND_VENDOR_PART_OFFSET;
340 		debug("[Vendor INFO]:VendorStorage offset address=0x%x\n", lba);
341 		break;
342 	case IF_TYPE_SPINOR:
343 		/*
344 		 * The location of VendorStorage in Flash is shown in the
345 		 * following figure. The starting address of the VendorStorage
346 		 * partition offset is 4KB (FLASH_VENDOR_PART_OFFSET * BLOCK_SIZE),
347 		 * and the partition size is 16KB.
348 		 * ----------------------------------------------------
349 		 * |   4KB    |  VendorStorage  |                     |
350 		 * ----------------------------------------------------
351 		 */
352 		lba = FLASH_VENDOR_PART_OFFSET;
353 		debug("[Vendor INFO]:VendorStorage offset address=0x%x\n", lba);
354 		break;
355 #ifdef CONFIG_MTD_BLK
356 	case IF_TYPE_MTD:
357 		/*
358 		 * The location of VendorStorage in NAND FLASH or SPI NAND partition "vnvm"
359 		 * is shown in the following figure. The partition size is at least  4
360 		 * NAND FLASH blocks.
361 		 * ----------------------------------------------------
362 		 * |   .....    |  vnvm  |  .......                   |
363 		 * ----------------------------------------------------
364 		 */
365 		lba = 0;
366 		break;
367 #endif
368 	default:
369 		printf("[Vendor ERROR]:Boot device type is invalid!\n");
370 		return -ENODEV;
371 	}
372 	if (write) {
373 		if (_flash_write)
374 			ret = _flash_write(dev_desc, lba + addr, n_sec, buffer);
375 		else
376 			ret = blk_dwrite(dev_desc, lba + addr, n_sec, buffer);
377 	} else {
378 		if (_flash_read)
379 			ret = _flash_read(dev_desc, lba + addr, n_sec, buffer);
380 		else
381 			ret = blk_dread(dev_desc, lba + addr, n_sec, buffer);
382 	}
383 
384 	debug("[Vendor INFO]:op=%s, ret=%d\n", write ? "write" : "read", ret);
385 
386 	return ret;
387 }
388 
389 /*
390  * The VendorStorage partition is divided into four parts
391  * (vendor 0-3) and its structure is shown in the following figure.
392  * The init function is used to select the latest and valid vendor.
393  *
394  * |******************** FLASH ********************|
395  * -------------------------------------------------
396  * |  vendor0  |  vendor1  |  vendor2  |  vendor3  |
397  * -------------------------------------------------
398  * Notices:
399  *   1. "version" and "version2" are used to verify that the vendor
400  *      is valid (equal is valid).
401  *   2. the "version" value is larger, indicating that the current
402  *      verndor data is new.
403  */
404 int vendor_storage_init(void)
405 {
406 	int ret = 0;
407 	int ret_size;
408 	u8 *buffer;
409 	u32 size, i;
410 	u32 max_ver = 0;
411 	u32 max_index = 0;
412 	u16 data_offset, hash_offset, part_num;
413 	u16 version2_offset, part_size;
414 	struct blk_desc *dev_desc;
415 
416 	dev_desc = rockchip_get_bootdev();
417 	if (!dev_desc) {
418 		printf("[Vendor ERROR]:Invalid boot device type(%d)\n",
419 		       bootdev_type);
420 		return -ENODEV;
421 	}
422 
423 	switch (dev_desc->if_type) {
424 	case IF_TYPE_MMC:
425 		size = EMMC_VENDOR_INFO_SIZE;
426 		part_size = EMMC_VENDOR_PART_BLKS;
427 		data_offset = EMMC_VENDOR_DATA_OFFSET;
428 		hash_offset = EMMC_VENDOR_HASH_OFFSET;
429 		version2_offset = EMMC_VENDOR_VERSION2_OFFSET;
430 		part_num = VENDOR_PART_NUM;
431 		break;
432 	case IF_TYPE_RKNAND:
433 	case IF_TYPE_SPINAND:
434 		size = NAND_VENDOR_INFO_SIZE;
435 		part_size = NAND_VENDOR_PART_BLKS;
436 		data_offset = NAND_VENDOR_DATA_OFFSET;
437 		hash_offset = NAND_VENDOR_HASH_OFFSET;
438 		version2_offset = NAND_VENDOR_VERSION2_OFFSET;
439 		part_num = NAND_VENDOR_PART_NUM;
440 		break;
441 	case IF_TYPE_SPINOR:
442 		size = FLASH_VENDOR_INFO_SIZE;
443 		part_size = FLASH_VENDOR_PART_BLKS;
444 		data_offset = FLASH_VENDOR_DATA_OFFSET;
445 		hash_offset = FLASH_VENDOR_HASH_OFFSET;
446 		version2_offset = FLASH_VENDOR_VERSION2_OFFSET;
447 		part_num = VENDOR_PART_NUM;
448 		break;
449 #ifdef CONFIG_MTD_BLK
450 	case IF_TYPE_MTD:
451 		size = FLASH_VENDOR_INFO_SIZE;
452 		part_size = FLASH_VENDOR_PART_BLKS;
453 		data_offset = FLASH_VENDOR_DATA_OFFSET;
454 		hash_offset = FLASH_VENDOR_HASH_OFFSET;
455 		version2_offset = FLASH_VENDOR_VERSION2_OFFSET;
456 		part_num = MTD_VENDOR_PART_NUM;
457 		_flash_write = mtd_vendor_write;
458 		break;
459 #endif
460 	default:
461 		debug("[Vendor ERROR]:Boot device type is invalid!\n");
462 		ret = -ENODEV;
463 		break;
464 	}
465 	/* Invalid bootdev type */
466 	if (ret)
467 		return ret;
468 
469 	/* Initialize */
470 	bootdev_type = dev_desc->if_type;
471 
472 	/* Always use, no need to release */
473 	buffer = (u8 *)malloc(size);
474 	if (!buffer) {
475 		printf("[Vendor ERROR]:Malloc failed!\n");
476 		return -ENOMEM;
477 	}
478 	/* Pointer initialization */
479 	vendor_info.hdr = (struct vendor_hdr *)buffer;
480 	vendor_info.item = (struct vendor_item *)(buffer + sizeof(struct vendor_hdr));
481 	vendor_info.data = buffer + data_offset;
482 	vendor_info.hash = (u32 *)(buffer + hash_offset);
483 	vendor_info.version2 = (u32 *)(buffer + version2_offset);
484 
485 #ifdef CONFIG_MTD_BLK
486 	if (dev_desc->if_type == IF_TYPE_MTD)
487 		return mtd_vendor_storage_init(dev_desc);
488 #endif
489 
490 	/* Find valid and up-to-date one from (vendor0 - vendor3) */
491 	for (i = 0; i < part_num; i++) {
492 		ret_size = vendor_ops((u8 *)vendor_info.hdr,
493 				      part_size * i, part_size, 0);
494 		if (ret_size != part_size) {
495 			ret = -EIO;
496 			goto out;
497 		}
498 
499 		if ((vendor_info.hdr->tag == VENDOR_TAG) &&
500 		    (*(vendor_info.version2) == vendor_info.hdr->version)) {
501 			if (max_ver < vendor_info.hdr->version) {
502 				max_index = i;
503 				max_ver = vendor_info.hdr->version;
504 			}
505 		}
506 	}
507 
508 	if (max_ver) {
509 		debug("[Vendor INFO]:max_ver=%d, vendor_id=%d.\n", max_ver, max_index);
510 		/*
511 		 * Keep vendor_info the same as the largest
512 		 * version of vendor
513 		 */
514 		if (max_index != (part_num - 1)) {
515 			ret_size = vendor_ops((u8 *)vendor_info.hdr,
516 					       part_size * max_index, part_size, 0);
517 			if (ret_size != part_size) {
518 				ret = -EIO;
519 				goto out;
520 			}
521 		}
522 	} else {
523 		debug("[Vendor INFO]:Reset vendor info...\n");
524 		memset((u8 *)vendor_info.hdr, 0, size);
525 		vendor_info.hdr->version = 1;
526 		vendor_info.hdr->tag = VENDOR_TAG;
527 		/* data field length */
528 		vendor_info.hdr->free_size =
529 			((u32)(size_t)vendor_info.hash
530 			- (u32)(size_t)vendor_info.data);
531 		*(vendor_info.version2) = vendor_info.hdr->version;
532 	}
533 	debug("[Vendor INFO]:ret=%d.\n", ret);
534 
535 out:
536 	return ret;
537 }
538 
539 /*
540  * @id: item id, first 4 id is occupied:
541  *	VENDOR_SN_ID
542  *	VENDOR_WIFI_MAC_ID
543  *	VENDOR_LAN_MAC_ID
544  *	VENDOR_BLUETOOTH_ID
545  * @pbuf: read data buffer;
546  * @size: read bytes;
547  *
548  * return: bytes equal to @size is success, other fail;
549  */
550 int vendor_storage_read(u16 id, void *pbuf, u16 size)
551 {
552 	int ret = 0;
553 	u32 i;
554 	u16 offset;
555 	struct vendor_item *item;
556 
557 	/* init vendor storage */
558 	if (!bootdev_type) {
559 		ret = vendor_storage_init();
560 		if (ret < 0)
561 			return ret;
562 	}
563 
564 	item = vendor_info.item;
565 	for (i = 0; i < vendor_info.hdr->item_num; i++) {
566 		if ((item + i)->id == id) {
567 			debug("[Vendor INFO]:Find the matching item, id=%d\n", id);
568 			/* Correct the size value */
569 			if (size > (item + i)->size)
570 				size = (item + i)->size;
571 			offset = (item + i)->offset;
572 			memcpy(pbuf, (vendor_info.data + offset), size);
573 			return size;
574 		}
575 	}
576 	debug("[Vendor ERROR]:No matching item, id=%d\n", id);
577 
578 	return -EINVAL;
579 }
580 
581 /*
582  * @id: item id, first 4 id is occupied:
583  *	VENDOR_SN_ID
584  *	VENDOR_WIFI_MAC_ID
585  *	VENDOR_LAN_MAC_ID
586  *	VENDOR_BLUETOOTH_ID
587  * @pbuf: write data buffer;
588  * @size: write bytes;
589  *
590  * return: bytes equal to @size is success, other fail;
591  */
592 int vendor_storage_write(u16 id, void *pbuf, u16 size)
593 {
594 	int cnt, ret = 0;
595 	u32 i, next_index, align_size;
596 	struct vendor_item *item;
597 	u16 part_size, max_item_num, offset, part_num;
598 
599 	/* init vendor storage */
600 	if (!bootdev_type) {
601 		ret = vendor_storage_init();
602 		if (ret < 0)
603 			return ret;
604 	}
605 
606 	switch (bootdev_type) {
607 	case IF_TYPE_MMC:
608 		part_size = EMMC_VENDOR_PART_BLKS;
609 		max_item_num = EMMC_VENDOR_ITEM_NUM;
610 		part_num = VENDOR_PART_NUM;
611 		break;
612 	case IF_TYPE_RKNAND:
613 	case IF_TYPE_SPINAND:
614 		part_size = NAND_VENDOR_PART_BLKS;
615 		max_item_num = NAND_VENDOR_ITEM_NUM;
616 		part_num = NAND_VENDOR_PART_NUM;
617 		break;
618 	case IF_TYPE_SPINOR:
619 		part_size = FLASH_VENDOR_PART_BLKS;
620 		max_item_num = FLASH_VENDOR_ITEM_NUM;
621 		part_num = VENDOR_PART_NUM;
622 		break;
623 #ifdef CONFIG_MTD_BLK
624 	case IF_TYPE_MTD:
625 		part_size = FLASH_VENDOR_PART_BLKS;
626 		max_item_num = FLASH_VENDOR_ITEM_NUM;
627 		part_num = MTD_VENDOR_PART_NUM;
628 		break;
629 #endif
630 	default:
631 		ret = -ENODEV;
632 		break;
633 	}
634 	/* Invalid bootdev? */
635 	if (ret < 0)
636 		return ret;
637 
638 	next_index = vendor_info.hdr->next_index;
639 	/* algin to 64 bytes*/
640 	align_size = (size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN);
641 	if (size > align_size)
642 		return -EINVAL;
643 
644 	item = vendor_info.item;
645 	/* If item already exist, update the item data */
646 	for (i = 0; i < vendor_info.hdr->item_num; i++) {
647 		if ((item + i)->id == id) {
648 			debug("[Vendor INFO]:Find the matching item, id=%d\n", id);
649 			offset = (item + i)->offset;
650 			memcpy((vendor_info.data + offset), pbuf, size);
651 			(item + i)->size = size;
652 			vendor_info.hdr->version++;
653 			*(vendor_info.version2) = vendor_info.hdr->version;
654 			vendor_info.hdr->next_index++;
655 			if (vendor_info.hdr->next_index >= part_num)
656 				vendor_info.hdr->next_index = 0;
657 			cnt = vendor_ops((u8 *)vendor_info.hdr, part_size * next_index, part_size, 1);
658 			return (cnt == part_size) ? size : -EIO;
659 		}
660 	}
661 	/*
662 	 * If item does not exist, and free size is enough,
663 	 * creat a new one
664 	 */
665 	if ((vendor_info.hdr->item_num < max_item_num) &&
666 	    (vendor_info.hdr->free_size >= align_size)) {
667 		debug("[Vendor INFO]:Create new Item, id=%d\n", id);
668 		item = vendor_info.item + vendor_info.hdr->item_num;
669 		item->id = id;
670 		item->offset = vendor_info.hdr->free_offset;
671 		item->size = size;
672 
673 		vendor_info.hdr->free_offset += align_size;
674 		vendor_info.hdr->free_size -= align_size;
675 		memcpy((vendor_info.data + item->offset), pbuf, size);
676 		vendor_info.hdr->item_num++;
677 		vendor_info.hdr->version++;
678 		vendor_info.hdr->next_index++;
679 		*(vendor_info.version2) = vendor_info.hdr->version;
680 		if (vendor_info.hdr->next_index >= part_num)
681 			vendor_info.hdr->next_index = 0;
682 
683 		cnt = vendor_ops((u8 *)vendor_info.hdr, part_size * next_index, part_size, 1);
684 		return (cnt == part_size) ? size : -EIO;
685 	}
686 	debug("[Vendor ERROR]:Vendor has no space left!\n");
687 
688 	return -ENOMEM;
689 }
690 
691 /**********************************************************/
692 /*              vendor API uinit test                      */
693 /**********************************************************/
694 /* Reset the vendor storage space to the initial state */
695 static void vendor_test_reset(void)
696 {
697 	u16 i, part_size, part_num;
698 	u32 size;
699 
700 	switch (bootdev_type) {
701 	case IF_TYPE_MMC:
702 		size = EMMC_VENDOR_INFO_SIZE;
703 		part_size = EMMC_VENDOR_PART_BLKS;
704 		part_num = VENDOR_PART_NUM;
705 		break;
706 	case IF_TYPE_RKNAND:
707 	case IF_TYPE_SPINAND:
708 		size = NAND_VENDOR_INFO_SIZE;
709 		part_size = NAND_VENDOR_PART_BLKS;
710 		part_num = NAND_VENDOR_PART_NUM;
711 		break;
712 	case IF_TYPE_SPINOR:
713 		size = FLASH_VENDOR_INFO_SIZE;
714 		part_size = FLASH_VENDOR_PART_BLKS;
715 		part_num = VENDOR_PART_NUM;
716 		break;
717 	default:
718 		size = 0;
719 		part_size = 0;
720 		break;
721 	}
722 	/* Invalid bootdev? */
723 	if (!size)
724 		return;
725 
726 	memset((u8 *)vendor_info.hdr, 0, size);
727 	vendor_info.hdr->version = 1;
728 	vendor_info.hdr->tag = VENDOR_TAG;
729 	/* data field length */
730 	vendor_info.hdr->free_size = (unsigned long)vendor_info.hash -
731 				     (unsigned long)vendor_info.data;
732 	*(vendor_info.version2) = vendor_info.hdr->version;
733 	/* write to flash. */
734 	for (i = 0; i < part_num; i++)
735 		vendor_ops((u8 *)vendor_info.hdr, part_size * i, part_size, 1);
736 }
737 
738 /*
739  * A total of four tests
740  * 1.All items test.
741  * 2.Overrides the maximum number of items test.
742  * 3.Single Item memory overflow test.
743  * 4.Total memory overflow test.
744  */
745 int vendor_storage_test(void)
746 {
747 	u16 id, size, j, item_num;
748 	u32 total_size;
749 	u8 *buffer = NULL;
750 	int ret = 0;
751 
752 	if (!bootdev_type) {
753 		ret = vendor_storage_init();
754 		if (ret) {
755 			printf("%s: vendor storage init failed, ret=%d\n",
756 			       __func__, ret);
757 			return ret;
758 		}
759 	}
760 
761 	/*
762 	 * Calculate the maximum number of items and the maximum
763 	 * allocable memory for each item.
764 	 */
765 	switch (bootdev_type) {
766 	case IF_TYPE_MMC:
767 		item_num = EMMC_VENDOR_ITEM_NUM;
768 		total_size = (unsigned long)vendor_info.hash -
769 			     (unsigned long)vendor_info.data;
770 		size = total_size / item_num;
771 		break;
772 	case IF_TYPE_RKNAND:
773 	case IF_TYPE_SPINAND:
774 		item_num = NAND_VENDOR_ITEM_NUM;
775 		total_size = (unsigned long)vendor_info.hash -
776 			     (unsigned long)vendor_info.data;
777 		size = total_size / item_num;
778 		break;
779 	case IF_TYPE_SPINOR:
780 	case IF_TYPE_MTD:
781 		item_num = FLASH_VENDOR_ITEM_NUM;
782 		total_size = (unsigned long)vendor_info.hash -
783 			     (unsigned long)vendor_info.data;
784 		size = total_size / item_num;
785 		break;
786 	default:
787 		total_size = 0;
788 		break;
789 	}
790 	/* Invalid bootdev? */
791 	if (!total_size)
792 		return -ENODEV;
793 	/* 64 bytes are aligned and rounded down */
794 	if (size > 64)
795 		size = (size / 64) * 64;
796 	/* malloc memory */
797 	buffer = (u8 *)malloc(size);
798 	if (!buffer) {
799 		printf("[Vendor Test]:Malloc failed(size=%d)!\n", size);
800 		return -ENOMEM;
801 	}
802 	printf("[Vendor Test]:Test Start...\n");
803 	printf("[Vendor Test]:Before Test, Vendor Resetting.\n");
804 	if (bootdev_type != IF_TYPE_MTD)
805 		vendor_test_reset();
806 
807 	/* FIRST TEST: test all items can be used correctly */
808 	printf("[Vendor Test]:<All Items Used> Test Start...\n");
809 	printf("[Vendor Test]:item_num=%d, size=%d.\n", item_num, size);
810 	/*
811 	 * Write data, then read the data, and compare the
812 	 * data consistency
813 	 */
814 	for (id = 0; id < item_num; id++) {
815 		memset(buffer, id, size);
816 		ret = vendor_storage_write(id, buffer, size);
817 		if (ret < 0) {
818 			printf("[Vendor Test]:vendor write failed(id=%d)!\n", id);
819 			free(buffer);
820 			return ret;
821 		}
822 	}
823 	/* Read data */
824 	for (id = 0; id < item_num; id++) {
825 		memset(buffer, 0, size);
826 		ret = vendor_storage_read(id, buffer, size);
827 		if (ret < 0) {
828 			printf("[Vendor Test]:vendor read failed(id=%d)!\n", id);
829 			free(buffer);
830 			return ret;
831 		}
832 		/* check data Correctness */
833 		for (j = 0; j < size; j++) {
834 			if (*(buffer + j) != id) {
835 				printf("[Vendor Test]:Unexpected error occurs(id=%d)\n", id);
836 				printf("the data content is:\n");
837 				print_buffer(0, buffer, 1, size, 16);
838 
839 				free(buffer);
840 				return -1;
841 			}
842 		}
843 		debug("\t#id=%03d success,data=0x%02x,size=%d.\n", id, *buffer, size);
844 	}
845 	printf("[Vendor Test]:<All Items Used> Test End,States:OK\n");
846 
847 	printf("[Vendor Test]:<All Items Used> re init,States:OK\n");
848 	ret = vendor_storage_init();
849 	/* Read data */
850 	for (id = 0; id < item_num; id++) {
851 		memset(buffer, 0, size);
852 		ret = vendor_storage_read(id, buffer, size);
853 		if (ret < 0) {
854 			printf("[Vendor Test]:vendor read failed(id=%d)!\n", id);
855 			free(buffer);
856 			return ret;
857 		}
858 		/* check data Correctness */
859 		for (j = 0; j < size; j++) {
860 			if (*(buffer + j) != id) {
861 				printf("[Vendor Test]:Unexpected error occurs(id=%d)\n", id);
862 				printf("the data content is:\n");
863 				print_buffer(0, buffer, 1, size, 16);
864 
865 				free(buffer);
866 				return -1;
867 			}
868 		}
869 		debug("\t#id=%03d success,data=0x%02x,size=%d.\n", id, *buffer, size);
870 	}
871 	printf("[Vendor Test]:<All Items Used> Test End,States:OK\n");
872 #ifdef CONFIG_MTD_BLK
873 	if (bootdev_type == IF_TYPE_MTD)
874 		return 0;
875 #endif
876 	/*
877 	 * SECOND TEST: Overrides the maximum number of items to see if the
878 	 * return value matches the expectation
879 	 */
880 	printf("[Vendor Test]:<Overflow Items Cnt> Test Start...\n");
881 	/* Any id value that was not used before */
882 	id = item_num;
883 	printf("[Vendor Test]:id=%d, size=%d.\n", id, size);
884 	ret = vendor_storage_write(id, buffer, size);
885 	if (ret == -ENOMEM)
886 		printf("[Vendor Test]:<Overflow Items Cnt> Test End,States:OK\n");
887 	else
888 		printf("[Vendor Test]:<Overflow Items Cnt> Test End,States:Failed\n");
889 
890 	/* free buffer, remalloc later */
891 	free(buffer);
892 	buffer = NULL;
893 	/*
894 	 * remalloc memory and recalculate size to test memory overflow
895 	 * (1) item_num > 10: Memory is divided into 10 blocks,
896 	 * 11th memory will overflow.
897 	 * (2) 10 > item_num > 1: Memory is divided into item_num-1
898 	 * blocks. item_num block, memory will overflow.
899 	 * (3) item_num = 1: size = total_size + 512 Bytes, The first
900 	 * block, memory will overflow.
901 	 * The reason to do so is to minimize the size of the memory,
902 	 * making malloc easier to perform successfully.
903 	 */
904 	item_num = (item_num > 10) ? 10 : (item_num - 1);
905 	size = item_num ? (total_size / item_num) : (total_size + 512);
906 	size = (size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN);
907 	/* Find item_num value that can make the memory overflow */
908 	for (id = 0; id <= item_num; id++) {
909 		if (((id + 1) * size) > total_size) {
910 			item_num = id;
911 			break;
912 		}
913 	}
914 	/* malloc */
915 	buffer = (u8 *)malloc(size);
916 	if (buffer == NULL) {
917 		printf("[Vendor Test]:Malloc failed(size=%d)!\n", size);
918 		return -ENOMEM;
919 	}
920 
921 	/* THIRD TEST: Single Item memory overflow test */
922 	printf("[Vendor Test]:<Single Item Memory Overflow> Test Start...\n");
923 	/* The value can be arbitrary */
924 	memset(buffer, 'a', size);
925 	/* Any id value that was used before */
926 	id = 0;
927 	printf("[Vendor Test]:id=%d, size=%d.\n", id, size);
928 	ret = vendor_storage_write(id, buffer, size);
929 	if (ret == size)
930 		printf("[Vendor Test]:<Single Item Memory Overflow> Test End, States:OK\n");
931 	else
932 		printf("[Vendor Test]:<Single Item Memory Overflow> Test End, States:Failed\n");
933 
934 	/* FORTH TEST: Total memory overflow test */
935 	printf("[Vendor Test]:<Total memory overflow> Test Start...\n");
936 	printf("[Vendor Test]:item_num=%d, size=%d.\n", item_num, size);
937 
938 	vendor_test_reset();
939 	for (id = 0; id < item_num; id++) {
940 		memset(buffer, id, size);
941 		ret = vendor_storage_write(id, buffer, size);
942 		if (ret < 0) {
943 			if ((id == item_num) && (ret == -ENOMEM)) {
944 				printf("[Vendor Test]:<Total memory overflow> Test End, States:OK\n");
945 				break;
946 			} else {
947 				printf("[Vendor Test]:<Total memory overflow> Test End, States:Failed\n");
948 				break;
949 			}
950 		}
951 		debug("\t#id=%03d success,data=0x%02x,size=%d.\n", id, *buffer, size);
952 	}
953 
954 	/* Test end */
955 	printf("[Vendor Test]:After Test, Vendor Resetting...\n");
956 	vendor_test_reset();
957 	printf("[Vendor Test]:Test End.\n");
958 	free(buffer);
959 
960 	return 0;
961 }
962